webpack 插件怎麼寫

摘要

如今項目大部分都使用webpack 進行編譯,一方面 webpack 生命力比較旺盛,另外一方面 webpack 的生態很是完善。咱們90%的場景都可以知足。但有時候也會遇到一些特定的業務場景,好比有時候會遇到須要對編譯後的文件進行一些文件注入 等其餘特定化的需求。怎麼辦呢?那就來寫一個業務定製化的webpack 插件吧。webpack

官方文檔可見: https://webpack.js.org/contribute/writing-a-plugin/#creating-a-pluginweb

如何編寫插件

首先咱們瞭解下一個插件的主要結構api

class DtoolPlugin {
    // 構造函數,進行參數校驗等功能
    constructor(args) {}
    
    // 定義插件執行的方法體,主要邏輯都在這裏完成,webpack 會自動調用此方法
    apply(compiler) {}

}

下面咱們來看下 compiler 這個關鍵對象,compile 提供了 webpack 一系列操做的鉤子函數,下面說一說經常使用的hooksapp

官方文檔可見:https://webpack.js.org/api/compiler-hooks/#watching異步

下面以真實案例來說解async

apply(compiler) {
            const metaParams = this.metaParams;
        const tester = {test: this.test};

        compiler.hooks.compilation.tap('DtoolPlugin', (compilation) => {
                compilation.hooks.optimizeChunkAssets.tapAsync('DtoolPlugin', (chunks, done) => {
                    wrapChunks(compilation, chunks);
                    done();
                })
            });
            // 注入文件方法
            function wrapChunks(compilation, chunks) {
                chunks.forEach(chunk => {
                    const args = {
                        hash: compilation.hash,
                        chunkhash: chunk.hash
                    };
                    chunk.files.forEach(fileName => {
                        if (ModuleFilenameHelpers.matchObject(tester, fileName)) {
                            const content = 'xxxxx';
                            // 注入內容
                            // assets 對象是編譯後的對象,以文件名爲key , 值爲文件內容 、 文件size 等一系列信息, 經過asset 能夠對文件名字 , 文件內容作變動
                            compilation.assets[fileName] = new ConcatSource(
                                compilation.assets[fileName],
                                String(content),
                            );
                    }
                });
            });
        }
    }

hooks 調用的時候有個類型 plugin types 支持 tap , 有些支持異步類型 tapAsync tapPromise函數

compiler.hooks.run.tapAsync('MyPlugin', (source, target, routesList, callback) => {
  console.log('Asynchronously tapping the run hook.');
  callback();
});

compiler.hooks.run.tapPromise('MyPlugin', (source, target, routesList) => {
  return new Promise(resolve => setTimeout(resolve, 1000)).then(() => {
    console.log('Asynchronously tapping the run hook with a delay.');
  });
});

compiler.hooks.run.tapPromise('MyPlugin', async (source, target, routesList) => {
  await new Promise(resolve => setTimeout(resolve, 1000));
  console.log('Asynchronously tapping the run hook with a delay.');
});
相關文章
相關標籤/搜索