Webpack 的 Chunk,想怎么分就怎么分

想必大家都用过 webpack,也或多或少了解它的原理,但是不知道大家有没有写过 Webpack 的插件呢?

今天我们就一起来写一个划分 Chunk 的 webpack 插件吧,写完后你会发现想怎么分 Chunk 都可以!

首先我们简单了解下 webpack 的原理:

webpack 的原理

webpack 是一个打包工具(bundler),它打包的是什么呢?

模块。

那模块能再拆分么?

不能了,模块是 webpack 处理的基本单位了,只是对模块做一些打包。

那怎么对模块打包呢?

首先要找到所有的模块(Module),从入口模块开始,分析依赖,构成一个图,叫做模块依赖图(ModuleGraph)。

然后模块要分成几个包,要有一种中间结构来保存这种划分,叫做 Chunk。把不同的模块放到不同的 Chunk 里就完成了分包。

但是 Chunk 只是一种中间结构,还要再变成可用的目标代码。通过代码模版把它打印成代码就可以了。

这三步分别叫 make、seal、emit。

make 这一步就是构建模块依赖图 ModuleGraph 的,这个过程中会从入口模块(EntryPoint)开始递归解析依赖,对解析出的每个模块做处理,也就是调用注册的 loader。

然后 Seal 也就是封装的意思,把不同的 Module 分到不同的 Chunk 里。

这一步会先做基础的 Chunk 划分,比如入口模块 EntryPoint 肯定要单独放到 Chunk 里,动态引入的模块肯定也要单独放到 Chunk 里。

完成了基础的划分之后,可以再对这些 Chunk 做进一步的优化划分,比如根据 Chunk 大小等来划分。

分完之后,ModuleGrapqh 就变成了 ChunkGraph。

最后 emit 阶段就是通过模版打印代码了。

这三步合起来就是一次编译过程 Compilation。

编译过程由 webpack 的 Compiler 调用。

整个过程中还会暴露出很多扩展点,也就是留给插件的 hook,不同阶段的 hook 自然就可以拿到不同阶段的资源。

这些插件都是保存在对象上的:

比如 compiler 的 hook:

compilation 的 hook:

那插件里自然就是往不同对象的 hook 上添加回调函数:

而且 webpack 为了控制 hook 的执行顺序,封装了一个 tappable 的包。可以指定 hook 是同步、异步,并行、串行执行。

比如这几种 hook:

SynHook 就是同步顺序执行。

AsyncSeriesHook 就是异步串行执行。

SyncBailHook 也是同步顺序执行,但是如果中间的 hook 返回 false 就会停止后续 hook 的执行,也就是可以熔断。

理解了 webpack 的编译流程,hook 的运行机制,接下来我们就写个插件来操作下 Chunk 吧:

操作 Chunk 的 webpack 插件

前面讲过,webpack 会对 Module 根据是否是入口模块、是否是异步引入的模块做基础的 Chunk 划分。

之后会进一步做优化的 Chunk 划分。

这些 chunk 相关的逻辑都是在 seal 那一步做的。

我们在源码里看到的也确实是这样:

在 seal 里做了 ChunkGraph 的创建,然后调用 optimizeChunks 的 hook 对 Chunks 做处理。

这里为啥是个死循环呢?

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值