為webpack編寫一個plugin

0、基本概念

插件是webpack的支柱功能,極大地強(qiáng)化了webpack的構(gòu)建能力。

webpack 插件由以下組成:
  • 一個 JavaScript 命名函數(shù)。
  • 在插件函數(shù)的 prototype 上定義一個 apply 方法。
  • 指定一個綁定到 webpack 自身的事件鉤子。
  • 處理 webpack 內(nèi)部實例的特定數(shù)據(jù)。
  • 功能完成后調(diào)用 webpack 提供的回調(diào)。

1、webpack Hooks

一個簡單的例子:
function MyExampleWebpackPlugin() {
};

// 在插件函數(shù)的 prototype 上定義一個 `apply` 方法。
MyExampleWebpackPlugin.prototype.apply = function(compiler) {
  // 指定一個掛載到 webpack 自身的事件鉤子。
  compiler.plugin('webpacksEventHook', function(compilation, callback) {
    console.log("This is an example plugin!!!");
    // 功能完成后調(diào)用 webpack 提供的回調(diào)。
    callback();
  });
};

以上是編寫一個插件的基本格式,關(guān)于 webpacksEventHook 可以查看文檔 webpack 的 Hooks

列舉幾種hooks:
  • entryOption SyncBailHook, webpack 處理完 entry 配置項后觸發(fā)
  • afterPlugins SyncHook, 處理完初始化插件后觸發(fā)
  • afterResolvers SyncHook, Resolve 安裝完成后觸發(fā)
  • environment SyncHook, environment 準(zhǔn)備好后觸發(fā)
  • emit AsyncSeriesHook, 輸出文件到 output 目錄之前觸發(fā)
hook的類型總結(jié)(引用一張網(wǎng)上的圖片):
1.png

2、實際案例

clean-webpack-plugin 插件大部分人應(yīng)該用過,可以在構(gòu)建項目時清理文件,下面來看一下 clean-webpack-plugin源碼

class CleanWebpackPlugin {
  // ...省略
  apply(compiler: Compiler) {
        if (!compiler.options.output || !compiler.options.output.path) {
            // eslint-disable-next-line no-console
            console.warn(
                'clean-webpack-plugin: options.output.path not defined. Plugin disabled...',
            );
            return;
        }
        this.outputPath = compiler.options.output.path;

        /**
         * webpack 4+ comes with a new plugin system.
         *
         * Check for hooks in-order to support old plugin system
         */
        const hooks = compiler.hooks;
        if (this.cleanOnceBeforeBuildPatterns.length !== 0) {
            if (hooks) {
                hooks.emit.tap('clean-webpack-plugin', (compilation) => {
                    this.handleInitial(compilation);
                });
            } else {
                compiler.plugin('emit', (compilation, callback) => {
                    try {
                        this.handleInitial(compilation);

                        callback();
                    } catch (error) {
                        callback(error);
                    }
                });
            }
        }
        // ...省略
    }
}

可以看到它使用到了 emit 這個hook, 另外發(fā)現(xiàn) webpack4+ 和 老版本的webpack 編寫插件時的一些差異: 4+版本使用 compiler.hooks 老版本使用 compiler.plugin。
還有一些代碼沒有在這里展示,總體上刪除文件就是調(diào)用了del.sync。

3、動手編寫一個插件

下面按照webpack官網(wǎng)給的例子,來實現(xiàn)一個插件,作用是在生成打包文件的目錄額外生成一個文件,記錄所有的打包文件。

test-webpack-plugin.js :

class TestWebpackPlugin {
  constructor(options) {
  }

  apply(compoiler) {
    compoiler.hooks.emit.tapAsync("TestWebpackPlugin", (compilation, cb) => {
     // 在生成文件中,創(chuàng)建一個頭部字符串:
    var filelist = "build files:\n\n";

    // compilation.assets 存放所有生成的文件信息
    for (var filename in compilation.assets) {
      filelist += ("- "+ filename + "\n");
    }

    /* 將這個列表作為一個新的文件資源,插入到 webpack 構(gòu)建中: 
     * 文件內(nèi)容和文件長度需要通過source 和 size來定義
     */
    compilation.assets["filelist.md"] = {
      // 填充文件內(nèi)容
      source: function() {
        return filelist;
      },
      // 文件長度
      size: function() {
        return filelist.length;
      }
    };
    cb();
    })
  }
}

module.exports = TestWebpackPlugin

webpack.config.js:

const path = require("path")
const TestWebpackPlugin = require("./plugins/test-webpack-plugin")

module.exports = {
    mode: "development",
    entry: {
        main: "./src/index.js"
    },
    output: {
        path: path.resolve(__dirname, "dist"),
        filename: "[name].[hash].js"
    },
    plugins: [
        new TestWebpackPlugin({ name: "測試參數(shù)"}) 
    ]
}

打包后dist目錄多了一個文件:


image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言 Plugin(插件) 是 webpack 生態(tài)的的一個關(guān)鍵部分。它為社區(qū)提供了一種強(qiáng)大的方法來擴(kuò)展 webp...
    champyin閱讀 2,003評論 0 3
  • 編寫一個webpack plugin(基礎(chǔ)篇) 創(chuàng)建插件 webpack插件由以下組成 一個具名javaScrip...
    拋荒了四序閱讀 2,603評論 4 58
  • 作為先進(jìn)最為流行的前端構(gòu)建工具之一,webpack成為了前端開發(fā)必須掌握的技能。其諸多的插件為我們的工作帶來了大大...
    緋色流火閱讀 4,513評論 0 13
  • 編寫 Loader Loader就像是一個翻譯員,能把源文件經(jīng)過轉(zhuǎn)化后輸出新的結(jié)果,并且一個文件還可以鏈?zhǔn)降慕?jīng)過多...
    oWSQo閱讀 7,696評論 0 8
  • 前幾篇文章中,我們介紹了webpack v4.20.2相關(guān)的內(nèi)容,但是很多老項目,還在使用webpack 3,也要...
    何幻閱讀 2,790評論 0 1

友情鏈接更多精彩內(nèi)容