在实际项目中,每次对项目打包后我们都需要手动在index.html
添加js
,当打包后的js
入口文件名更改时,我们又需要再一次修改index.html
中的js
,有没有觉得很麻烦,现在有一个插件来帮助我们,打包完之后自动生成HTML
文件,并自动引入打包后的js
文件。
1、安装依赖
npm i html-webpack-plugin html-loader --save-dev
package.json
如下:
{
"name": "webpack_test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "webpack --mode development",
"build": "webpack --mode production"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.6.4",
"@babel/plugin-transform-runtime": "^7.6.2",
"@babel/polyfill": "^7.6.0",
"@babel/preset-env": "^7.6.3",
"@babel/runtime": "^7.6.3",
"babel-loader": "^8.0.6",
"clean-webpack-plugin": "^3.0.0",
"core-js": "^3.3.2",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
"jquery": "^3.4.1",
"lodash": "^4.17.15",
"react": "^16.10.2",
"webpack": "^4.41.2",
"webpack-bundle-analyzer": "^3.6.0",
"webpack-cli": "^3.3.9"
}
}
解释一下html-webpack-plugin
和html-loader
的作用:
html-webpack-plugin
插件用于根据配置自动生成html
文件,并将打包后的js
入口文件自动引入到生成的html
中。如果有多个入口文件,它们都会被引入到html
中。如果在webpack
输出中含有任何的css
文件(例如,用mini-css-extract-plugin
提取的css
),这些文件将包含在html
头中的<link>
标签中。
参考:https://github.com/jantimon/html-webpack-plugin
html-loader
加载器用于html-webpack-plugin
在根据html
模板生成html
时加载html
模板。
参考:https://github.com/webpack-contrib/html-loader
html-webpack-plugin
和html-loader
之间没有任何依赖关系
2、配置webpack.config.js
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: {
main: './lazyloading/index.js'
},
output: {
path: path.resolve(__dirname, 'build'), // 打包文件的输出目录
filename: '[name].bundle.js', // 代码打包后的文件名
publicPath: __dirname + '/build/', // 引用的路径或者 CDN 地址
chunkFilename: '[name].js' // 代码拆分后的文件名
},
module: {
rules: [{
test: /\.html$/,
use: [{
loader: 'html-loader'
}]
}]
},
// 拆分代码配置项
optimization: {
splitChunks: {
chunks: 'all',
minSize: 30000,
maxSize: 0,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
common: {
name: 'common',
minSize: 0, //表示在压缩前的最小模块大小,默认值是 30kb,如果没设置为0,common模块就不会抽离为公共模块,因为原始大小小于30kb
minChunks: 2, // 最小公用次数
priority: 5, // 优先级
reuseExistingChunk: true // 公共模块必开启
},
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
},
plugins: [
new CleanWebpackPlugin(), // 会删除上次构建的文件,然后重新构建
new BundleAnalyzerPlugin(),
new HtmlWebpackPlugin({
// 打包输出HTML
title: '自动生成 HTML',
minify: {
// 压缩 HTML 文件
removeComments: true, // 移除 HTML 中的注释
collapseWhitespace: true, // 删除空白符与换行符
minifyCSS: true // 压缩内联 css
},
filename: 'index.html', // 生成后的文件名
template: path.resolve(__dirname, 'index.html'), // 根据此模版生成 HTML 文件
chunks: ['main'] // entry中的 main 入口才会被打包
})
]
}
主要是在配置中引入html-loader
加载器和html-webpack-plugin
插件。
由于使用了 title
选项,则需要在 template
选项对应的 html
的 title
中加入 <%= htmlWebpackPlugin.options.title %>
3、打包并测试
运行cnpm run build
打包后生成了index.html
文件,打开index.html
文件发现title
部分并没有根据配置改变,这是为什么呢?
原因是因为HtmlWebpackPlugin
支持html
以及ejs
模板语法,当在webpack
中配置了html-loader
后,就相当于全局设置以html
模板语法进行解析,HtmlWebpackPlugin
解析html
模板是以string
类型进行解析,而解析ejs
模板是以函数类型进行解析,在全局设置了html-loader
后,HtmlWebpackPlugin
就不会认识ejs
语法了,只会将它当成string
直接输出。
参考:
https://blog.csdn.net/kai_vin/article/details/88722662
https://segmentfault.com/q/1010000004555431
现在有两种解决方法:
- 注释掉配置中添加的
html-loader
,HtmlWebpackPlugin
会默认采用函数类型去解析模板。 - 将
html
模板改成ejs
模板。
第一种方式:
注释掉以下代码
// module: {
// rules: [{
// test: /\.html$/,
// use: [{
// loader: 'html-loader'
// }]
// }]
// },
打包执行:
第二种方式:
细心的朋友可能还会发现引入js入口文件的地址是一个绝对地址,但是真实项目需要部署到服务器,使用绝对地址肯定不行的,因为服务器是不可能找得到电脑本地的文件。
所以,我们要将引入的绝对路径改成相对路径,修改publicPath
即可,该字段表示引用的路径
修改webpack.config.js
:
output: {
path: path.resolve(__dirname, 'build'), // 打包文件的输出目录
filename: '[name].bundle.js', // 代码打包后的文件名
publicPath: __dirname + '/build/', // 引用的路径或者 CDN 地址
chunkFilename: '[name].js' // 代码拆分后的文件名
},
改成:
output: {
path: path.resolve(__dirname, 'build'), // 打包文件的输出目录
filename: '[name].bundle.js', // 代码打包后的文件名
publicPath: './', // 引用的路径或者 CDN 地址
chunkFilename: '[name].js' // 代码拆分后的文件名
},
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。