web-dev-qa-db-fra.com

Comment utiliser Webpack 4 SplitChunksPlugin avec HtmlWebpackPlugin pour une application à plusieurs pages?

J'essaie d'utiliser le SplitChunksPlugin pour produire des bundles distincts pour chaque page/modèle dans un MPA. Lorsque j'utilise HtmlWebpackPlugin, j'obtiens un fichier html pour chaque page avec une balise de script pointant vers le bundle correct. C'est super! Cependant, le problème que j'ai avec mes fichiers fournisseur. Je souhaite que les fichiers html séparés pointent uniquement sur les bundles de fournisseurs dont ils ont besoin. Je ne parviens pas à faire en sorte que chaque fichier html distinct pointe vers les lots de fournisseurs corrects lorsque SplitChunksPlugin crée plusieurs lots de fournisseurs. Les bundles produits sont:

home.bundle.js
product.bundle.js
cart.bundle.js
vendors~cart~home~product.bundle.js
vendors~cart~product.bundle.js

Donc, fondamentalement, le modèle home doit faire référence à home.bundle.js, vendors ~ cart ~ home ~ product.bundle.js, et non au deuxième bundle de fournisseurs. Seuls les modèles de panier et de produit doivent faire référence aux deux offres de fournisseurs. J'utilise l'option chunks pour HtmlWebpackPlugin mais je ne peux pas l'obtenir pour extraire les bundles de fournisseurs corrects à moins que j'en fasse explicitement référence au nom comme ceci:

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

Mais cela va un peu à l'encontre du but du rendu dynamique de vos balises de script. J'ai essayé de créer un point d'entrée de fournisseur, mais cela regroupe tous mes fournisseurs ensemble. Y a-t-il une configuration simple qui me manque?

Mon webpack.config.js:

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']
        }),
    ], ...

Mes modules js:

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

le panier et le produit font également référence à la bibliothèque React:

/* cart.js */
    import jQuery from 'jquery';
    import 'bootstrap';
    import React from 'react';
    import ReactDOM from 'react-dom';

/* product.js */
    import jQuery from 'jquery';
    import 'bootstrap';
    import React from 'react';
    import ReactDOM from 'react-dom';

Exemple de sortie html home.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Webpack App</title>
  </head>
  <body>
  <script type="text/javascript" src="home.bundle.js"></script></body>
</html>
21
user1121622

Utilisez la version4 de html-webpack-plugin (qui est maintenant en version bêta), et n'incluez que le bloc d'entrée dans l'option de blocs.

npm i -D html-webpack-plugin@next

et

module.exports = {
    new HtmlWebpackPlugin({
        filename: 'home.html',
        chunks: ['home']
    }),
    new HtmlWebpackPlugin({
        filename: 'product.html',
        chunks: ['product']
    }),
    new HtmlWebpackPlugin({
        filename: 'cart.html',
        chunks: ['cart']
    }),
};

Cela inclura automatiquement les morceaux associés.

9
nilptr

Une option consiste à créer manuellement vos morceaux de fournisseur, puis à inclure celui des morceaux nécessaires pour une page dans l'option chunks de HtmlWebpackPlugin.

webpack.config.js:

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']
        }),
    ], ...

Le vendor-all le bloc consiste à intercepter toutes les autres bibliothèques de fournisseurs qui ne sont pas incluses dans les autres blocs.

2
Derek