下面我们来介绍下webpack plugin的写法,顺便回答上一篇 this.hooks.make.callAsync
的调用问题。
(1)test-plugin.js
在工程目录中,我们新建test-plugin.js
文件,
module.exports = class TestPlugin {
apply(compiler) {
compiler.hooks.make.tapAsync('TestPlugin', (compilation, callback) => {
compilation.hooks.buildModule.tap('TestPlugin', module => {
console.log('module.resource', module.resource);
console.log('module.loaders', module.loaders);
console.time('TestPlugin');
});
compilation.hooks.succeedModule.tap('TestPlugin', module => {
console.timeEnd('TestPlugin');
});
callback();
});
}
};
它导出了一个包含apply
方法的类。
(2)webpack.config.js中使用该plugin
const path = require('path');
const TestPlugin = require('./test-plugin');
module.exports = {
entry: {
index: path.resolve(__dirname, 'src/index.js'),
},
output: {
path: path.resolve(__dirname, 'dist/'),
},
module: {
rules: [
{ test: /\.js$/, use: { loader: 'babel-loader', query: { presets: ['@babel/preset-env'] } } },
]
},
plugins:[
new TestPlugin(),
],
};
我们在webpack.config.js
中,引入了test-plugin
模块,
然后为导出对象增加了plugins
属性。
(3)执行结果
module.resource ~/Test/debug-webpack/src/index.js
module.loaders [ { options: { presets: [Array] },
ident: 'ref--4',
loader: '~/Test/debug-webpack/node_modules/_babel-loader@8.0.4@babel-loader/lib/index.js' } ]
TestPlugin: 213.301ms
我们使用test-plugin实现了监控,它能统计出文件的build时间。
其中,
compiler.hooks.make
,在源代码webpack/lib/Compiler.js 第536行被调用,
this.hooks.make.callAsync(compilation, err => {
...
});
compilation.hooks.buildModule
,在源代码webpack/lib/Compilation.js 第617行被调用,
this.hooks.buildModule.call(module);
compilation.hooks.succeedModule
,在源代码webpack/lib/Compilation.js 第652行被调用,
this.hooks.succeedModule.call(module);
注:
hooks为Compiler
和Compilation
对象实现了切面能力,
其中,Compiler
和Compilation
都是Tapable
类的子类。
Tapable
是一个单独的库,位于github: tapable。
hooks有很多不同的种类,不同种类的hooks实现与调用方式一一对应。
例如,compiler.hooks.make
是一种AsyncParallelHook
,源码位于Compiler.js 第73行,
make: new AsyncParallelHook(["compilation"]),
实现方法如下,
compiler.hooks.make.tapAsync('TestPlugin', (compilation, callback) => {
...
callback(); // 这里不用return而是用callback返回
});
而调用方式是,
this.hooks.make.callAsync(compilation, err => {
...
});
其中,make.tapAsync
与make.callAsync
相对应。
又例如,compilation.hooks.buildModule
是一种SyncHook
,源码位于Compilation.js 第211行,
buildModule: new SyncHook(["module"]),
实现方法如下,
compilation.hooks.buildModule.tap('TestPlugin', module => {
...
});
而调用方式是,
this.hooks.buildModule.call(module);
其中,hooks.buildModule.tap
与hooks.buildModule.call
相对应。
附
上文中我们提到了loader-runner是一个递归加载文件的过程,
下面我们改变一下src/index.js,增加一个src/a.js,
然后看下日志。
(1)src/index.js
import a from './a'; alert(1);
(2)src/a.js
alert(2);
(3)日志
debug-webpack webpack webpack.js cliPath: ~/.nvm/versions/node/v8.12.0/lib/node_modules/webpack-cli/bin/cli.js +0ms
debug-webpack webpack-cli cli.js start: compiler.run +0ms
debug-webpack webpack Compiler.js start: this.hooks.make.callAsync +0ms
debug-webpack webpack SingleEntryPlugin.js in: compiler.hooks.make.tapAsync +0ms
debug-webpack webpack SingleEntryPlugin.js start: compilation.addEntry +0ms
debug-webpack webpack Compilation.js in: addEntry +0ms
debug-webpack webpack Compilation.js start: this._addModuleChain +0ms
debug-webpack webpack Compilation.js in: _addModuleChain +0ms
debug-webpack webpack Compilation.js start: moduleFactory.create +0ms
debug-webpack webpack Compilation.js end: moduleFactory.create +39ms
debug-webpack webpack Compilation.js module.resource: ~/Test/debug-webpack/src/index.js +0ms
debug-webpack webpack Compilation.js module.loaders: [{"options":{"presets":["@babel/preset-env"]},"ident":"ref--4","loader":"~/Test/debug-webpack/node_modules/_babel-loader@8.0.4@babel-loader/lib/index.js"}] +0ms
debug-webpack webpack Compilation.js start: this.buildModule +1ms
debug-webpack webpack Compilation.js in: buildModule +0ms
debug-webpack webpack Compilation.js start: module.build +0ms
debug-webpack webpack NormalModule.js in: build +0ms
debug-webpack webpack NormalModule.js start: this.doBuild +0ms
debug-webpack webpack NormalModule.js in: doBuild +1ms
debug-webpack webpack NormalModule.js start: runLoaders +0ms
debug-webpack loader-runner LoaderRunner.js in: runLoaders +0ms
debug-webpack loader-runner LoaderRunner.js start: iteratePitchingLoaders +1ms
debug-webpack loader-runner LoaderRunner.js in: iteratePitchingLoaders +0ms
debug-webpack loader-runner LoaderRunner.js start: loadLoader +0ms
debug-webpack loader-runner loadLoader.js in: loadLoader +0ms
debug-webpack loader-runner loadLoader.js loader.path: ~/Test/debug-webpack/node_modules/_babel-loader@8.0.4@babel-loader/lib/index.js +0ms
debug-webpack loader-runner LoaderRunner.js end: loadLoader +38ms
debug-webpack loader-runner LoaderRunner.js start: 1. iteratePitchingLoaders +0ms
debug-webpack loader-runner LoaderRunner.js in: iteratePitchingLoaders +0ms
debug-webpack loader-runner LoaderRunner.js start: 2. iteratePitchingLoaders +0ms
debug-webpack loader-runner LoaderRunner.js in: iteratePitchingLoaders +0ms
debug-webpack loader-runner LoaderRunner.js start: processResource +0ms
debug-webpack loader-runner LoaderRunner.js in: processResource +0ms
debug-webpack loader-runner LoaderRunner.js start: iterateNormalLoaders +0ms
debug-webpack loader-runner LoaderRunner.js in: iterateNormalLoaders +1ms
debug-webpack loader-runner LoaderRunner.js start: runSyncOrAsync +0ms
debug-webpack loader-runner LoaderRunner.js in: runSyncOrAsync +0ms
debug-webpack loader-runner LoaderRunner.js start: LOADER_EXECUTION +0ms
debug-webpack loader-runner LoaderRunner.js in: async +0ms
debug-webpack babel-loader index.js in: loader +0ms
debug-webpack babel-loader index.js this.resourcePath: ~/Test/debug-webpack/src/index.js +1ms
debug-webpack babel-loader index.js start: transform +112ms
debug-webpack babel-loader index.js source: import a from './a'; alert(1); +1ms
debug-webpack babel-loader index.js end: transform +72ms
debug-webpack babel-loader index.js result: {"ast":null,"code":"import a from './a';\nalert(1);","map":null,"metadata":{},"sourceType":"module"} +0ms
debug-webpack loader-runner LoaderRunner.js in: innerCallback +187ms
debug-webpack loader-runner LoaderRunner.js end: LOADER_EXECUTION +0ms
debug-webpack loader-runner LoaderRunner.js end: runSyncOrAsync +0ms
debug-webpack loader-runner LoaderRunner.js start: 1. iterateNormalLoaders +0ms
debug-webpack loader-runner LoaderRunner.js in: iterateNormalLoaders +0ms
debug-webpack loader-runner LoaderRunner.js start: 2. iterateNormalLoaders +0ms
debug-webpack loader-runner LoaderRunner.js in: iterateNormalLoaders +0ms
debug-webpack loader-runner LoaderRunner.js end: iteratePitchingLoaders +0ms
debug-webpack webpack NormalModule.js end: runLoaders +228ms
debug-webpack webpack NormalModule.js end: this.doBuild +0ms
debug-webpack webpack Compilation.js end: module.build +237ms
debug-webpack webpack Compilation.js end: this.buildModule +0ms
debug-webpack webpack Compilation.js in: buildModule +43ms
debug-webpack webpack Compilation.js start: module.build +0ms
debug-webpack webpack NormalModule.js in: build +51ms
debug-webpack webpack NormalModule.js start: this.doBuild +0ms
debug-webpack webpack NormalModule.js in: doBuild +0ms
debug-webpack webpack NormalModule.js start: runLoaders +0ms
debug-webpack loader-runner LoaderRunner.js in: runLoaders +52ms
debug-webpack loader-runner LoaderRunner.js start: iteratePitchingLoaders +0ms
debug-webpack loader-runner LoaderRunner.js in: iteratePitchingLoaders +0ms
debug-webpack loader-runner LoaderRunner.js start: loadLoader +0ms
debug-webpack loader-runner loadLoader.js in: loadLoader +278ms
debug-webpack loader-runner loadLoader.js loader.path: ~/Test/debug-webpack/node_modules/_babel-loader@8.0.4@babel-loader/lib/index.js +0ms
debug-webpack loader-runner LoaderRunner.js end: loadLoader +0ms
debug-webpack loader-runner LoaderRunner.js start: 1. iteratePitchingLoaders +1ms
debug-webpack loader-runner LoaderRunner.js in: iteratePitchingLoaders +0ms
debug-webpack loader-runner LoaderRunner.js start: 2. iteratePitchingLoaders +0ms
debug-webpack loader-runner LoaderRunner.js in: iteratePitchingLoaders +0ms
debug-webpack loader-runner LoaderRunner.js start: processResource +0ms
debug-webpack loader-runner LoaderRunner.js in: processResource +0ms
debug-webpack loader-runner LoaderRunner.js start: iterateNormalLoaders +0ms
debug-webpack loader-runner LoaderRunner.js in: iterateNormalLoaders +0ms
debug-webpack loader-runner LoaderRunner.js start: runSyncOrAsync +0ms
debug-webpack loader-runner LoaderRunner.js in: runSyncOrAsync +0ms
debug-webpack loader-runner LoaderRunner.js start: LOADER_EXECUTION +0ms
debug-webpack loader-runner LoaderRunner.js in: async +0ms
debug-webpack babel-loader index.js in: loader +53ms
debug-webpack babel-loader index.js this.resourcePath: ~/Test/debug-webpack/src/a.js +0ms
debug-webpack babel-loader index.js start: transform +0ms
debug-webpack babel-loader index.js source: alert(2); +0ms
debug-webpack babel-loader index.js end: transform +3ms
debug-webpack babel-loader index.js result: {"ast":null,"code":"alert(2);","map":null,"metadata":{},"sourceType":"module"} +0ms
debug-webpack loader-runner LoaderRunner.js in: innerCallback +3ms
debug-webpack loader-runner LoaderRunner.js end: LOADER_EXECUTION +0ms
debug-webpack loader-runner LoaderRunner.js end: runSyncOrAsync +0ms
debug-webpack loader-runner LoaderRunner.js start: 1. iterateNormalLoaders +0ms
debug-webpack loader-runner LoaderRunner.js in: iterateNormalLoaders +0ms
debug-webpack loader-runner LoaderRunner.js start: 2. iterateNormalLoaders +0ms
debug-webpack loader-runner LoaderRunner.js in: iterateNormalLoaders +0ms
debug-webpack loader-runner LoaderRunner.js end: iteratePitchingLoaders +0ms
debug-webpack webpack NormalModule.js end: runLoaders +4ms
debug-webpack webpack NormalModule.js end: this.doBuild +0ms
debug-webpack webpack Compilation.js end: module.build +5ms
debug-webpack webpack Compilation.js end: this._addModuleChain +1ms
debug-webpack webpack Compiler.js end: this.hooks.make.callAsync +327ms
(4)插件的日志
module.resource ~/Test/debug-webpack/src/index.js
module.loaders [ { options: { presets: [Array] },
ident: 'ref--4',
loader: '~/Test/debug-webpack/node_modules/_babel-loader@8.0.4@babel-loader/lib/index.js' } ]
TestPlugin: 353.712ms
module.resource ~/Test/debug-webpack/src/a.js
module.loaders [ { options: { presets: [Array] },
ident: 'ref--4',
loader: '~/Test/debug-webpack/node_modules/_babel-loader@8.0.4@babel-loader/lib/index.js' } ]
TestPlugin: 3.883ms
网友评论