- webpack-cli啟動(dòng)打包流程
通過convert-argv(node的yargs模塊)獲取命令行得到運(yùn)行配置瞒渠,然后與webpack配置文件整合;
webpack4 cli獨(dú)立到webpack-cli模塊厅篓,增強(qiáng)靈活性包券,讓webpack的調(diào)用更便捷; - 載入weback核心模塊/代碼,創(chuàng)建compiler
創(chuàng)建工作周期hook, 通過make.top() 注冊(cè)默認(rèn)內(nèi)置的插件(toptabel方法)
- 使用compiler對(duì)象編譯整個(gè)項(xiàng)目
創(chuàng)建compilation對(duì)象存放模塊資源窗价,同時(shí)創(chuàng)建buildModule方法
通過buildModule方法執(zhí)行l(wèi)oader對(duì)特殊的文件進(jìn)行處理 - 從入口文件開始解析各個(gè)模塊間的依賴,形成依賴樹
buildModule后,通過acorn庫(kù)生成模塊間的AST
語法樹恨憎,找到各模塊間的依賴 - 遞歸依賴樹,將每個(gè)模塊交給對(duì)應(yīng)的loader處理
- 合并loader處理的結(jié)果郊楣,打包到目標(biāo)disk/自定義文件
webpack-cli部分源碼解析
通過yargs去解析命令行參數(shù).
yargs.parse(process.argv.slice(2), (err, argv, output) => {...}
將命令行參數(shù)解析為配置參數(shù)對(duì)象.
options = require("./utils/convert-argv")(argv);
// convert-argv.js
if (argv.config) { /** 判斷是否有指定默認(rèn)配置文件 **/
const getConfigExtension = function getConfigExtension(configPath) {...} else {
// 按配置文件規(guī)則查找文件
const defaultConfigFileNames = ["webpack.config", "webpackfile"].join("|");
const webpackConfigFileRegExp = `(${defaultConfigFileNames})(${extensions.join("|")})`;
const pathToWebpackConfig = findup(webpackConfigFileRegExp);
.............................
// 入口文件
compiler = webpack(options);
option可以是對(duì)象或者數(shù)組憔恳,數(shù)組即可以多路打包
//
期間plugin通過compiler訪問各個(gè)環(huán)節(jié),做額外的工作處理净蚤;
常用plugin如:
1.打包后文件壓縮[ uglifyjs-webpack-plugin ]
- 定義html文件輸出[ html-webpack-plugin ]
- 清空打包前的文件[ clean-webpack-plugin ]
- 靜態(tài)拷貝的文件定義 [copy-webpack-plugin]
- 熱更新[HotModuleReplacementPlugin]
................
自定義清除注釋的plugin
webpack生命周期
- complie開始編譯
- make分析入口模塊創(chuàng)建對(duì)象
- bind-module構(gòu)建模塊
- after-complie完成模塊構(gòu)建結(jié)束編譯
- emit compilers開始輸出生成的assets文件钥组,插件最后的機(jī)會(huì)修改assets
- after-emit 輸出完成
calss RemoveCommentsPlugin {
apply(compiler) {
compiler.hooks.emit.tap('RemoveCommentsPlugin', compilation => {
for(const name in compilation.assets) {
if(name.endsWith(".js")){
const content = compilation.assets[name].source();
compilation.assets[name] = {
source: () => content.replace('/\/\/*{2,}\/\s/g', ''),
length: () => content.replace('/\/\/*{2,}\/\s/g', '').length,
}
}
}
})
}
}