web-dev-qa-db-fra.com

Webpack 4 - Migration de CommonsChunkPlugin avec SplitChunksPlugin

Nous avons une application de rendu de serveur traditionnelle (non SPA) où chaque page est augmentée avec vuejs

La configuration existante de Webpack 3 est

webpack.config.js

var webpack = require('webpack')
var path = require('path')

const ExtractTextPlugin = require('extract-text-webpack-plugin')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')

module.exports = {
    entry: {
        shared: './shared.js',
        pageA: './pageA.js',
        // pageB: './pageB.js',
        // pageC: './pageC.js',
        // etc
    },

    resolve: {
        alias: { vue: 'vue/dist/vue.esm.js' },
    },

    output: {
        path: path.join(__dirname, './dist'),
        filename: '[name].js',
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                exclude: /node_modules/,
                use: ExtractTextPlugin.extract({
                    use: [
                        {
                            loader: 'css-loader',
                            query: {
                                sourceMap: true,
                            },
                        },
                    ],
                }),
            },
        ],
    },

    plugins: [
        new CleanWebpackPlugin('./dist'),

        new webpack.optimize.CommonsChunkPlugin({
            name: ['shared'],
            minChunks: Infinity,
        }),

        new webpack.optimize.CommonsChunkPlugin({
            name: 'runtime',
        }),

        new ExtractTextPlugin('[name].css'),

        new CopyWebpackPlugin([{ from: 'index.html', to: '.' }]),
    ],
}

shared.js

// import shared dependencies & pollyfills
var vue = require('vue')

// import global site css file
require('./shared.css')

// initialize global defaults
// vue.setDefaults(...)

console.log('shared', { vue })

pageA.js

var vue = require('vue')

// only this page uses axios
var axios = require('axios')

console.log('pageA', { vue, axios })

shared.css

body {
    background-color: aquamarine;
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <!-- included on every page-->
    <link rel="stylesheet" href="shared.css">
</head>
<body>
    <!-- included on every page-->
    <script src="runtime.js"></script>
    <script src="shared.js"></script>

    <script src="pageA.js"></script>
</body>
</html>

Avec cette configuration

1) runtime.js contient le chargeur de webpack, de sorte que toute modification apportée à shared.js n'entraîne pas l'authentification de pageA.js dans le cache et inversement

2) shared.js contient toutes les dépendances partagées (dans ce cas, vue), ainsi que toute initialisation globale partagée pour chaque page (paramètre vue par défaut, etc.). C’est aussi le point où nous importons notre fichier css global partagé.

3) pageA.js ne contient aucune dépendance importée dans shared.js (vue dans ce cas) mais contient des dépendances qu'il importe (axios dans ce cas).

Nous n’avons pas été en mesure de reproduire cette configuration avec la variable SplitChunksPlugin

1) SplitChunksPlugin ne semble pas autoriser un point d’entrée comme point de partage.

2) Tous les exemples ont divisé TOUS les dépendances du module de nœud en un bloc fournisseur. Cela ne fonctionne pas pour nous car nous avons des centaines de pages, mais seulement quelques-unes importent une bibliothèque graphique ou un moment, etc. Nous ne voulons pas que cette bibliothèque graphique ou ce moment soit inclus dans shared.js, car il sera ensuite chargé pour toutes les pages. .

3) Il n'était pas clair non plus comment scinder le runtime dans son propre fichier

SplitChunksPlugin semble cibler un SPA où le javascript peut être chargé à la demande. Le scénario que nous traginant est-il toujours pris en charge?

10
kimsagro

Essayez-vous de migrer vers le Webpack 4?

Je trouve que le optimisation cacheGroups test option fonctionne bien pour préciser ce qui se passe où.

optimization: {
  splitChunks: {
    cacheGroups: {
      shared: {
        test: /node_modules[\\/](?!axios)/,
        name: "shared",
        enforce: true,
        chunks: "all"
      }
    }
  }
}

Tout chargera des modules de nœud (sauf axios) et devrait donc être inclus dans le point d’entrée de votre page.

3
Eliott Robson

Si vous voulez que Webpack fragmente un composant, vous devrez l'importer de manière asynchrone à partir de votre fichier d'entrée principal .

Dans mon webpack.config.js

optimization: {
  splitChunks: {
    chunks: 'all'
  },
  mergeDuplicateChunks: true,
}
module: {
  rules: [
    {
      test: /\.bundle\.js$/, //yes my output file contains the bundle in its name
      use: {
        loader: 'bundle-loader', options: {lazy: true}
      }
    }
  ]
}

Dans mon fichier d'entrée.

//this code will replace the line where you are importing this component
let Login;

// this method will go inside your component
componentWillMount() {
    require("bundle-loader!./ui/Login.jsx")((loginFile) => {
        Login = loginFile.default;
        this.setState({ loginLoaded: true });
    });
}

Si vous ne souhaitez pas l'utiliser, il existe d'autres moyens d'importer votre fichier en mode asynchrone.

0
Cleriston