插件向第三方开发者提供了 webpack 引擎中完整的能力。使用阶段式的构建回调,开发者可以引入它们自己的行为到 webpack 构建流程中。创建插件比创建 loader 更加高级,因为你将需要理解一些 webpack 底层的内部特性来做相应的钩子
对象 | 钩子 |
---|---|
Compiler | run,compile,compilation,make,emit,done |
Compilation | buildModule,normalModuleLoader,succeedModule,finishModules,seal,optimize,after-seal |
Module Factory | beforeResolver,afterResolver,module,parser |
Module | |
Parser | program,statement,call,expression |
Template | hash,bootstrap,localVars,render |
class DonePlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
}
}
module.exports = DonePlugin;
在插件开发中最重要的两个资源就是compiler
和compilation
对象。理解它们的角色是扩展 webpack 引擎重要的第一步。
compiler 对象代表了完整的 webpack 环境配置。这个对象在启动 webpack 时被一次性建立,并配置好所有可操作的设置,包括 options,loader 和 plugin。当在 webpack 环境中应用一个插件时,插件将收到此 compiler 对象的引用。可以使用它来访问 webpack 的主环境。
compilation 对象代表了一次资源版本构建。当运行 webpack 开发环境中间件时,每当检测到一个文件变化,就会创建一个新的 compilation,从而生成一组新的编译资源。一个 compilation 对象表现了当前的模块资源、编译生成资源、变化的文件、以及被跟踪依赖的状态信息。compilation 对象也提供了很多关键时机的回调,以供插件做自定义处理时选择使用。
if (options.plugins && Array.isArray(options.plugins)) {
for (const plugin of options.plugins) {
plugin.apply(compiler);
}
}
class DonePlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
compiler.hooks.done.tap("DonePlugin", (stats) => {
console.log("Hello ", this.options.name);
});
}
}
module.exports = DonePlugin;
class DonePlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
compiler.hooks.done.tapAsync("DonePlugin", (stats, callback) => {
console.log("Hello ", this.options.name);
callback();
});
}
}
module.exports = DonePlugin;
const DonePlugin = require("./plugins/DonePlugin");
module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve("build"),
filename: "bundle.js",
},
plugins: [new DonePlugin({ name: "zhufeng" })],
};
plugins\webpack-assets-plugin.js
//编写个Compilation插件,用来打印本次产出的代码块和文件
class WebpackAssetsPlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
//每当webpack开启一次新的编译 ,就会创建一个新的compilation
compiler.hooks.compilation.tap('WebpackAssetsPlugin', (compilation) => {
//每次根据chunk创建一个新的文件后会触发一次chunkAsset
compilation.hooks.chunkAsset.tap('WebpackAssetsPlugin', (chunk, filename) => {
console.log(chunk.name || chunk.id, filename);
});
});
}
}
module.exports = WebpackAssetsPlugin;
plugins\webpack-archive-plugin.js
const jszip = require('jszip');
const { RawSource } = require('webpack-sources');
const { Compilation } = require('webpack');
/**
* 1.如何获取打出后的文件名和文件内容
* 2.如何打压缩包
* 3.如何向目标目录输出压缩包
*/
class WebpackArchivePlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
compiler.hooks.compilation.tap('WebpackAssetsPlugin', (compilation) => {
//当确定好文件,当你处理每个资源的时候处执行
compilation.hooks.processAssets.tapPromise({ name: 'WebpackArchivePlugin' }, (assets) => {
const zip = new jszip();
for (const filename in assets) {
const sourceObj = assets[filename];
const sourceCode = sourceObj.source();
zip.file(filename, sourceCode);
}
return zip.generateAsync({ type: 'nodebuffer' }).then(zipContent => {
assets[`archive_${Date.now()}。zip`] = new RawSource(zipContent);
});
});
});
}
}
module.exports = WebpackArchivePlugin;
webpack.config.js
const WebpackArchivePlugin = require('./plugins/webpack-archive-plugin');
plugins: [
+ new WebpackArchivePlugin({
+ filename:'[timestamp].zip'
+ })
]
external
script
能否检测代码中的 import 自动处理这个步骤?
{
externals:{
//key jquery是要require或import 的模块名,值 jQuery是一个全局变量名
'jquery':'$'
},
module:{}
}
external
和script
的问题,需要怎么实现,该从哪方面开始考虑依赖
当检测到有import
该library
时,将其设置为不打包类似exteral
,并在指定模版中加入 script,那么如何检测 import?这里就用Parser
external依赖
需要了解 external 是如何实现的,webpack 的 external 是通过插件ExternalsPlugin
实现的,ExternalsPlugin 通过tap
NormalModuleFactory
在每次创建 Module 的时候判断是否是ExternalModule
Parser
获取需要指定类型 moduleType,一般使用javascript/auto
即可plugins: [
new HtmlWebpackPlugin({
template:'./src/index.html'
}),
new AutoExternalPlugin({
jquery:{//自动把jquery模块变成一个外部依赖模块
variable:'jQuery',//不再打包,而是从window.jQuery变量上获取jquery对象
url:'https://cdn.bootcss.com/jquery/3.1.0/jquery.js'//CDN脚本
},
lodash:{//自动把jquery模块变成一个外部依赖模块
variable:'_',//不再打包,而是从window.jQuery变量上获取jquery对象
url:'https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.js'//CDN脚本
}
})
];
AsyncSeriesBailHook factorize
let { AsyncSeriesBailHook } = require("tapable");
let factorize = new AsyncSeriesBailHook(['resolveData']);
//最后总得返回一个模块吧 switch case default
factorize.tapAsync('factory1', (resolveData, callback) => {
if (resolveData === 'jquery') {
callback(null, {
id: resolveData,
type: '外部模块',
source: 'window.jQuery'
});
} else {
callback(null);
}
});
//生成正常模块的工厂函数最后一个工厂函数了,
factorize.tapAsync('factory2', (resolveData, callback) => {
callback(null, { id: resolveData, type: '正常模块', source: 'webpack打包后的内容' });
});
factorize.callAsync('jquery', (err, module) => {
console.log(module);
});
factorize.callAsync('lodash', (err, module) => {
console.log(module);
});
plugins\auto-external-plugin.js
const { ExternalModule } = require("webpack");
const HtmlWebpackPlugin = require('html-webpack-plugin');
/**
* 1.需要向输出html文件中添加CDN脚本引用
* 2.在打包生产模块的时候,截断正常的打包逻辑,变成外部依赖模块
*/
class AutoExternalPlugin{
constructor(options){
this.options = options;
this.externalModules = Object.keys(this.options);//['jquery'] 进行自动外键的模块
this.importedModules = new Set();//存放着所有的实际真正使用到的外部依赖模块
}
apply(compiler){
//每种模块会对应一个模块工厂 普通模块对应的就是普通模块工厂
//https://webpack.docschina.org/api/normalmodulefactory-hooks/
compiler.hooks.normalModuleFactory.tap('AutoExternalPlugin',(normalModuleFactory)=>{
//https://webpack.docschina.org/api/parser/#root
normalModuleFactory.hooks.parser
.for('javascript/auto')//普通 的JS文件对应的钩子就是'javascript/auto'
.tap('AutoExternalPlugin',parser=>{
//在parser遍历语法的过程中,如果遍历到了import节点
//https://webpack.docschina.org/api/parser/#import
parser.hooks.import.tap('AutoExternalPlugin',(statement,source)=>{
if(this.externalModules.includes(source)){
this.importedModules.add(source);
}
});
//https://webpack.docschina.org/api/parser/#call
//call=HookMap key方法名 值是这个方法对应的钩子
parser.hooks.call.for('require').tap('AutoExternalPlugin',(expression)=>{
let value = expression.arguments[0].value;
if(this.externalModules.includes(value)){
this.importedModules.add(value);
}
});
})
//2.改造模块的生产过程,如果是外链模块,就直接生产一个外链模块返回
//https://webpack.docschina.org/api/normalmodulefactory-hooks/
normalModuleFactory.hooks.factorize.tapAsync('AutoExternalPlugin',(resolveData,callback)=>{
let {request} = resolveData;//模块名 jquery lodash
if(this.externalModules.includes(request)){
let {variable} = this.options[request];
//request=jquery window.jQuery
callback(null,new ExternalModule(variable,'window',request));
}else{
callback(null);//如果是正常模块,直接向后执行。走正常的打包模块的流程
}
});
});
//是往输出的HTML中添加一个新的CDN Script标签
compiler.hooks.compilation.tap('AutoExternalPlugin',(compilation)=>{
HtmlWebpackPlugin.getHooks(compilation).alterAssetTags.tapAsync('AutoExternalPlugin',(htmlData,callback)=>{
//console.log(JSON.stringify(htmlData,null,2));
Reflect.ownKeys(this.options).filter(key=>this.importedModules.has(key)).forEach(key=>{
//jquery
htmlData.assetTags.scripts.unshift({
tagName:'script',
voidTag:false,
attributes:{
defer:false,
src:this.options[key].url
}
});
})
callback(null,htmlData);
});
});
}
}
module.exports = AutoExternalPlugin;
/**
* Node {
type: 'ImportDeclaration',
start: 0,
end: 23,
loc: SourceLocation {
start: Position { line: 1, column: 0 },
end: Position { line: 1, column: 23 }
},
range: [ 0, 23 ],
specifiers: [
Node {
type: 'ImportDefaultSpecifier',
start: 7,
end: 8,
loc: [SourceLocation],
range: [Array],
local: [Node]
}
],
source: Node {
type: 'Literal',
start: 14,
end: 22,
loc: SourceLocation { start: [Position], end: [Position] },
range: [ 14, 22 ],
value: 'jquery',
raw: "'jquery'"
}
}
jquery
*/
let AsyncQueue = require('webpack/lib/util/AsyncQueue');
let AsyncQueue = require('./AsyncQueue');
function processor(item, callback) {
setTimeout(() => {
console.log('process',item);
callback(null, item);
}, 3000);
}
const getKey = (item) => {
return item.key;
}
let queue = new AsyncQueue({
name:'createModule',parallelism:3,processor,getKey
});
const start = Date.now();
let item1 = {key:'module1'};
queue.add(item1,(err,result)=>{
console.log(err,result);
console.log(Date.now() - start);
});
queue.add(item1,(err,result)=>{
console.log(err,result);
console.log(Date.now() - start);
});
queue.add({key:'module2'},(err,result)=>{
console.log(err,result);
console.log(Date.now() - start);
});
queue.add({key:'module3'},(err,result)=>{
console.log(err,result);
console.log(Date.now() - start);
});
queue.add({key:'module4'},(err,result)=>{
console.log(err,result);
console.log(Date.now() - start);
});
use.js
const QUEUED_STATE = 0;//已经 入队,待执行
const PROCESSING_STATE = 1;//处理中
const DONE_STATE = 2;//处理完成
class ArrayQueue {
constructor() {
this._list = [];
}
enqueue(item) {
this._list.push(item);//[1,2,3]
}
dequeue() {
return this._list.shift();//移除并返回数组中的第一个元素
}
}
class AsyncQueueEntry {
constructor(item, callback) {
this.item = item;//任务的描述
this.state = QUEUED_STATE;//这个条目当前的状态
this.callback = callback;//任务完成的回调
}
}
class AsyncQueue {
constructor({ name, parallelism, processor, getKey }) {
this._name = name;//队列的名字
this._parallelism = parallelism;//并发执行的任务数
this._processor = processor;//针对队列中的每个条目执行什么操作
this._getKey = getKey;//函数,返回一个key用来唯一标识每个元素
this._entries = new Map();
this._queued = new ArrayQueue();//将要执行的任务数组队列
this._activeTasks = 0;//当前正在执行的数,默认值1
this._willEnsureProcessing = false;//是否将要开始处理
}
add = (item, callback) => {
const key = this._getKey(item);//获取这个条目对应的key
const entry = this._entries.get(key);//获取 这个key对应的老的条目
if (entry !== undefined) {
if (entry.state === DONE_STATE) {
process.nextTick(() => callback(entry.error, entry.result));
} else if (entry.callbacks === undefined) {
entry.callbacks = [callback];
} else {
entry.callbacks.push(callback);
}
return;
}
const newEntry = new AsyncQueueEntry(item, callback);//创建一个新的条目
this._entries.set(key, newEntry);//放到_entries
this._queued.enqueue(newEntry);//把这个新条目放放队列
if (this._willEnsureProcessing === false) {
this._willEnsureProcessing = true;
setImmediate(this._ensureProcessing);
}
}
_ensureProcessing = () => {
//如果当前的激活的或者 说正在执行任务数行小于并发数
while (this._activeTasks < this._parallelism) {
const entry = this._queued.dequeue();//出队 先入先出
if (entry === undefined) break;
this._activeTasks++;//先让正在执行的任务数++
entry.state = PROCESSING_STATE;//条目的状态设置为执行中
this._startProcessing(entry);
}
this._willEnsureProcessing = false;
}
_startProcessing = (entry) => {
this._processor(entry.item, (e, r) => {
this._handleResult(entry, e, r);
});
}
_handleResult = (entry, error, result) => {
const callback = entry.callback;
const callbacks = entry.callbacks;
entry.state = DONE_STATE;//把条目的状态设置为已经完成
entry.callback = undefined;//把callback
entry.callbacks = undefined;
entry.result = result;//把结果赋给entry
entry.error = error;//把错误对象赋给entry
callback(error, result);
if (callbacks !== undefined) {
for (const callback of callbacks) {
callback(error, result);
}
}
this._activeTasks--;
if (this._willEnsureProcessing === false) {
this._willEnsureProcessing = true;
setImmediate(this._ensureProcessing);
}
}
}
module.exports = AsyncQueue;
Object.keys(this.hooks).forEach(hookName => {
const hook = this.hooks[hookName];
if (hook instanceof HookMap) {
for (let key of hook._map.keys()) {
hook.for(key).tap('flow', () => {
console.log(`|JavascriptParser|${hookName}|${hook.for(key).constructor.name}|${hook._args}|`);
});
}
} else {
hook.tap('flow', () => {
console.log(`|JavascriptParser|${hookName}|${hook.constructor.name}|${hook._args}|`);
});
}
});
对象 | 钩子名称 | 类型 | 参数 | 含义 |
---|---|---|---|---|
Compiler | environment | SyncHook | 在编译器准备环境时调用,时机就在配置文件中初始化插件之后 | |
Compiler | afterEnvironment | SyncHook | ||
Compiler | entryOption | SyncBailHook | context,entry | |
Compiler | afterPlugins | SyncHook | compiler | |
Compiler | afterResolvers | SyncHook | compiler | |
Compiler | initialize | SyncHook | ||
Compiler | beforeRun | AsyncSeriesHook | compiler | |
Compiler | run | AsyncSeriesHook | compiler | |
Compiler | infrastructureLog | SyncBailHook | origin,type,args | |
Compiler | readRecords | AsyncSeriesHook | ||
Compiler | normalModuleFactory | SyncHook | normalModuleFactory | |
Compiler | contextModuleFactory | SyncHook | contextModuleFactory | |
Compiler | beforeCompile | AsyncSeriesHook | params | |
Compiler | compile | SyncHook | params | |
Compiler | thisCompilation | SyncHook | compilation,params | |
Compiler | compilation | SyncHook | compilation,params | |
Compiler | make | AsyncParallelHook | compilation | |
Compilation | addEntry | SyncHook | entry,options | |
NormalModuleFactory | beforeResolve | AsyncSeriesBailHook | resolveData | |
NormalModuleFactory | factorize | AsyncSeriesBailHook | resolveData | |
NormalModuleFactory | resolve | AsyncSeriesBailHook | resolveData | |
NormalModuleFactory | afterResolve | AsyncSeriesBailHook | resolveData | |
NormalModuleFactory | createModule | AsyncSeriesBailHook | createData,resolveData | |
NormalModuleFactory | module | SyncWaterfallHook | module,createData,resolveData | |
Compilation | buildModule | SyncHook | module | |
Compilation | normalModuleLoader | SyncHook | loaderContext,module | |
JavascriptParser | program | SyncBailHook | ast,comments | |
JavascriptParser | preStatement | SyncBailHook | statement | |
JavascriptParser | preStatement | SyncBailHook | statement | |
JavascriptParser | blockPreStatement | SyncBailHook | declaration | |
JavascriptParser | preDeclarator | SyncBailHook | declarator,statement | |
JavascriptParser | blockPreStatement | SyncBailHook | declaration | |
JavascriptParser | statement | SyncBailHook | statement | |
JavascriptParser | declarator | SyncBailHook | declarator,statement | |
JavascriptParser | statement | SyncBailHook | statement | |
JavascriptParser | finish | SyncBailHook | ast,comments | |
Compilation | succeedModule | SyncHook | module | |
NormalModuleFactory | beforeResolve | AsyncSeriesBailHook | resolveData | |
NormalModuleFactory | factorize | AsyncSeriesBailHook | resolveData | |
NormalModuleFactory | resolve | AsyncSeriesBailHook | resolveData | |
NormalModuleFactory | afterResolve | AsyncSeriesBailHook | resolveData | |
NormalModuleFactory | createModule | AsyncSeriesBailHook | createData,resolveData | |
NormalModuleFactory | module | SyncWaterfallHook | module,createData,resolveData | |
Compilation | buildModule | SyncHook | module | |
Compilation | normalModuleLoader | SyncHook | loaderContext,module | |
JavascriptParser | program | SyncBailHook | ast,comments | |
JavascriptParser | preStatement | SyncBailHook | statement | |
JavascriptParser | blockPreStatement | SyncBailHook | declaration | |
JavascriptParser | statement | SyncBailHook | statement | |
JavascriptParser | finish | SyncBailHook | ast,comments | |
Compilation | succeedModule | SyncHook | module | |
Compilation | succeedEntry | SyncHook | entry,options,module | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compiler | finishMake | AsyncSeriesHook | compilation | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | finishModules | AsyncSeriesHook | modules | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | seal | SyncHook | ||
Compilation | optimizeDependencies | SyncBailHook | modules | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | afterOptimizeDependencies | SyncHook | modules | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | beforeChunks | SyncHook | ||
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | afterChunks | SyncHook | chunks | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | optimize | SyncHook | ||
Compilation | optimizeModules | SyncBailHook | modules | |
Compilation | afterOptimizeModules | SyncHook | modules | |
Compilation | optimizeChunks | SyncBailHook | chunks,chunkGroups | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | afterOptimizeChunks | SyncHook | chunks,chunkGroups | |
Compilation | optimizeTree | AsyncSeriesHook | chunks,modules | |
Compilation | afterOptimizeTree | SyncHook | chunks,modules | |
Compilation | optimizeChunkModules | AsyncSeriesBailHook | chunks,modules | |
Compilation | afterOptimizeChunkModules | SyncHook | chunks,modules | |
Compilation | shouldRecord | SyncBailHook | ||
Compilation | reviveModules | SyncHook | modules,records | |
Compilation | beforeModuleIds | SyncHook | modules | |
Compilation | moduleIds | SyncHook | modules | |
Compilation | optimizeModuleIds | SyncHook | modules | |
Compilation | afterOptimizeModuleIds | SyncHook | modules | |
Compilation | reviveChunks | SyncHook | chunks,records | |
Compilation | beforeChunkIds | SyncHook | chunks | |
Compilation | chunkIds | SyncHook | chunks | |
Compilation | optimizeChunkIds | SyncHook | chunks | |
Compilation | afterOptimizeChunkIds | SyncHook | chunks | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | recordModules | SyncHook | modules,records | |
Compilation | recordChunks | SyncHook | chunks,records | |
Compilation | optimizeCodeGeneration | SyncHook | modules | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | beforeModuleHash | SyncHook | ||
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | afterModuleHash | SyncHook | ||
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | beforeCodeGeneration | SyncHook | ||
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | afterCodeGeneration | SyncHook | ||
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | beforeRuntimeRequirements | SyncHook | ||
Compilation | additionalModuleRuntimeRequirements | SyncHook | module,runtimeRequirements,context | |
Compilation | additionalModuleRuntimeRequirements | SyncHook | module,runtimeRequirements,context | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | additionalChunkRuntimeRequirements | SyncHook | chunk,runtimeRequirements,context | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | additionalTreeRuntimeRequirements | SyncHook | chunk,runtimeRequirements,context | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | afterRuntimeRequirements | SyncHook | ||
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | beforeHash | SyncHook | ||
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | chunkHash | SyncHook | chunk,chunkHash,ChunkHashContext | |
Compilation | contentHash | SyncHook | chunk | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | fullHash | SyncHook | hash | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | afterHash | SyncHook | ||
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | recordHash | SyncHook | records | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | beforeModuleAssets | SyncHook | ||
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | shouldGenerateChunkAssets | SyncBailHook | ||
Compilation | beforeChunkAssets | SyncHook | ||
Compilation | renderManifest | SyncWaterfallHook | result,options | |
Compilation | assetPath | SyncWaterfallHook | path,options,assetInfo | |
Compilation | chunkAsset | SyncHook | chunk,filename | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | additionalChunkAssets | Object | undefined | |
Compilation | additionalAssets | Object | undefined | |
Compilation | optimizeAssets | AsyncSeriesHook | assets | |
Compilation | processAssets | AsyncSeriesHook | assets | |
Compilation | optimizeChunkAssets | Object | undefined | |
Compilation | afterOptimizeChunkAssets | Object | undefined | |
Compilation | afterOptimizeAssets | SyncHook | assets | |
Compilation | afterProcessAssets | SyncHook | assets | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | record | SyncHook | compilation,records | |
Compilation | needAdditionalSeal | SyncBailHook | ||
Compilation | afterSeal | AsyncSeriesHook | ||
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compiler | afterCompile | AsyncSeriesHook | compilation | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compiler | shouldEmit | SyncBailHook | compilation | |
Compiler | emit | AsyncSeriesHook | compilation | |
Compilation | assetPath | SyncWaterfallHook | path,options,assetInfo | |
Compiler | assetEmitted | AsyncSeriesHook | file,info | |
Compiler | afterEmit | AsyncSeriesHook | compilation | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | needAdditionalPass | SyncBailHook | ||
Compiler | emitRecords | AsyncSeriesHook | ||
Compilation | log | SyncBailHook | origin,logEntry | |
Compiler | done | AsyncSeriesHook | stats | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compilation | log | SyncBailHook | origin,logEntry | |
Compiler | shutdown | AsyncSeriesHook | ||
Compilation | statsNormalize | SyncHook | options,context | |
Compilation | statsFactory | SyncHook | statsFactory,options | |
Compilation | statsPrinter | SyncHook | statsPrinter,options | |
Compilation | processErrors | SyncWaterfallHook | errors | |
Compilation | processWarnings | SyncWaterfallHook | warnings | |
Compiler | afterDone | SyncHook | stats | |
Compiler | infrastructureLog | SyncBailHook | origin,type,args |
事件名 | 解释 | 代码位置 |
---|---|---|
读取命令行参数 | 从命令行中读取用户输入的参数 | require("./convert-argv")(argv) |
实例化 Compiler | 1.用上一步得到的参数初始化 Compiler 实例 2.Compiler 负责文件监听和启动编译 3.Compiler 实例中包含了完整的 Webpack 配置,全局只有一个 Compiler 实例。 |
compiler = webpack(options); |
加载插件 | 1.依次调用插件的 apply 方法,让插件可以监听后续的所有事件节点。 同时给插件传入 compiler 实例的引用,以方便插件通过 compiler 调用 Webpack 提供的 API。 |
plugin.apply(compiler) |
处理入口 | 读取配置的 Entrys,为每个 Entry 实例化一个对应的 EntryPlugin,为后面该 Entry 的递归解析工作做准备 | new EntryOptionPlugin().apply(compiler) new SingleEntryPlugin(context, item, name) compiler.hooks.make.tapAsync |
事件名 | 解释 | 代码位置 |
---|---|---|
seal | 封装 | compilation.seal seal(callback) |
addChunk | 生成资源 | addChunk(name) |
createChunkAssets | 创建资源 | this.createChunkAssets() |
getRenderManifest | 获得要渲染的描述文件 | getRenderManifest(options) |
render | 渲染源码 | source = fileManifest.render(); |
afterCompile | 编译结束 | this.hooks.afterCompile |
shouldEmit | 所有需要输出的文件已经生成好,询问插件哪些文件需要输出,哪些不需要。 | this.hooks.shouldEmit |
emit | 确定好要输出哪些文件后,执行文件输出,可以在这里获取和修改输出内容。 | this.emitAssets(compilation this.hooks.emit.callAsync const emitFiles = err this.outputFileSystem.writeFile |
this.emitRecords | 写入记录 | this.emitRecords |
done | 全部完成 | this.hooks.done.callAsync |