先上一张流程图,小伙伴可以跟着这个流程图结合代码往下走:
再来一张大神画的图:
图片来源于:细说webpack之流程篇
开始
git clone https://github.com/webpack/webpack.git
yarn
yarn setup
打包
node ./bin/webpack.js
bin/webpack.js
//判断有没有安装webpack-cli,没有话的就提示是否需要安装
const question = `Do you want to install 'webpack-cli' (yes/no): `;
//确定有webpack-cli之后开始执行
require(path.resolve(path.dirname(pkgPath), pkg.bin[cli.binName]));
webpack-cli/bin/cli.js
//创建compiler编译引擎
let compiler;
try {
compiler = webpack(options);
} catch (err) {
}
compiler.run((err, stats) => {}
整个made过程
lib/webpack.js
const webpack = (options, callback) => {
let compiler;
compiler = createCompiler(options);
watch = options.watch;
watchOptions = options.watchOptions || {};
return compiler;
};
//创建编译器
const createCompiler = options => {
//获取默认的webpack参数
options = new WebpackOptionsDefaulter().process(options);
const compiler = new Compiler(options.context);
compiler.options = options;
//配置全局api插件比如(fs文件api、infrastructureLogger日志log、)
new NodeEnvironmentPlugin({
infrastructureLogging: options.infrastructureLogging
}).apply(compiler);
// 执行我们在配置文件中配置的所有插件
if (Array.isArray(options.plugins)) {
for (const plugin of options.plugins) {
if (typeof plugin === "function") {
plugin.call(compiler, compiler);
} else {
plugin.apply(compiler);
}
}
}
//开启默认的所有插件(比较重要)
compiler.options = new WebpackOptionsApply().process(options, compiler);
return compiler;
};
lib/WebpackOptionsApply.js
//设置默认的一些插件
process(options, compiler) {
//入口文件插件注册
new EntryOptionPlugin().apply(compiler);
//调用入口文件插件注册钩子函数
compiler.hooks.entryOption.call(options.context, options.entry);
}
lib/EntryOptionPlugin.js
module.exports = class EntryOptionPlugin {
/**
* @param {Compiler} compiler the compiler instance one is tapping into
* @returns {void}
*/
apply(compiler) {
//注册入口文件插件注册钩子函数
compiler.hooks.entryOption.tap("EntryOptionPlugin", (context, entry) => {
const applyEntryPlugins = (entry, name) => {
if (typeof entry === "string") {
//调用入口插件
new EntryPlugin(context, entry, name).apply(compiler);
} else if (Array.isArray(entry)) {
for (const item of entry) {
applyEntryPlugins(item, name);
}
}
};
//options的entry支持string||array比如:(entry: "src/main.js")||(entry: ["pollyfill.js","src/main.js"])
if (typeof entry === "string" || Array.isArray(entry)) {
applyEntryPlugins(entry, "main");
//options的entry支持object类型比如:(entry:{main: "src/main.js"})
} else if (typeof entry === "object") {
for (const name of Object.keys(entry)) {
applyEntryPlugins(entry[name], name);
}
//options的entry支持function类型比如:(entry:()=>"src/main.js")})
} else if (typeof entry === "function") {
new DynamicEntryPlugin(context, entry).apply(compiler);
}
return true;
});
}
};
EntryPlugin.js
apply(compiler) {