原文首發於 blog.flqin.com。若有錯誤,請聯繫筆者。分析碼字不易,轉載請代表出處,謝謝!html
此係列文章做爲筆記,用於記錄分析 webpack
源碼主流程的過程。node
根據 webpack
構建流程及相關,本系列文章一共分爲如下章節:webpack
webpack
構建流程圖:git
"devDependencies": {
"@babel/core": "^7.7.5",
"@babel/preset-env": "^7.7.6",
"@fe_korey/test-loader": "^1.0.0",
"babel-loader": "^8.0.6",
"html-webpack-plugin": "^3.2.0"
},
"dependencies": {
"webpack": "^4.41.2",
"webpack-cli": "^3.3.10"
}
複製代碼
版本不一樣,源碼略微有差別。github
本項目 demo
開源在github,歡迎交流學習。web
採用 vscode 來打斷點調試分析。npm
//launch.json
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "debug"],
"port": 5858,
"console": "externalTerminal",
"skipFiles": ["<node_internals>/**/*.js"]
}
]
複製代碼
這些配置是怎麼來的?json
"scripts": {
"debug": "node --inspect-brk=5858 ./node_modules/.bin/webpack"
},
複製代碼
webpack
從配置初始化到打包完成定義了一個生命週期,在這個生命週期中的每個階段定義一些不一樣的功能。webpack
的流程一樣也是一個事件驅動的架構,利用插件系統 tabpable
,經過 發佈訂閱事件
來實現全部內部的,外部擴展的功能。bash
webpack
的構建是經過 Compiler
控制構建流程,Compilation
解析,ModuleFactory
生成模塊,Parser
解析源碼,Template
渲染代碼,最後輸出打包後的文件。babel
tabpable
本質就是一個事件發佈訂閱機制,支持同步異步,使用xxx.tap
之類的來事件訂閱,使用xxx.call
之類的來進行事件發佈。 相關文檔查閱:
npm i webpack-cli webpack
npm i @babel/core @babel/preset-env babel-loader -D
npm i @fe_korey/test-loader -D
複製代碼
咱們以 development
模式爲例,暫時忽略支線劇情,只分析探索 webpack
的打包主流程。
//src/a.js
import { add } from 'Src/b';
import('./c.js').then(m => m.sub(2, 1));
const a = 1;
add(3, 2 + a);
複製代碼
//src/b.js
import { mul } from '@fe_korey/test-loader?number=20!Src/e';
export function add(a, b) {
return a + b + mul(10, 5);
}
export function addddd(a, b) {
return a + b * b;
}
複製代碼
//src/c.js
import { mul } from 'Src/d';
import('./b.js').then(m => m.add(200, 100));
export function sub(a, b) {
return a - b + mul(100, 50);
}
複製代碼
//src/d.js
export function mul(a, b) {
const d = 10000;
return a * b + d;
}
複製代碼
//webpack.config.js
var path = require('path');
module.exports = {
entry: {
bundle: './src/a.js'
},
devtool: 'none',
output: {
path: __dirname + '/dist',
filename: '[name].[chunkhash:4].js',
chunkFilename: '[name].[chunkhash:8].js'
},
mode: 'development',
resolve: {
alias: {
Src: path.resolve(__dirname, 'src/')
}
},
module: {
rules: [
{
test: /\.js$/,
use: [
{
loader: 'babel-loader'
}
]
}
]
}
};
複製代碼
//babel.config.js
module.exports = {
presets: ['@babel/env']
};
複製代碼
爲何要閱讀它?
plugin
和 loader
有更深入的理解最重要的仍是想知足本身的好奇欲,想知道在這犀利的打包背後,究竟是怎麼實現的。
webpack
裏包含數不清的變量和鉤子,海量插件,這些足以讓你懷疑人生,請務必保持一顆耐操的心。 一切準備就緒後,進入 vscode
的調試模式!