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?
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.
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.