跳到主要内容

html-webpack-plugin

一、认识


HtmlWebpackPlugin 是一个非常流行的 Webpack 插件,用于简化在 Webpack 打包过程中生成 HTML 文件的过程。它可以自动将 Webpack 打包生成的 JavaScriptCSS 文件注入到 HTML 文件中,从而避免手动修改 HTML 模板。

HtmlWebpackPlugin 的核心功能是自动生成 HTML 文件并注入相关的资源文件(例如 JavaScriptCSS 等),通常用于动态生成一个 HTML 文件并包含 Webpack 打包后的资源文件。

二、准备


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

三、配置


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

module.exports = {
entry: './src/index.js', // 入口文件
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html' // 通过模板生成 HTML 文件
})
]
};

三、配置项


3.1 hash

HtmlWebpackPlugin.hash 添加文件的 hash 值到输出的文件名中(例如:bundle.[hash].js)。

  • true:启用文件名哈希,防止缓存问题。

3.2 data

3.3 inject

HtmlWebpackPlugin.inject 控制如何将 JavaScriptCSS 文件注入到 HTML 文件中。

  • true(默认):默认情况下,inject: true 会把所有的 <script> 标签(通常是 JavaScript 文件)自动插入到 HTML 文件的 <body> 标签的结束前。这是常见的默认行为,因为将 <script> 放在 </body> 标签前面可以避免阻塞页面的渲染,优化页面加载速度。

  • head:将 JavaScript 文件注入到 HTML 文件的 <head> 部分。这通常用于那些需要在页面加载时优先执行的脚本(例如,一些需要在页面加载前执行的代码)。

  • body: 将 JavaScript 文件注入到 HTML 文件的 <body> 部分(默认行为)。这种方式通常用于不影响页面渲染的脚本。

  • false:不自动注入任何文件,通常需要手动插入资源。允许开发者手动控制资源插入的位置。果将 inject 设置为 falseHTMLWebpackPlugin 就不会自动注入 JavaScriptCSS 文件。此时,你需要手动在生成的 HTML 文件中添加 <script><link> 标签,指向打包后的资源文件。

语法

new HtmlWebpackPlugin({
inject: 'body', // 将这些标签插入到 <body> 底部(推荐的做法,避免阻塞渲染)。
})
new HtmlWebpackPlugin({
inject: 'head', // 将 <script> 和 <link> 标签插入到 <head> 部分。
})

3.4 minify

HtmlWebpackPlugin.minify 用于压缩生成的 HTML 文件,可以设置为 true 或提供压缩选项。例如minify: { collapseWhitespace: true, removeComments: true }:压缩 HTML,去除空格和注释。

3.5 chunks

HtmlWebpackPlugin.chunks 指定要注入的 JavaScriptCSS 文件的名称,默认为 all,即注入所有入口文件对应的资源。例如:chunks: ['app'] 只注入 app 相关的资源。

3.6 template

HtmlWebpackPlugin.template 指定一个 HTML 文件作为模板,插件会基于该模板生成 HTML 文件。如果不设置 template,插件会默认生成一个简单的 HTML 文件。

3.7 filename

HtmlWebpackPlugin.filename 指定输出的 HTML 文件的名称(默认为 index.html)。

四、使用场景


4.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"),
}),
]
};

4.2 动态引入 CDN 依赖

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>