调试webpack过程理解执行流程
开始-合并配置------------实例化compile-------设置node文件读写能力-----通过循环挂载plugins-----解决webpack外部默认的插件(入口文件)
开始-compiler.beforeRun-compiler.run--------compiler.beforeCompile-compiler.compile-------compile.make
在Compiler
类中,构造函数内会挂载大量的钩子,这些钩子都来自tapable
,挂载之后在后续的操作中,这些钩子期待被触发执行。
this.hooks = {
/** @type {SyncBailHook<Compilation>} */
shouldEmit: new SyncBailHook(["compilation"]),
/** @type {AsyncSeriesHook<Stats>} */
done: new AsyncSeriesHook(["stats"]),
/** @type {AsyncSeriesHook<>} */
additionalPass: new AsyncSeriesHook([]),
/** @type {AsyncSeriesHook<Compiler>} */
beforeRun: new AsyncSeriesHook(["compiler"]),
/** @type {AsyncSeriesHook<Compiler>} */
run: new AsyncSeriesHook(["compiler"]),
/** @type {AsyncSeriesHook<Compilation>} */
emit: new AsyncSeriesHook(["compilation"]),
/** @type {AsyncSeriesHook<string, Buffer>} */
assetEmitted: new AsyncSeriesHook(["file", "content"]),
/** @type {AsyncSeriesHook<Compilation>} */
afterEmit: new AsyncSeriesHook(["compilation"]),
/** @type {SyncHook<Compilation, CompilationParams>} */
thisCompilation: new SyncHook(["compilation", "params"]),
/** @type {SyncHook<Compilation, CompilationParams>} */
compilation: new SyncHook(["compilation", "params"]),
/** @type {SyncHook<NormalModuleFactory>} */
normalModuleFactory: new SyncHook(["normalModuleFactory"]),
/** @type {SyncHook<ContextModuleFactory>} */
contextModuleFactory: new SyncHook(["contextModulefactory"]),
/** @type {AsyncSeriesHook<CompilationParams>} */
beforeCompile: new AsyncSeriesHook(["params"]),
/** @type {SyncHook<CompilationParams>} */
compile: new SyncHook(["params"]),
/** @type {AsyncParallelHook<Compilation>} */
make: new AsyncParallelHook(["compilation"]),
/** @type {AsyncSeriesHook<Compilation>} */
afterCompile: new AsyncSeriesHook(["compilation"]),
/** @type {AsyncSeriesHook<Compiler>} */
watchRun: new AsyncSeriesHook(["compiler"]),
/** @type {SyncHook<Error>} */
failed: new SyncHook(["error"]),
/** @type {SyncHook<string, string>} */
invalid: new SyncHook(["filename", "changeTime"]),
/** @type {SyncHook} */
watchClose: new SyncHook([]),
/** @type {SyncBailHook<string, string, any[]>} */
infrastructureLog: new SyncBailHook(["origin", "type", "args"]),
// TODO the following hooks are weirdly located here
// TODO move them for webpack 5
/** @type {SyncHook} */
environment: new SyncHook([]),
/** @type {SyncHook} */
afterEnvironment: new SyncHook([]),
/** @type {SyncHook<Compiler>} */
afterPlugins: new SyncHook(["compiler"]),
/** @type {SyncHook<Compiler>} */
afterResolvers: new SyncHook(["compiler"]),
/** @type {SyncBailHook<string, Entry>} */
entryOption: new SyncBailHook(["context", "entry"])
};
实现迷你版webpack临时不须要这么多钩子.
文件目录构造,lib文件夹下package.json中 "main": "./lib/webpack.js",
NodeEnvironmentPlugin.js
文件次要给compiler挂载node读写文件性能
const fs = require('fs')
class NodeEnvironmentPlugin {
constructor(options) {
this.options = options || {}
}
apply(complier) {
// 源码中还有解决日志的性能,这里暂不须要,这里只须要使compiler具备文件读写能力即可
complier.inputFileSystem = fs
complier.outputFileSystem = fs
}
}
module.exports = NodeEnvironmentPlugin
Compiler.js
文件实现compiler实例化,挂载钩子,实现run
办法。
const {
Tapable,
AsyncSeriesHook
} = require('tapable')
class Compiler extends Tapable {
constructor(context) {
super()
this.context = context
// 源码中的钩子会有很多
this.hooks = {
done: new AsyncSeriesHook(["stats"])
}
}
run(callback) {
callback(null, {
toJson() {
return {
entries: [], // 以后打包入口信息
chunks: [], // 以后打包代码块信息
modules: [], // 模块信息
assets: [], // 打包生成的资源
}
}
})
}
}
module.exports = Compiler
webpack.js
实现webpack流程次要步骤
const Compiler = require("./Compiler")
const NodeEnvironmentPlugin = require('./node/NodeEnvironmentPlugin')
const webpack = function (options) {
// 实例化 compiler 对象
let compiler = new Compiler(options.context)
compiler.options = options
// 初始化 NodeEnvironmentPlugin(让compiler具体文件读写能力)
new NodeEnvironmentPlugin().apply(compiler)
// 挂载所有 plugins 插件至 compiler 对象身上
if (options.plugins && Array.isArray(options.plugins)) {
for (const plugin of options.plugins) {
plugin.apply(compiler)
}
}
// 挂载所有 webpack 内置的插件(入口)
// 最初返回
return compiler
}
module.exports = webpack
测试代码
let webpack = require('./myPack')
let options = require('./webpack.config.js')
let complier = webpack(options)
complier.run((err, stats) => {
console.log(err)
console.log(stats.toJson({
entries: true,
chunks: false,
modules: false,
assets: false
}))
})
运行后打印
{ entries: [], chunks: [], modules: [], assets: [] }
发表回复