跳到主要内容

html-webpack-plugin

html-webpack-plugin 主要有两个作用:

  • 可以生成创建html入口文件,比如单页面可以生成一个html文件入口,配置N个html-webpack-plugin可以生成N个页面入口
  • html文件中引入的外部资源如scriptlink动态添加每次compile后的hash,防止引用缓存的外部文件问题

开始


  1. 安装 html-webpack-plugin 依赖
yarn add html-webpack-plugin -D

语法


plugins: [
new HtmlWebpackPlugin({
template: './public/index.html',
filename: 'index.html',
title:'学习webpack'
}),
]
  • title: 生成的html文档的标题。配置该项,它并不会替换指定模板文件中的title元素的内容,除非html模板文件中使用了模板引擎语法来获取该配置项值。用法如下:

    • webpack.config.js 配置 html-webpack-plugin 中的 title

      plugins:[
      new HtmlWebpackPlugin({
      title:"学习 Webpack",
      template:Path.resolve(process.cwd(),'./public/index.html')
      })
      ]
    • public/index.html 模板文件使用模板引擎语法

      <!DOCTYPE html>
      <html lang="en">
      <head>
      <meta charset="UTF-8" />
      <meta http-equiv="X-UA-Compatible" content="IE=edge" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
      <title><%= htmlWebpackPlugin.options.title %></title>
      </head>
      <body></body>
      </html>
  • filename: 输出文件的文件名称,默认为index.html,不配置就是该文件名

  • template: 本地模板文件的位置,支持加载器(如handlebars、ejs、undersore、html等)

  • injext: 向template或者templateContent中注入所有静态资源,不同的配置值注入的位置不经相同

    • true或者body: 所有JavaScript资源插入到body元素的底部
    • head: 所有JavaScript资源插入到head元素中
    • false: 所有静态资源css和JavaScript都不会注入到模板文件中
  • favicon: 添加特定favicon路径到输出的html文档中,这个同title配置项,需要在模板中动态获取其路径值

  • hash: true|false,是否为所有注入的静态资源添加webpack每次编译产生的唯一hash值

  • chunks: 允许插入到模板中的一些chunk,不配置此项默认会将entry中所有的thunk注入到模板中。在配置多个页面时,每个页面注入的thunk应该是不相同的,需要通过该配置为不同页面注入不同的thunk;

  • minify: 压缩html模板

    new HtmlWebpackPlugin({
    title: "学习 Webpack",
    minify: {
    removeComments: true, // 去除注释
    collapseWhitespace: true, // 去除空格
    },
    template: Path.resolve(process.cwd(), "./public/index.html"),
    }),
  • excludeChunks: 这个与chunks配置项正好相反,用来配置不允许注入的thunk。

  • 自定义配置项: 可以自行添加属性,通过ejs动态输出到html模板中

场景


场景一、多页面

  1. webpack.config.js 配置 entryhtmlWebpackPlugin

    const Path = require("path");
    const HtmlWebpackPlugin = require("html-webpack-plugin");

    module.exports = {
    mode: "development",
    entry: {
    entry1: Path.resolve(__dirname, "src", "entry1.js"),
    entry2: Path.resolve(__dirname, "src", "entry2.js"),
    },
    output: {
    filename: "[name].js",
    path: Path.resolve(__dirname, "build"),
    },
    optimization: {
    splitChunks: {
    chunks: "all", // 代码分割应用于哪些情况: initial 同步 / async 异步 / all = initial + all
    minSize: 0, // 分割出去的代码块最小的尺寸多大,默认是 30k . 0 为不限制,只有符合分割的要求就会分割
    minChunks: 2, // 如果一个模块被多少个入口引用了才会分割, 2 为有两个才会分割
    name: false, // 打包后的名称,默认规则是 分割名称
    automaticNameDelimiter: "~", // 分隔符
    cacheGroups: {
    // 缓存组: 用来抽取满足不同规则的 chunk
    verdors: {
    chunks: "all",
    test: /node_modules/, // 如果这个模块 request 路径包含 node_modules
    priority: -10,
    },
    common: {
    chunks: "all",
    minSize: 0,
    minChunks: 2,
    priority: -20,
    },
    },
    },
    },
    plugins: [
    new HtmlWebpackPlugin({
    chunks: ["entry1"],
    filename: "index1.html",
    template: Path.resolve(__dirname, "index1.html"),
    }),
    new HtmlWebpackPlugin({
    chunks: ["entry2"],
    filename: "index2.html",
    template: Path.resolve(__dirname, "index2.html"),
    }),
    ]
    };

场景二、动态引入 CDN 依赖

  1. webpack.config.js 配置 htmlWebpackPlugin

    const Path = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const cdnConfig = [
    "https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js",
    "https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js",
    ];

    module.exports = {
    mode: "development",
    entry: Path.resolve(process.cwd(), "./src/index.js"),
    output: {
    path: Path.resolve(process.cwd(), "./build"),
    filename: "index.js",
    },
    devServer: {
    port: 8090,
    open: true,
    },
    module: {
    rules: [],
    },
    plugins: [
    new HtmlWebpackPlugin({
    title: "学习 Webpack",
    template: Path.resolve(process.cwd(), "./public/index.html"),
    cdn: cdnConfig,
    }),
    ],
    };
  2. 配置模板文件 public/index.html

    细节

    在html中配置的CDN引入脚本一定要在body内的最底部,因为:

    • 如果放在 body 上面或 header 内,则加载会阻塞整个页面渲染。
    • 如果放在 body 外,则会在业务代码被加载之后加载,模块中使用了该模块将会报错。
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title><%= htmlWebpackPlugin.options.title %></title>
    </head>
    <body>
    <% if(htmlWebpackPlugin.options.cdn){%>
    <% for(const i in htmlWebpackPlugin.options.cdn){%>
    <script src='<%= htmlWebpackPlugin.options.cdn[i] %>'></script>
    <% } %>
    <% } %>
    </body>
    </html>