擴展 HtmlwebpackPlugin 插入自定義的腳本

webpack 提供了一個如何開發 webpack 插件的介紹,你能夠直接訪問這裏查看,這裏提供一個擴展 HtmlWebpackPlugin 的開發實例。javascript

前面咱們介紹過 HtmlWebpackPlugin, 這個插件容許將 webpack 動態打包的輸出注入到頁面中,可是,有的時候咱們須要在這個頁面中注入一些自定義的樣式表或者腳本,HtmlWebpackPlugin 並不支持這個特性。有人向插件做者提了建議,這裏是討論的內容,結果是插件提供了幾個事件來支持本身來實現這個特性。咱們經過一個實例來演示如何使用這些事件來擴展 webpack。html

需求

咱們但願可以自動插入一個腳本的 script 在 webpack 生成的 script 以前,以便提早加載咱們自定義的數據。最後生成的 HTML 相似這樣的效果。java

    <script type="text/javascript" src="./configuration/config.js"></script>
    <script type="text/javascript" src="style.bundle.js"></script>
    <script type="text/javascript" src="app.bundle.js"></script>

 

第一行是咱們指望注入的腳本,其它兩行是 webpack 導出的腳本。webpack

插件入門

做爲一個 webpack 的插件,使用方式是這樣的。git

plugins: [
    new MyPlugin({
        paths: ["./configuration/config.js"]
    }),
    new HtmlwebpackPlugin({
        title: 'Hello Angular2!',
        template: './src/index.html',
        inject: true
    })
],

 

全部的插件定義在 plugins 中,插件組成的一個數組,每一個元素是一個插件的對象實例,具體傳遞什麼參數,是你本身定義的。github

從使用方式中能夠看出,其實咱們須要一個 JavsScript 的類函數,也就是說,寫 webpack 插件就是定義一個這樣的函數,這個函數須要接收參數。web

webpack 還要求這個對象提供一個名爲 apply 的函數,這個函數定義在插件的原型上,webpack 會調用插件實例的這個方法,在調用的時候還會傳遞一個參數,以便咱們訪問 webpack 的上下文信息。npm

官方提供的實例函數以下,最後一行是使用 CommonJs 風格導出這個插件。數組

function HelloWorldPlugin(options) {
  // Setup the plugin instance with options...
}

HelloWorldPlugin.prototype.apply = function(compiler) {
  compiler.plugin('done', function() {
    console.log('Hello World!'); 
  });
};

module.exports = HelloWorldPlugin;

 

 

傳遞參數

在咱們的需求中,咱們但願傳遞一個名爲 paths 的路徑參數,其中的每一個路徑須要生成一個 script 元素,插入到 webpack 導出的 script 以前。app

new MyPlugin({
        paths: ["./configuration/config.js"]
    }),

 

 在咱們的插件中,須要保存這個參數,以便在 apply 函數中使用。

function MyPlugin(options) {
    // Configure your plugin with options... 
this.options = options;
}

 

直接保存到當前的對象實例中,在配合 new 的時候,this 就是剛剛建立的插件對象實例了。

實現

在 webpack 調用插件對象的 apply 方式的時候,咱們首先應該獲取咱們保存的參數,使用 this 訪問當前對象,獲取剛剛保存的參數。

MyPlugin.prototype.apply = function(compiler) {
    // ...
    var paths = this.options.paths;
    

};

 

 

在咱們的 apply 方法內,須要調用 compiler 的 plugin 函數。這個函數註冊到 webpack 各個處理階段上,能夠支持的參數有:

咱們這裏使用了 compilation 編譯任務。

MyPlugin.prototype.apply = function(compiler) {
    var paths = this.options.paths;
    compiler.plugin('compilation', function(compilation, options) {


}); };

 

webpack 會給咱們提供的回調函數提供參數,咱們能夠註冊編譯階段的事件了。html-webpack-plugin 提供了一系列事件。

Async:

  • html-webpack-plugin-before-html-generation
  • html-webpack-plugin-before-html-processing
  • html-webpack-plugin-alter-asset-tags
  • html-webpack-plugin-after-html-processing
  • html-webpack-plugin-after-emit

Sync:

  • html-webpack-plugin-alter-chunks

咱們能夠註冊到它處理 HTML 以前,使用 html-webpack-plugin-before-html-processing 事件。

MyPlugin.prototype.apply = function(compiler) {
    var paths = this.options.paths;
    compiler.plugin('compilation', function(compilation, options) {
        compilation.plugin('html-webpack-plugin-before-html-processing', function(htmlPluginData, callback) {

     ......
}); }); };

 

在這個回調函數中,咱們能夠獲得 html-webpack-plugin 提供的上下文對象,好比,它準備生成 script 所對應的 javascript 文件路徑就保存在 htmlPluginData.assets.js 數組中,它會根據這個數組中的路徑,依次生成 script 元素,而後插入到 Html 網頁中。

咱們須要的就是就咱們的路徑插入到這個數組的前面。

MyPlugin.prototype.apply = function(compiler) {
    var paths = this.options.paths;
    compiler.plugin('compilation', function(compilation, options) {
        compilation.plugin('html-webpack-plugin-before-html-processing', function(htmlPluginData, callback) {
            for (var i = paths.length - 1; i >= 0; i--) {
                htmlPluginData.assets.js.unshift(paths[i]);
            }
            callback(null, htmlPluginData);
        });
    });
};

 

完整的插件代碼以下所示。

function MyPlugin(options) {
this.options = options;
}

MyPlugin.prototype.apply = function(compiler) {
    var paths = this.options.paths;
    compiler.plugin('compilation', function(compilation, options) {
        compilation.plugin('html-webpack-plugin-before-html-processing', function(htmlPluginData, callback) {
            for (var i = paths.length - 1; i >= 0; i--) {
                htmlPluginData.assets.js.unshift(paths[i]);
            }
            callback(null, htmlPluginData);
        });
    });
};

module.exports = MyPlugin;

 

最後一行是導出咱們的插件。

討論

經過 webpack 的插件機制,咱們能夠自由地擴展 webpack ,實現咱們須要的特性。

See Also:

HOW TO WRITE A PLUGIN

如何寫一個webpack插件(一)

webpack使用優化(基本篇) #2

html-res-webpack-plugin

相關文章
相關標籤/搜索