html-webpack-plugin詳解

引言

咱們來看看主要做用:javascript

爲html文件中引入的外部資源如scriptlink動態添加每次compile後的hash,防止引用緩存的外部文件問題css

能夠生成建立html入口文件,好比單頁面能夠生成一個html文件入口,配置Nhtml-webpack-plugin能夠生成N個頁面入口html

html-webpack-plugin

插件的基本做用就是生成html文件。原理很簡單:java

`entry``extract-text-webpack-plugin``template``templateContent``link``head``script``head``body`將 webpack中配置的相關入口chunk  和 抽取的css樣式   插入到該插件提供的或者配置項指定的內容基礎上生成一個html文件,具體插入方式是將樣式插入到元素中,插入到或者中。

實例化該插件時能夠不配置任何參數,例以下面這樣:webpack

var HtmlWebpackPlugin = require('html-webpack-plugin')
webpackconfig = {
    plugins: [
        new HtmlWebpackPlugin()
    ]
}

  

不配置任何選項的html-webpack-plugin插件,他會默認將webpack中的entry配置全部入口thunk和extract-text-webpack-plugin抽取的css樣式都插入到文件指定的位置。例如上面生成的html文件內容以下:git

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Webpack App</title>
  <link href="index-af150e90583a89775c77.css" rel="stylesheet"></head>
  <body>
  <script type="text/javascript" src="common-26a14e7d42a7c7bbc4c2.js"></script>
  <script type="text/javascript" src="index-af150e90583a89775c77.js"></script></body>
</html>

  

固然可使用具體的配置項來定製化一些特殊的需求,那麼插件有哪些配置項呢?github

html-webpack-plugin配置項

插件提供的配置項比較多,經過源碼能夠看出具體的配置項以下:web

 1 this.options = _.extend({
 2   template: path.join(__dirname, 'default_index.ejs'),
 3   templateParameters: templateParametersGenerator,
 4   filename: 'index.html',
 5   hash: false,
 6   inject: true,
 7   compile: true,
 8   favicon: false,
 9   minify: false,
10   cache: true,
11   showErrors: true,
12   chunks: 'all',
13   excludeChunks: [],
14   chunksSortMode: 'auto',
15   meta: {},
16   title: 'Webpack App',
17   xhtml: false
18 }, options);
: 生成的html文檔的標題。配置該項,它並不會替換指定模板文件中的title元素的內容,除非html模板文件中使用了模板引擎語法來獲取該配置項值,以下ejs模板語法形式:title
<title></title>{%= o.htmlWebpackPlugin.options.title %}

filename:輸出文件的文件名稱,默認爲index.html,不配置就是該文件名;此外,還能夠爲輸出文件指定目錄位置(例如'html/index.html')數組

關於filename補充兩點:

一、filename配置的html文件目錄是相對於webpackConfig.output.path路徑而言的,不是相對於當前項目目錄結構的。
二、指定生成的html文件內容中的linkscript路徑是相對於生成目錄下的,寫路徑的時候請寫生成目錄下的相對路徑。緩存

template: 本地模板文件的位置,支持加載器(如handlebars、ejs、undersore、html等),如好比 handlebars!src/index.hbs

關於template補充幾點:

一、template配置項在html文件使用file-loader時,其所指定的位置找不到,致使生成的html文件內容不是指望的內容。
二、爲template指定的模板文件沒有指定任何loader的話,默認使用ejs-loader。如template: './index.html',若沒有爲.html指定任何loader就使用ejs-loader

templateContent: string|function,能夠指定模板的內容,不能與template共存。配置值爲function時,能夠直接返回html字符串,也能夠異步調用返回html字符串。

inject:向template或者templateContent中注入全部靜態資源,不一樣的配置值注入的位置不經相同。

一、true或者body:全部JavaScript資源插入到body元素的底部
二、head: 全部JavaScript資源插入到head元素中
三、false: 全部靜態資源css和JavaScript都不會注入到模板文件中

 

favicon: 添加特定favicon路徑到輸出的html文檔中,這個同title配置項,須要在模板中動態獲取其路徑值

hash:true|false,是否爲全部注入的靜態資源添加webpack每次編譯產生的惟一hash值,添加hash形式以下所示:
html <script type="text/javascript" src="common.js?a3e1396b501cdd9041be"></script>

chunks:容許插入到模板中的一些chunk,不配置此項默認會將entry中全部的thunk注入到模板中。在配置多個頁面時,每一個頁面注入的thunk應該是不相同的,須要經過該配置爲不一樣頁面注入不一樣的thunk;

excludeChunks: 這個與chunks配置項正好相反,用來配置不容許注入的thunk。

chunksSortMode: none | auto| function,默認auto; 容許指定的thunk在插入到html文檔前進行排序。
>function值能夠指定具體排序規則;auto基於thunk的id進行排序; none就是不排序

xhtml: true|fasle, 默認false;是否渲染link爲自閉合的標籤,true則爲自閉合標籤

cache: true|fasle, 默認true; 若是爲true表示在對應的thunk文件修改後就會emit文件

showErrors: true|false,默認true;是否將錯誤信息輸出到html頁面中。這個頗有用,在生成html文件的過程當中有錯誤信息,輸出到頁面就能看到錯誤相關信息便於調試。

minify: {....}|false;傳遞 html-minifier 選項給 minify 輸出,false就是不使用html壓縮,minify具體配置參數請點擊html-minifier

下面的是一個用於配置這些屬性的一個例子:

    new HtmlWebpackPlugin({
          title:'rd平臺',
          template: 'src/index.html', // 源模板文件
          filename: './index.html', // 輸出文件【注意:這裏的根路徑是module.exports.output.path】
          showErrors: true,
          inject: 'body',
          chunks: ["common",'index']
      })

  

配置多個html頁面

html-webpack-plugin的一個實例生成一個html文件,若是單頁應用中須要多個頁面入口,或者多頁應用時配置多個html時,那麼就須要實例化該插件屢次;

即有幾個頁面就須要在webpack的plugins數組中配置幾個該插件實例:

……
    plugins: [
        new HtmlWebpackPlugin({
             template: 'src/html/index.html',
              excludeChunks: ['list', 'detail']
        }),
        new HtmlWebpackPlugin({
            filename: 'list.html',
            template: 'src/html/list.html',
            thunks: ['common', 'list']
        }), 
        new HtmlWebpackPlugin({
          filename: 'detail.html',
          template: 'src/html/detail.html',
           thunks: ['common', 'detail']
        })
    ]
    ...

  

如上例應用中配置了三個入口頁面:index.html、list.html、detail.html;而且每一個頁面注入的thunk不盡相同;相似若是多頁面應用,就須要爲每一個頁面配置一個;

配置自定義的模板

不帶參數的html-webpack-plugin默認生成的html文件只是將thunk和css樣式插入到文檔中,可能不能知足咱們的需求;

另外,如上面所述,三個頁面指定了三個不一樣html模板文件;在項目中,可能全部頁面的模板文件能夠共用一個,由於html-webpack-plugin插件支持不一樣的模板loader,因此結合模板引擎來共用一個模板文件有了可能。

因此,配置自定義模板就派上用場了。具體的作法,藉助於模板引擎來實現,例如插件沒有配置loader時默認支持的ejs模板引擎,下面就以ejs模板引擎爲例來講明;

例如項目中有2個入口html頁面,它們能夠共用一個模板文件,利用ejs模板的語法來動態插入各自頁面的thunk和css樣式,代碼能夠這樣:

<!DOCTYPE html>
<html style="font-size:20px">
<head>
    <meta charset="utf-8">
    <title><%= htmlWebpackPlugin.options.title %></title>
    <% for (var css in htmlWebpackPlugin.files.css) { %>
    <link href="<%=htmlWebpackPlugin.files.css[css] %>" rel="stylesheet">
    <% } %>
</head>
<body>
<div id="app"></div>
<% for (var chunk in htmlWebpackPlugin.files.chunks) { %>
<script type="text/javascript" src="<%=htmlWebpackPlugin.files.chunks[chunk].entry %>"></script>
<% } %>
</body>
</html>

  

你可能會對代碼中的上下文htmlWebpackPlugin數據感到迷惑,這是啥東東?其實這是html-webpack-plugin插件在生成html文件過程當中產生的數據,這些數據對html模板文件是可用的,而且咱們看<%%>是否是給java裏面的jsp差很少了。

自定義模板上下文數據

html-webpack-plugin在生成html文件的過程當中,插件會根據配置生成一個對當前模板可用的特定數據,模板語法能夠根據這些數據來動態生成html文件的內容。

那麼,插件生成的特殊數據格式是什麼,生成的哪些數據呢?從源碼或者其官網都給出了答案。從源碼中能夠看出模板引擎具體能夠訪問的數據以下:

var templateParams = {
        compilation: compilation,
        webpack: compilation.getStats().toJson(),
        webpackConfig: compilation.options,
        htmlWebpackPlugin: 
          files: assets,
          options: self.options
        }
      };

  

從中能夠看出,有四個主要的對像數據。其中compilation爲全部webpack插件提供的均可以訪問的一個編譯對象,此處就不太作介紹,具體能夠本身查資料。下面就對剩下的三個對象數據進行說明。

webpack

webpack的stats對象;注意一點:

這個能夠訪問的stats對象是htm文件生成時所對應的stats對象,而不是webpack運行完成後所對應的整個stats對象。

webpackConfig

webpack的配置項;經過這個屬性能夠獲取webpack的相關配置項,如經過webpackConfig.output.publicPath來獲取publicPath配置。固然還能夠獲取其餘配置內容。

htmlWebpackPlugin

html-webpack-plugin插件對應的數據。它包括兩部分:

htmlWebpackPlugin.files: 這次html-webpack-plugin插件配置的chunk和抽取的css樣式該files值實際上是webpack的stats對象的assetsByChunkName屬性表明的值,該值是插件配置的chunk塊對應的按照webpackConfig.output.filename映射的值。例如對應上面配置插件各個屬性配置項例子中生成的數據格式以下:

"htmlWebpackPlugin": {
  "files": {
    "css": [ "inex.css" ],
    "js": [ "common.js", "index.js"],
    "chunks": {
      "common": {
        "entry": "common.js",
        "css": [ "index.css" ]
      },
      "index": {
        "entry": "index.js",
        "css": ["index.css"]
      }
    }
  }
}

 

這樣,就能夠是用以下模板引擎來動態輸出script腳本

<% for (var chunk in htmlWebpackPlugin.files.chunks) { %>
<script type="text/javascript" src="<%=htmlWebpackPlugin.files.chunks[chunk].entry %>"></script>
<% } %>

  

htmlWebpackPlugin.options: 傳遞給插件的配置項,具體的配置項如上面插件配置項小節所描述的。

插件事件

不知道你發現沒有,html-webpack-plugin插件在插入靜態資源時存在一些問題:

  • 在插入js資源只能插入head或者body元素中,不能一些插入head中,另外一些插入body
  • 不支持在html中文件內聯*,例如在文件的某個地方用<script src="xxx.js?__inline"></script>來內聯外部腳本

爲此,有人專門給插件做者提問了這個問題;對此插件做者提供了插件事件,容許其餘插件來改變html文件內容。具體的事件以下:

Async(異步事件):

before    * html-webpack-plugin--html-generation
before    * html-webpack-plugin--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的內容。所以,要用這些事件須要提供一個webpack插件。例以下面定義的MyPlugin插件。

function MyPlugin(options) {
  // Configure your plugin with options...
}
 
MyPlugin.prototype.apply = function(compiler) {
  // ...
  compiler.plugin('compilation', function(compilation) {
    console.log('The compiler is starting a new compilation...');
 
    compilation.plugin('html-webpack-plugin-before-html-processing', function(htmlPluginData, callback) {
      htmlPluginData.html += 'The magic footer';
      callback(null, htmlPluginData);
    });
  });
 
};

module.exports = MyPlugin;

  

 
 

而後,在webpack.config.js文件中配置Myplugin信息:

plugins: [
  new MyPlugin({options: ''})
]
相關文章
相關標籤/搜索