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打包过程,网上还蛮多的,运行一遍对这个流程就挺好理解的了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值