目前为止,都是在 index.html
文件中手动引入所有资源,然而随着应用程序的不断增长,一旦开始 使用哈希值进行文件命名 并输出 多个 bundle,手动管理 index.html
文件将变得困难。使用一些插件可以更容易管理这个过程。
首先调整一下项目结构:
project
webpack-demo
|- package.json
|- package-lock.json
|- webpack.config.js
|- /dist
|- /src
|- index.js
+ |- print.js
|- /node_modules
在 src/print.js
文件中添加一些逻辑:
src/print.js
export default function printMe() {
console.log('I get called from print.js!');
}
并在 src/index.js
文件中使用这个函数:
src/index.js
import _ from 'lodash';
+import printMe from './print.js';
function component() {
const element = document.createElement('div');
+ const btn = document.createElement('button');
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
+ btn.innerHTML = 'Click me and check the console!';
+ btn.onclick = printMe;
+
+ element.appendChild(btn);
+
return element;
}
document.body.appendChild(component());
更新 dist/index.html
文件,为 webpack 分离入口文件做准备:
dist/index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
- <title>管理资源</title>
+ <title>管理输出</title>
+ <script src="./print.bundle.js"></script>
</head>
<body>
- <script src="bundle.js"></script>
+ <script src="./index.bundle.js"></script>
</body>
</html>
接下来调整配置:在 entry 添加 src/print.js
作为新的入口起点(命名为 print
),然后修改 output 使得能够根据入口起点定义的名称动态生成 bundle 名称:
webpack.config.js
const path = require('path');
module.exports = {
- entry: './src/index.js',
+ entry: {
+ index: './src/index.js',
+ print: './src/print.js',
+ },
output: {
- filename: 'bundle.js',
+ filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};
执行 npm run build
将看到输出如下:
...
[webpack-cli] Compilation finished
asset index.bundle.js 69.5 KiB [emitted] [minimized] (name: index) 1 related asset
asset print.bundle.js 316 bytes [emitted] [minimized] (name: print)
runtime modules 1.36 KiB 7 modules
cacheable modules 530 KiB
./src/index.js 406 bytes [built] [code generated]
./src/print.js 83 bytes [built] [code generated]
./node_modules/lodash/lodash.js 530 KiB [built] [code generated]
webpack 5.4.0 compiled successfully in 1996 ms
可以看到,webpack 将会生成 print.bundle.js
与 index.bundle.js
文件,即与在 index.html
文件中指定的文件名称相对应。试试在浏览器中打开 index.html
,看看点击按钮时会发生什么。
如果更改入口起点的名称,或者添加一个新的入口起点,那么会在构建时重新命名生成的 bundle,而 index.html
仍然在引用旧的名称。使用 HtmlWebpackPlugin
插件可以解决这个问题。
安装插件并且调整 webpack.config.js
文件:
npm install --save-dev html-webpack-plugin
webpack.config.js
const path = require('path');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
index: './src/index.js',
print: './src/print.js',
},
+ plugins: [
+ new HtmlWebpackPlugin({
+ title: '管理输出',
+ }),
+ ],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};
需要注意,在执行构建之前,虽然在 dist/
文件夹已经有了自定义的 index.html
文件,但是 HtmlWebpackPlugin
插件仍然会默认生成 index.html
文件,即使用新生成的 index.html
文件替换原有文件。观察执行 npm run build
后会发生什么:
...
[webpack-cli] Compilation finished
asset index.bundle.js 69.5 KiB [compared for emit] [minimized] (name: index) 1 related asset
asset print.bundle.js 316 bytes [compared for emit] [minimized] (name: print)
asset index.html 253 bytes [emitted]
runtime modules 1.36 KiB 7 modules
cacheable modules 530 KiB
./src/index.js 406 bytes [built] [code generated]
./src/print.js 83 bytes [built] [code generated]
./node_modules/lodash/lodash.js 530 KiB [built] [code generated]
webpack 5.4.0 compiled successfully in 2189 ms
代码编辑器中打开 index.html
会发现 HtmlWebpackPlugin
创建了一个全新的文件,而所有的 bundle 都已自动添加到其中。
参阅 HtmlWebpackPlugin
仓库源码以了解 HtmlWebpackPlugin
插件提供的全部功能。
/dist
文件夹可能已经注意到,由于遗留了之前的指南的代码示例,/dist
文件夹已经变得相当杂乱。webpack 生成文件并将其默认放置在 /dist
文件夹中,但是它不会追踪哪些文件是实际在项目中需要的。
通常比较推荐的做法是在每次构建前清理 /dist
文件夹,那么构建后就只会存在将要用到的文件。可以使用 output.clean
配置选项实现这个需求。
webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
index: './src/index.js',
print: './src/print.js',
},
plugins: [
new HtmlWebpackPlugin({
title: 'Output Management',
}),
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
+ clean: true,
},
};
再次执行 npm run build
后检查 /dist
文件夹。如果一切顺利,现在只会看到构建后生成的文件,而没有旧文件!
你可能会对 webpack 和 webpack 插件似乎“知道”应该生成哪些文件感兴趣。webpack 通过 manifest 追踪所有模块到输出的 bundle 之间的映射。了解 manifest 将会帮助了解如何以其他方式控制 webpack 输出
。
WebpackManifestPlugin
插件可以将 manifest 数据提取为 json 文件。
参阅 manifest 概念页面以深入了解如何在项目中使用此插件,同时 缓存 指南介绍了其与长效缓存之间的关系。
现在已经了解如何向 HTML 动态添加 bundle,接下来继续深入 开发环境 指南。如果想要深入更多相关高级话题,那么推荐前往 代码分离 指南。