webpack 源码解析
首先我们上 github 上面 clone 一份源码,我这里 clone 的是 4.30 版本的 webpack 源码
git clone https://github.com/webpack/webpack.git
起步
- 首先,看一个源码的初始步骤就是打开 package.json 找到它的入口文件
"main": "lib/webpack.js",
- 确定了 webpack.js 文件,我们就可以开始代码阅读了.
webpack.js
- 一开始我们可以分析一下它的结构
可以看出
webpack.js
主要用于导出一些默认的 plugin 与工具函数.其中我们发现exports = module.exports = webpack
默认导出的就是webpack
函数,这个函数也就是我们平时执行时所使用的.我们来看一下它的源码.
/**
* @param {WebpackOptions} options options object
* @param {function(Error=, Stats=): void=} callback callback
* @returns {Compiler | MultiCompiler} the compiler object
*/
/**
* 从参数列表中,我们可以看出, webpack 主要携带两个参数,即一个是 webpack 的配置
* 另一个则是 webpack 执行结束之后的回调, 因为是 node 程序,所以 webpack 参照了一些 node 函数的使用方法
* 第一个参数是 err 信息, 这是因为 node 主要是异步的,异常不能正常捕获,所以这么设计
*/
const webpack = (options, callback) => {
// 根据设定好的 validate 来对 options 进行校验,如果有异常,那么就终止程序并抛出异常
const webpackOptionsValidationErrors = validateSchema(
webpackOptionsSchema,
options
)
if (webpackOptionsValidationErrors.length) {
throw new WebpackOptionsValidationError(webpackOptionsValidationErrors)
}
// 初始化编译器,其实 webpack 打包也就是一个编译器,把我们的代码,转换成打包后的目标代码
// 接受两种类型的参数,一个是 Array<Object:options> 型 , 另一种是 Object:options 型
// 如果不是指定的参数类型,那么就会招出参数异常
let compiler
if (Array.isArray(options)) {
// 如果 options 是 Array<Object:options> ,那么就在可以在单个 compiler 中执行多个配置
compiler = new MultiCompiler(options.map(options => webpack(options)))
} else if (typeof options === 'object') {
// 如果 options 是 Object:options 的话,也就是通常使用的模式
// Array<Object:options> 其实是对每个配置来执行本步骤
//将用户自定义的配置信息与默认信息进行 minix
options = new WebpackOptionsDefaulter().process(options)
// 根据配置信息,初始化webpack编辑器对象,并把配置信息配置给它
compiler = new Compiler(options.context)
compiler.options = options
// 注册 NodeEnvironmentPlugin node 环境插件,并用其为 compiler 添加一些环境信息
new NodeEnvironmentPlugin().apply(compiler)
// 把用户注册的插件挂载到 compiler 上
if (options.plugins && Array.isArray(options.plugins)) {
for (const plugin of options.plugins) {
if (typeof plugin === 'function') {
plugin.call(compiler