webpack 输出管理

发布时间 2023-08-30 17:11:50作者: 软匠

管理输出

到目前为止,我们都是在 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: {
    index: './src/index.js',
    print: './src/print.js',
  },
  output: {
    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 来解决这个问题。

设置 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 都自动添加到其中。

清理 /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 文件夹。如果一切顺利,现在只会看到构建后生成的文件,而没有旧文件!

manifest

你可能会很感兴趣,webpack 和 webpack 插件似乎“知道”应该生成哪些文件 —— webpack 通过 manifest 追踪所有模块到输出 bundle 之间的映射。如果你想要知道如何以其他方式来控制 webpack 输出,了解 manifest 是个好的开始。

WebpackManifestPlugin 插件可以将 manifest 数据提取为一个 json 文件以供使用。