循环依赖导致模块导出为空对象
const fn = lazyFunction(() => require("./webpack")); // lib\index.js 128
初看可能不会将它和解决循环依赖导致的导出模块为空对象联系在一起,不过你可以试着这样子修改这行代码
const fn = require("./webpack");
然后重新启动debugger,你会发现一个报错,说webpack.ProvidePlugin is not a constructor
然后我们跟着这个compiler溯源发现,这里的compiler.webpack到赋值处

Compiler.js文件中的webpack值来源于导入
const webpack = require("."); //lib\Compiler.js 17, 解释一下这里的.导入的是./index.js文件
我们的index.js中存在这行代码
get Compiler() {
return require("./Compiler");
}, // lib\index.js 189-191
从这里我们可以看出 index.js 导入了 Compiler.js。然后Compiler.js又导入了index.js。这样子就产生了循环依赖。循环依赖会导致模块还没加载完成,从而导致了导出的是空对象的情况。
模块导入收集以及构建缓存
该文章的开始构建部分中我们了解到了构建过程中的函数调用,对于当前模块导入的依赖进行分析,然后递归出链式的导入依赖,从this._processModuleDependencies (任务队列调用-模块依赖)调用开始
_processModuleDependencies() {
// ...其它逻辑
this.handleModuleCreation() // 递归的开始,Entry逻辑中编译部分亦是通过这个方法。
} // lib\Compilation.js 1593-1873
可以在这部分代码中看到sortedDependencies,这个变量用来收集上一个模块中的dependencies(模块依赖数组),这个数组的产生一定离不开对于当前模块解析。
承接上篇文章的编译部分,build之后的ast处理逻辑以及dep收集
当前模块解析模块依赖逻辑
└── module.build (模块对应的解析处理实例, 大多数是NormalModule,lib\NormalModule.js)
└── (this.parser).parse (_.doBuild最后的入参,一个回调函数 1357行. (this.parser),这里的parser是当前实例的属性值,是在链式执行中通过发布订阅赋予的值, javascript/esm 对应 JavascriptParser.apply中发布方法产生的返回值)
└── JavascriptParser._parse
└── acorn.parse (三方库acorn)

下面是借助acorn.parse分析简单字符串的输出,可以看出esm的导入type是"ImportDeclaration",表达式声明的type是"ExpressionStatement"。由此可以区分出当前模块依赖的模块是哪些,然后通过后续的逻辑启用递归。

依赖资源文件路径解析
像webpack包括vite都可以通过配置alias来做到避免在项目中因使用相对路径而导致的文件路径过程或者过乱的问题。比如 …/…/…/…/utils/index.js可以通过alias转换成@/utils/index.js,@代表者一个目录的根路径。既然可以这样子写,那webpack就必然需要对这种写法进行处理,以保证获取正确的文件位置。
在webpack中,借助enhanced-resolve库来实现对与资源路径的正确解析。

模块的分割打包机制
先看下webpack分割打包配置的配置项
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/, // 将正则匹配包括node_modules的文件资源打包成一个文件
name: 'commons',
minSize: 20000, // chunk文件大小小于20kb则不会单独拆分,而是打包到一个文件当中
}
}
}
},
从打包产物来看,webpack会将目标资源文件整合到一起,当整合资源文件超过minSize的时候便会产生一个独立的chunk。下面是webpack的源码

当result中收集的同一个chunk的资源文件大小超过设置的minSize的时候,就会单独生成一个或者多个chunk作为打包资源的产物
目标文件 lib\optimize\SplitChunksPlugin.js
后续补充,从分割chunk到打包chunk,到依赖当前chunk的执行文件的运行时引用是怎么实现的。
1725

被折叠的 条评论
为什么被折叠?



