合并配置项
实例化Compiler
加载所有插件
runWebpack() // webpack-cli/lib/webpack-cli.js
createCompiler() // webpack-cli/lib/webpack-cli.js
webpack() // webpack/lib/webpack.js
create() //webpack/lib/webpack.js
var compiler = createCompiler(webpackOptions) // webpack/lib/webpack.js
const createCompiler = rawOptions => {
// 合并配置项,即将在webpack.config.js中配置的和webpack自带的配置合并
const options = getNormalizeWebpackOptions(rawOptions)
// 实例化compiler
const compiler = new Compiler(options.context, options)
// 遍历插件,执行插件的apply()方法
if(Array.isArray(options.plugins)){
for(const plugin of options.plugins) {
if(typeof plugin === "function"){
plugin.call(compiler, compiler)
}else{
plugin.apply(compiler)
}
}
}
// 实例化WebpackOptionsApply,并执行它的process()方法
new WebpackOptionsApply().process(options, compiler)
return compiler
}
加载 入口插件EntryPlugin
// 调用WebpackOptionsApply
//此处的options是我们在webpack.config.js中配置的内容
new WebpackOptionsApply().process(options, compiler) // webpack/lib/webpack.js
// 调用EntryOptionPlugin插件
process(){ // webpack/lib/WebpackOptionsApply.js
...
new EntryOptionPlugin().apply(compiler)
compiler.hooks.entryOption.call(options.context, options.entry)
...
}
// EntryOptionsPlugin插件的apply方法
apply(compiler){
compiler.hooks.entryOption.tap("EntryOptionPlugin", (context, entry) => {
EntryOptionPlugin.applyEntryOption(compiler, context, entry)
return true
})
}
// applyEntryOption是EntryOptionPlugin类的静态方法
static applyEntryOption(compiler, context, entry){
if(typeof entry === "function"){
}else{
const EntryPlugin = require("./EntryPlugin");
// 遍历入口对象的key
for(const name of Object.keys(entry)){
const desc = entry[name]
...
for(const entry of desc.import){
new EntryPlugin(context, entry, options).apply(compiler)
}
}
}
}
// webpack/lib/EntryPlugin.js
// 在EntryPlugin插件的apply()方法中我们调用了compiler的make钩子
// make钩子: compilation结束之前执行
apply(compiler){
...
const { entry, options, context } = this
...
compiler.hooks.make.tapAsync("EntryPlugin", (compilation, callback) => {
})
}
实例化Compilation, 根据入口的数量,1次或多次调用该实例对象的addEntry()方法, addEntry()主要是将entry放入到AsyncQueue中
compiler.run() //webpack/lib/Compiler.js
compiler.compile() //webpack/lib/Compiler.js
compiler.newCompilationParams() //webpack/lib/Compiler.js
compiler.createNormalModuleFactory() //webpack/lib/Compiler.js
const normalModuleFactory = new NormalModuleFactory()
// constructor() //构造函数,webpack/lib/NormalModuleFactory.js
const compilation = compiler.newCompilation() //webpack/lib/Compiler.js
// 调用compiler.hooks.make.callAsync即是执行compiler.hooks.make.tapAsync
// compiler.hooks.make.callAsync只会执行一次
// compiler.hooks.make.tapAsync 内部执行次数 等于 入口的个数
compiler.hooks.make.callAsync(compilation, err=>{}) //webpack/lib/Compiler.js
compiler.hooks.make.tapAsync("EntryPlugin", (compilation, callback)=>{ })
// webpack/lib/EntryPlugin.js
// 以下是EntryPlugin插件apply()方法中
apply(compiler){
...
const { entry, options, context } = this
...
compiler.hooks.make.tapAsync("EntryPlugin", (compilation, callback) => {
// 有n个入口,这里就会被执行n次
compilation.addEntry(context, dep, options, err => {
callback(err)
})
})
}
简化版
class Compilation {
constructor(){
}
addEntry(entry){
console.log(entry)
}
}
const compilation = new Compilation()
compilation.addEntry('app.js')
compilation.addEntry('search.js')
实例化一个异步队列(AsyncQueue),存储一个entry; 多个entry对应多个异步队列
//webpack/lib/Compiler.js
compilation.addEntry()
compilation._addEntryItem() //webpack/lib/Compilation.js
compilation.addModuleTree() // webpack/lib/Compilation.js
compilation.handleModuleCreation() // webpack/lib/Compilation.js
compilation.factorizeModule() //webpack/lib/Compilation.js
compilation.prototype.factorizeQueue = new AsyncQueue({}) //webpack/lib/Compilation.js
Compilation.factorizeQueue.add() //webpack/lib/Compilation.js
AsyncQueue.add() //webpack/lib/util/AsyncQueue.js
宏任务执行AsyncQueue的_ensureProcessing()方法,该方法内会遍历前面加入到AsyncAueue中的所有entry,做后续操作,未完待续,期待下期的 webpack运行过程(2)
// 在执行宏任务之前会将多个entry加入到AsyncQueue的_children中
// 宏任务执行root._ensureProcessing
setImmediate(root._ensureProcessing)
_ensureProcessing() //webpack/lib/util/AsyncQueue.js
// 这里的_children可以理解为多个入口
// 遍历多个入口
for(const child of this._children){
// _parallelism为并发数
while(this._activeTasks < this._parallelism){
const entry = child._queued.dequeue();
if(entry === undefined) break;
this._activeTasks++
entry.state = PROCESSING_STATE
child._startProcessing(entry)
}
}
_startProcessing() //webpack/lib/util/AsyncQueue.js
上述简化版实现
class Compilation {
constructor(){
}
addEntry(entry){
const asyncAueue = new AsyncQueue()
asyncAueue.add(entry)
}
}
class AsyncQueue{
constructor(){
this.list = []
}
add(entry){
this.list.push(entry)
// 这里要使用bind指定this,不然this会执行执行调用者setImmediate
setImmediate(this._ensureProcessing.bind(this))
}
_ensureProcessing(){
for (let index = 0; index < this.list.length; index++) {
const entry = this.list[index];
this._startProcessing(entry)
}
}
_startProcessing(entry){
console.log(entry)
}
}
const compilation = new Compilation()
compilation.addEntry('app.js')
compilation.addEntry('search.js')
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!