HTML Webpack Plugin(英译中)

原文地址

HTML Webpack Plugin

HTML Webpack Plugin

----为打包时简化HTML文件生成的插件

下载

npm i --save-dev html-webpack-plugin

yarn add --dev html-webpack-plugin

这是一个可以在使用webpck打包时简化你的HTML文件生成的webpack插件。它对于webpck打包尤其有用,例如在每次编译后在文件名中生成的hash值。你既可以让插件使用lodash应用你自己的模板为你生成一个HTML文件,也可以使用你自己的loader。

用法

这个插件会为你生成一个HTML5文件,并在body中使用script标签引入了你所有webpack打包文件。只要在你的webpack配置文件中添加如下促代码:

webpack.config.js

const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: 'index.js',
  output: {
    path: __dirname + '/dist',
    filename: 'index_bundle.js'
  },
  plugins: [
    new HtmlWebpackPlugin()
  ]
}

它将会生成一个 dist/index.html的文件。其中包含了以下内容:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Webpack App</title>
  </head>
  <body>
    <script src="index_bundle.js"></script>
  </body>
</html>

如果你拥有多个webpack入口,它们也都会被script标签引入到生成的HTML文件中。

如果你在webpack的出口中拥有多个CSS资源(例如,使用mini-css-extra-plugin提取出的CSS文件),它们都将会被使用<link>标签引入到HTML的头部。

如果你有其它想要使用的插件,html-webpack-plugin应当被第一个引入。

参数

你可以使用许多html-webpack-plugin的配置参数。如下:

名称 类型 默认值 描述
title String Webpack App 用于生成HTML文档的title
filename String 'index.html' 将HTML写入的文件。默认为index.html。你也可以在此外指定一个子目录(如assets/admin.html)
template String `` webpack中到模板文件的相对或绝对路径。如果存在的话默认使用src/index.ejs更多
templateContent string|Function|false false 可以代替template用于提供一个嵌入式模板。更多
templateParameters Boolean|Object|Function false 能够重写模板中的配置参数。例子
inject Boolean|String true 使用`true
scriptLoading 'blocking'|'defer' 'blocking' 当代浏览器支持非阻塞javascript加载('defer')来提高页面启动性能。
favicon String `` 为输出的HTML文件提供 favicon 路径。
meta Object {} 允许注入meta标签。例如meta: {viewport: 'width=device-width, initial-scale=1, shrink-to-fit=no'}
base Object|String|false false 注入base标签。例如base: "https://example.com/path/page.html
minify Boolean|Object mode为‘production’时为true,否则为false 用于控制输出文件的压缩方式。更多
hash Boolean false 值为true时将会为所有的script和CSS文件添加一个独特的webpack编译hash值。这对于清除缓存很有用。
cache Boolean true 仅在文件被修改后提交文件
showErrors Boolean true 错误信息将会被显示在HTML页面中。
chunks ? 允许你只添加指定的块文件(例如只添加unit-test块)
chunksSortMode String|Function auto 允许你控制块文件在被引入HTML前的顺序。可用的值有`'none'
excludeChunks Array. `` 允许你略过一些块文件(例如不添加 unit-test 块)
xhtml Boolean false 值为true时标签渲染为自动闭合(符合XHTML)

例子

下面是一个描述怎样使用以上选项的webpack config 例子:

单个HTML文件

webpack.config.js

{
  entry: 'index.js',
  output: {
    path: __dirname + '/dist',
    filename: 'index_bundle.js'
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: 'My App',
      filename: 'assets/admin.html'
    })
  ]
}

生成多个HTML文件

为了生成多个HTML文件,要在plugins数组中多次声明该插件

webpack.config.js

{
  entry: 'index.js',
  output: {
    path: __dirname + '/dist',
    filename: 'index_bundle.js'
  },
  plugins: [
    new HtmlWebpackPlugin(), // Generates default index.html
    new HtmlWebpackPlugin({  // Also generate a test.html
      filename: 'test.html',
      template: 'src/assets/test.html'
    })
  ]
}

书写你自己的模板

如果默认生成的HTML模板不能满足你的需求,你可以使用你自己的模板。最简单的方法是使用template选项,传递一个自定义的HTML文件。html-webpack-plugin将会自动注入所有需要的CSS,JS,manifest以及favicon文件到标记中。

更多使用其它模板loader的描述在文档

plugins: [
  new HtmlWebpackPlugin({
    title: 'Custom template',
    // Load a custom template (lodash by default)
    template: 'index.html'
  })
]

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
  </body>
</html>

如果你已经的拥有了一个模板loader,你可以使用它来解析模板。需要注意的是当你指定html-loader以及使用 .html 文件也会发生这种情况。

webpack.config.js

module: {
  loaders: [
    { test: /\.hbs$/, loader: "handlebars-loader" }
  ]
},
plugins: [
  new HtmlWebpackPlugin({
    title: 'Custom template using Handlebars',
    template: 'index.hbs'
  })
]

你还可以直接使用lodash语法。如果inject功能不符合你的要求而你想要完全控制你的所有资源,你可以使用

html-webpack-plugin的默认模板作为你自定义模板编写的起点。

默认情况下,下面这些变量可以在模板中使用(你可以使用templateParameters选项去扩展它们)。

  • htmlWebpackPlugin:用于声明插件的data

    • htmlWebpackPlugin.options:传递给插件的hash值。除了此插件实际使用的选项之外,你还可以使用此hash值将任意数据传递到模板。

    • htmlWebpackPlugin.tags:提前准备好的用于渲染<base>,<meta>,<script><link>标签的head标签和body标签。可以被直接在template和文字中使用。例如:

      <html>
        <head>
          <%= htmlWebpackPlugin.tags.headTags %>
        </head>
        <body>
          <%= htmlWebpackPlugin.tags.bodyTags %>
        </body>
      </html>
      
    • htmlWebpackPlugin.files:直接访问编译时所使用和文件。

      publicPath: string;
      js: string[];
      css: string[];
      manifest?: string;
      favicon?: string;
      
      
  • webpackConfig:在webpack编译时所使用的配置。例如,它可以用来获取publicPath(webpackConfig.output.pblicPath)

  • complilation:webpack编译对象。例如,可以使用它来获取已处理资源的内容,并通过compilation.assets[...].source()将它们直接内联到页面中。([例子][https://github.com/jantimon/html-webpack-plugin/blob/master/examples/inline/template.pug])

模板也可以直接内联到options对象中。

⚠️templateContent不允许对模板使用webpack加载程序,并且不会监视模板文件的修改。

webpack.config.js

new HtmlWebpackPlugin({
  templateContent: `
    <html>
      <body>
        <h1>Hello World</h1>
      </body>
    </html>
  `
})

templateContent还可以访问所有的templateParameters的值。

webpack.config.js

new HtmlWebpackPlugin({
  inject: false,
  templateContent: ({htmlWebpackPlugin}) => `
    <html>
      <head>
        ${htmlWebpackPlugin.tags.headTags}
      </head>
      <body>
        <h1>Hello World</h1>
        ${htmlWebpackPlugin.tags.bodyTags}
      </body>
    </html>
  `
})

过滤块 (Filtering Chunks)

可以用来限制仅使用某些特定的块。

webpack.config.js

plugins: [
  new HtmlWebpackPlugin({
    chunks: ['app']
  })
]

也可以通过设置excludeChunks选项来排除某些块文件。

webpack.config.js

plugins: [
  new HtmlWebpackPlugin({
    excludeChunks: [ 'dev-helper' ]
  })
]

压缩文件 (Minification)

如果minify选项被设置为true时(生产环境下默认为true),生成的HTML文件将会使用html-minifier-terser

和以下的选项进行压缩:

{
  collapseWhitespace: true,
  removeComments: true,
  removeRedundantAttributes: true,
  removeScriptTypeAttributes: true,
  removeStyleLinkTypeAttributes: true,
  useShortDoctype: true
}

可以通过传递一个对象来自定义html-minifier选项,他不会与上面的选项合并。

minify选项设为false即可在生产环境下禁用压缩。

Meta 标签

如果设置了meta选项,html-webpack-plugin将会注入meta标签。

在html-webpack-plugin的默认模板中已经注入了viewport的meta标签。

[查看所有meta标签][https://github.com/joshbuchea/HEAD#meta]

name/content meta标签

大部分的meta标签都要通过设置namecontent属性来配置。

可以使用健值对(key/value)来添加:

webpack.config.js

plugins: [
  new HtmlWebpackPlugin({
      'meta': {
        'viewport': 'width=device-width, initial-scale=1, shrink-to-fit=no',
        // 生成: <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
        'theme-color': '#4285f4'
        // 生成: <meta name="theme-color" content="#4285f4">
      }
  })
]

Base 标签

当设置了base选项时,html-webpack-plugin将会注入一个base标签。base标签默认不会被引入。

下面两种不同的方法都能插入<base href="http://example.com/some/page.html">:

new HtmlWebpackPlugin({
  'base': 'http://example.com/some/page.html'
})

new HtmlWebpackPlugin({
  'base': { 'href': 'http://example.com/some/page.html' }
})

可以用相应的值来指定target:

new HtmlWebpackPlugin({
  'base': {
    'href': 'http://example.com/some/page.html',
    'target': '_blank'
  }
})

这样会插入一个<base href="http://example.com/some/page.html" target="_blank">元素。

长期缓存 (Long Term Caching)

在文件名中添加contenthash/templatehash来处理长期缓存。

例如

plugins: [
  new HtmlWebpackPlugin({
    filename: 'index.[contenthash].html'
  })
]

contenthash/templatehash是输出文件内容的hash值。

你可以像[<hashType>:contenthash:<disgestType>:<length>]一样来配置:

  • hashTypesha1,md5,sha512中的任意一个或其它node.js支持和hash值类型。
  • disgestType:hex,base26,base32,base36,base49,base52,base62,base64中的任意一个。
  • maxlength:(以字符为单位)生成的hash值的最大长度。

默认值:[md5:contenthash:hex:9999]

事件 (Events)

该插件执行的能让其它插件更改HTML文件的tapable钩子函数。

lib/hook.js包含了所有能被传递的参数的信息。

beforeAssetTagGeneration函数
    AsyncSeriesWaterfallHook<{
        assets: {
            publicPath: string,
            js: Array<{string}>,
            css: Array<{string}>,
            favicon?: string | undefined,
            manifest?: string | undefined
        },	
        outputName: string,
        plugin: HtmlWebpackPlugin
    }>

alterAssetTags 函数
    AsyncSeriesWaterfallHook<{
        assetTags: {
            scripts: Array<HtmlTagObject>,
            styles: Array<HtmlTagObject>,
            meta: Array<HtmlTagObject>,
        },
        outputName: string,
        plugin: HtmlWebpackPlugin
    }>

afterTemplateExecution 函数
    AsyncSeriesWaterfallHook<{
      html: string,
      headTags: Array<HtmlTagObject | HtmlTagObject>,
      bodyTags: Array<HtmlTagObject | HtmlTagObject>,
      outputName: string,
      plugin: HtmlWebpackPlugin,
    }>

beforeEmit 函数
    AsyncSeriesWaterfallHook<{
      html: string,
      outputName: string,
      plugin: HtmlWebpackPlugin,
    }>

afterEmit 函数
    AsyncSeriesWaterfallHook<{
      outputName: string,
      plugin: HtmlWebpackPlugin
    }>

案例补充

plugin.js

// 如果你的插件直接依赖于html-webpack-plugin:
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 如果你只是将html-webpack-plugin作为一个附属依赖
// 你可以使用 https://github.com/tallesl/node-safe-require:
const HtmlWebpackPlugin = require('safe-require')('html-webpack-plugin');

class MyPlugin {
  apply (compiler) {
    compiler.hooks.compilation.tap('MyPlugin', (compilation) => {
      console.log('The compiler is starting a new compilation...')

      // Static Plugin interface |compilation |HOOK NAME | register listener 
      HtmlWebpackPlugin.getHooks(compilation).beforeEmit.tapAsync(
        'MyPlugin', // <-- Set a meaningful name here for stacktraces
        (data, cb) => {
          // Manipulate the content
          data.html += 'The Magic Footer'
          // Tell webpack to move on
          cb(null, data)
        }
      )
    })
  }
}

module.exports = MyPlugin

webpack.config.js

plugins: [
  new MyPlugin({ options: '' })
]

请注意,必须将回调传递给HtmlWebpackPluginData才能将其传递给侦听同一beforeEmit事件的其他任何插件。

posted @ 2020-05-06 16:17  听袁惟仁敲代码  阅读(787)  评论(0编辑  收藏  举报