在研究WEBPACK 源码时想了些什么,首先想到的是阅读每一个文件,再查过查资料改变了一些想法,可以通过阅读webpack 的四个大部分,例:入口,加载器,插件,输出。
webpack 入口
- webpack 大约有以下几种
// 第一种
entry: "***.js"
// 第二种
entry: ["**.js"]
// 第三种
entry: async () => {
// 这里面可以加载JS文件实现异步操作
return "***.js"
}
在阅读源码时可以参照以上的方式进行webpack 运行逻辑整理
webpack 加载器
- webpack css-loader 加载器
// 加载器配置示例
{
// 静态CSS加载
test: /\.css$/i,
use: [{ loader: MiniCssExtractPlugin.loader, options: { publicPath: './' } }, 'css-loader', 'postcss-loader'],// 'clear-print',
}
// 加载器示例
module.exports = function(/** @type {string} */ source){
source = source.replace(/console.log\([^)]+[\)];?/,'')
return source;
}
以上示例中介绍了 .css 加载器的用法,在加载器中会对所有的 导入的.css 进行读取,然后在加载器中进行逻辑处理,最后将处理后的字符串返回给 webpack 使用。 以上就是加载器的基本原理
webpack 插件(plus)
- webpack 与加载器类型
class ClearPrint {
/**
* @param {any} doneCallback
* @param {any} failCallback
*/
constructor(doneCallback, failCallback){
this.doneCallback = doneCallback;
}
/**
* @param {{ hooks: { emit: { tapAsync: (arg0: string, arg1: (compilation: any, callback: any) => void) => void; }; }; }} compiler
*/
apply(compiler){
compiler.hooks.emit.tapAsync('ClearPrint',(/** @type {{ assets: { [x: string]: { _value: any; }; }; }} */ compilation,/** @type {() => void} */ callback)=>{
for(let key in compilation.assets){
let str = compilation.assets[key]._value;
compilation.assets[key]._value = str.replace(/console.log\([^)]+[\)];?/,'');
}
callback();
// @ts-ignore
this.doneCallback && this.doneCallback()
})
}
}
module.exports = ClearPrint;
与加载器不同的是 插件(plus) 能够在webpack 运行的各个介阶定义勾子,如上例所示,插件监听的是
emit钩子,它在 Webpack 生成文件并写入output目录 之前执行
webpack 输出
- webpack 中输出可以插件定义输入也能通过 output 定义输入,主入口文件的输出只能由 output 定义
output: {
filename: '**.js',
path: path.resolve(basePath, "web"),
publicPath: "/",
chunkFilename: "**.js",
clean: true,
},
上例中定义了输出主入口文件的名称输出路径,默认输出路和戏,检出文件名,以及打包是否清除原目录文件。
上面介绍了webpack 中的四个大部分,在源码研究中会陆续输入,webpack 优化,以及对webpack 功能进行增改,例优化hot 功能,定义复杂一些的插件。