关于javascript:如何将Webpack 4 SplitChunksPlugin与HtmlWebpackPlugin一起用于多页应用程序?

How to use Webpack 4 SplitChunksPlugin with HtmlWebpackPlugin for Multiple Page Application?

我正在尝试利用SplitChunksPlugin在MPA中的每个页面/模板上生成单独的包。当我使用HtmlWebpackPlugin时,我会为每个页面获取一个html文件,并带有指向正确捆绑软件的脚本标签。这太棒了!但是,我遇到的麻烦是我的供应商文件。我希望单独的html文件仅指向他们需要的供应商捆绑包。当SplitChunksPlugin创建多个供应商捆绑包时,我无法获得每个单独的html文件来指向正确的供应商捆绑包。产生的束是:

1
2
3
4
5
home.bundle.js
product.bundle.js
cart.bundle.js
vendors~cart~home~product.bundle.js
vendors~cart~product.bundle.js

因此,基本上,主页模板应引用home.bundle.js,vendors?cart?home?product.bundle.js,而不是第二个捆绑销售商。仅购物车和产品模板应同时引用两个供应商捆绑包。我正在使用HtmlWebpackPlugin的chunks选项,但是除非我明确引用它的名称,否则无法获取正确的供应商捆绑包,如下所示:

1
chunks: ['vendors~cart~home~product.bundle','home']

但这有点违反了动态呈现脚本标签的目的。我曾尝试创建一个供应商入口点,但这将我所有的供应商混为一谈。
我缺少一些简单的配置吗?

我的webpack.config.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
const path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const Visualizer = require('webpack-visualizer-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    mode: 'development',
    devtool: 'cheap-module-eval-source-map',
    entry: {
        home: './src/js/page-types/home.js',
        product: './src/js/page-types/product.js',
        cart: './src/js/page-types/cart.js'
    },
    output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist/js')
    },
    optimization: {
        splitChunks: {
            chunks: 'all'
        }
    },
    plugins: [
        new CleanWebpackPlugin(['dist']),
        new Visualizer(),
        new HtmlWebpackPlugin({
            filename: 'home.html',
            chunks: ['vendors','home']
        }),
        new HtmlWebpackPlugin({
            filename: 'product.html',
            chunks: ['vendors','product']
        }),
        new HtmlWebpackPlugin({
            filename: 'cart.html',
            chunks: ['vendors~cart~product','cart']
        }),
    ], ...

我的js模块:

1
2
3
/* home.js */
    import jQuery from 'jquery';
    import 'bootstrap';

购物车和产品还引用了反应库:

1
2
3
4
5
/* cart.js */
    import jQuery from 'jquery';
    import 'bootstrap';
    import React from 'react';
    import ReactDOM from 'react-dom';

1
2
3
4
5
/* product.js */
    import jQuery from 'jquery';
    import 'bootstrap';
    import React from 'react';
    import ReactDOM from 'react-dom';

示例html输出home.html:

1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    Webpack App
  </head>
  <body>
  <script type="text/javascript" src="home.bundle.js"></body>
</html>


使用html-webpack-plugin的version4(现在处于beta版),并且仅在块选项中包括条目块。

1
npm i -D html-webpack-plugin@next

1
2
3
4
5
6
7
8
9
10
11
12
13
14
module.exports = {
    new HtmlWebpackPlugin({
        filename: 'home.html',
        chunks: ['home']
    }),
    new HtmlWebpackPlugin({
        filename: 'product.html',
        chunks: ['product']
    }),
    new HtmlWebpackPlugin({
        filename: 'cart.html',
        chunks: ['cart']
    }),
};

这将自动包括相关的块。


一个选项是手动创建您的供应商块,然后在HtmlWebpackPluginchunks选项中包括页面所需的那些块中的任何一个。

webpack.config.js:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
const path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const Visualizer = require('webpack-visualizer-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    mode: 'development',
    devtool: 'cheap-module-eval-source-map',
    entry: {
        home: './src/js/page-types/home.js',
        product: './src/js/page-types/product.js',
        cart: './src/js/page-types/cart.js'
    },
    output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist/js')
    },
    optimization: {
        splitChunks: {
            cacheGroups: {
                'vendor-bootstrap': {
                    name: 'vendor-bootstrap',
                    test: /[\\\\/]node_modules[\\\\/](jquery|bootstrap)[\\\\/]/,
                    chunks: 'initial',
                    priority: 2
                },
                'vendor-react': {
                    name: 'vendor-react',
                    test: /[\\\\/]node_modules[\\\\/]react.*?[\\\\/]/,
                    chunks: 'initial',
                    priority: 2
                },
                'vendor-all': {
                    name: 'vendor-all',
                    test: /[\\\\/]node_modules[\\\\/]/,
                    chunks: 'initial',
                    priority: 1
                },
            }
        }
    },
    plugins: [
        new CleanWebpackPlugin(['dist']),
        new Visualizer(),
        new HtmlWebpackPlugin({
            filename: 'home.html',
            chunks: ['vendor-bootstrap', 'vendor-all', 'home']
        }),
        new HtmlWebpackPlugin({
            filename: 'product.html',
            chunks: ['vendor-bootstrap', 'vendor-react', 'vendor-all', 'product']
        }),
        new HtmlWebpackPlugin({
            filename: 'cart.html',
            chunks: ['vendor-bootstrap', 'vendor-react', 'vendor-all', 'cart']
        }),
    ], ...

vendor-all块将捕获其他块中未包括的任何其他供应商库。