npm link和webpack流程

时间:2022-07-24
本文章向大家介绍npm link和webpack流程,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

最近在学习webpack的流程,因为很多都问过webpack的流程,随便不知道问的人知不知道,自己还是想去了解一下。说webpack流程之前先说一下npm link,方便调试npm包的小技巧。

我们先初始化一个项目,我这边是wadepack:npm init -y,然后在package.json里面配置bin:

bin对应的路径可以随便,只要是能找到这个js就可以,这个js里面代码:

#! /usr/bin/env node(固定的,指定用node去执行)

console.log('wadepack')(随便写点代码)

然后初始化另外一个项目demo,要先安装webpack和webpack-cli,接着在wadepack项目下执行npm link,结果:

npm link 将当前目录临时放到全局,指向wadepaxk.js,然后可以在npm的目录下找到wadepaxk.cmd,node_modules下也有wadepack文件。

回到demo项目,执行npm link wadepack,这时候这个项目就把我们写的wadepack链接到这个项目下,可以在node_modules下看见wadepack这个文件夹,接着执行npx wadepack:

可以执行。这就是npm link的使用,方便调试你的npm包。如果demo项目不用了要解绑可以用npm unlink wadepack,但是我发现执行之后,原来的依赖会有一些问题,就是node_nodules里面好像被删除了,需要删除这文件夹重新初始化。如果要全局移除就在wadepack下执行npm unlink就可以。

接着说webpack大概流程,通过配置文件找到入口文件,解析入口文件生成ast语法树,ast语法树有个字段name判断语法是否是require,大概是下面这样(删除了很多其他字段):

Node {
  callee: Node {
    name: 'require'
  },
  ]
}

如果有新的依赖先放入一个依赖数组dependencies(引入地址):

[ './src\a.js', './src\b.js' ]
[]
[]

然后循环dependencies继续解析成ast,继续判断是否有依赖,递归把所有的依赖都找到。期间需要用path解析拼接地址,用fs读取文件内容:

fs.readFileSync(modulePath, 'utf-8');

这期间,获取到文件内容之后要获取配置文件的loader,看是否有rules数组,通过配置的正则test(/.js/)判断当前内容的引入地址modulePath是否是以这个test为结尾,然后倒叙的把内容传递到loader里面处理:

let content = fs.readFileSync(modulePath, 'utf-8');
let rules = this.config.module.rules;
if(Array.isArray(rules)){
    for (let i = 0; i < rules.length; i++) {
        let rule = rules[i];
        let {test, use} = rule;
        let len = use.length - 1;
        if(test.test(modulePath)){
            function normalLoader() {
                let loader = require(use[len - 1]);
                content = loader(content);
                if(len >= 0){
                    normalLoader();
                }
            }
            normalLoader();
        }
    }
}
return content;

loader之前有分享过大概怎么手写,所以就很清楚这边为什么这样执行了。

把每个文件的内容都缓存到modules对象,key就是每个引入依赖的地址:

this.modules[moduleName] = sourceCode;

当递归把所有依赖解析出来之后,把内容写入配置文件的出口地址和文件名,这边直接写是不对的,如果找不到文件夹和文件会报错,我是提前建好文件和文件夹。

fs.writeFileSync(output, code);

插件的注入更简单了,只要在不同过程调用tapable的回调就可以了,比如在编译之前和文件发射之后:

this.hooks.compile.call();
this.buildModule(path.resolve(this.root, this.entry), true);
this.hooks.afterCompile.call();
this.emitFile();
this.hooks.emit.call();
this.hooks.done.call();

hooks在constructor的时候就声明了,之前分享怎么手写插件,所以这个应该也不难理解。

随便看看,自己也只是理解到这种程度,比较重要的其实是知道解析成ast之后怎么递归加载依赖,然后loader怎么注入的,至于插件的注入,知道了tapable应该不难理解,就是发布订阅,然后在不同运行阶段调用。

可以使用npm link调试自己手写一个简易的webpack打包过程,网上还蛮多的,运行一遍对这个流程就挺好理解的了。

(完)