背景: 由于一些业务原因,我们的一个项目由20-30个前端维护。并且这些人不属于同一个组,这就给项目管理带来一些问题 最常见的问题就是 1. 有业务需求的A同学随意引入一个 npm包, 有业务需求的B同学也随意引入一个 npm包,两个npm包之间功能都差不多,但是引入两个包,造成打包的体积肯定较大。(影响 FP FCP FID 巴拉巴拉。。。。)
如何解决
- 写一个 babel plugin,在编译项目代码的时候检测编译的路径,匹配到不允许引入的 npm包,直接退出当前编译
- 写一个 webpack plugin,在编译阶段检测编译的路径,匹配到不允许引入的 npm包,直接退出当前编译
- 写一个 pre-commit 脚本,匹配到不允许引入的 npm包,直接禁止提交
方案2 实现: 代码实现
GitHub地址:github.com/webgzh90724…
代码解析
- webpack plugin 本质上属于一种类似发布订阅模式,在 webpack 启动阶段,循环 webpack配置的 plugins 数组,执行每一个plugin对象的 apply 方法,或者直接执行当前方法。(面试题1: webpack.config.js 里面的 plugins 数组的每一项一定要是一个通过 new Class出来的嘛? 答: plugin 不一定要是一个对象,new Plugin 会产生一个对象,也可以直接传入一个函数,此函数执行阶段也会传入compiler)
-
拿到 compiler.context 和传入的需要被禁止引入的 npm 包数组(errorWithImportPackageList)
-
判断没有传入errorWithImportPackageList, 直接 return (面试题2: 此处 plugin 里面 return了,会影响后续其他plugin 执行吗?答: 不会影响,这里的 return 只是 跳出当前 plugin 的 apply 方法。注意 return 的位置不能影响 plugin 的 cb 的执行,此处对应的是 36 行代码)
-
compiler.hooks.emit.tapAsync 含义是 在 compiler对象上 挂载了一个 hooks 对象,此 hooks 对象上存在多个 webpack 构建的 钩子 (done, emit, beforeRun, compile, afterCompiler, make) ,这些钩子函数有同步 也有异步,具体查看文档。
-
compilation.chunks 含义是: 在 compilation 对象上有一个 chunks 数组,此数组是 webpack 编译完成阶段,每一个 chunk 的 抽象被 push 到 chunks这个数组当中 (chunk、module、bundle 是 webapck 核心的概念, module: 万物皆是 module, chunk: 拆分出来的一个 chunk对象,通过 new Chunk 实现。可以理解为 代码块,由 entries 演变而来。 bundle: 由 chunk 进行压缩之后的产物)
-
chunk.getModules() 含义是: 包含在当前 chunk 中的 module 组成的一个数组 (可以拿到当前 chunk 的每个组成的 module)
-
module?.buildInfo?.fileDependencies 每个模块的依赖的 module 的 路径数组