美文网首页Front End
[FE] webpack v4.20.2 源码解析(三):插件的

[FE] webpack v4.20.2 源码解析(三):插件的

作者: 何幻 | 来源:发表于2018-10-17 12:25 被阅读1次

    下面我们来介绍下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为CompilerCompilation对象实现了切面能力,
    其中,CompilerCompilation都是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.tapAsyncmake.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.taphooks.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
    

    相关文章

      网友评论

        本文标题:[FE] webpack v4.20.2 源码解析(三):插件的

        本文链接:https://www.haomeiwen.com/subject/teblzftx.html