Как использовать Webpack 4 SplitChunksPlugin с HtmlWebpackPlugin для многостраничного приложения?
Я пытаюсь использовать SplitChunksPlugin для создания отдельных пакетов на каждую страницу/шаблон в MPA. Когда я использую HtmlWebpackPlugin, я получаю html файл для каждой страницы с тегом скрипта, указывающим на правильный набор. Это прекрасно! Тем не менее, проблема, с которой я столкнулась, связана с файлами моего поставщика. Я хочу, чтобы отдельные html файлы указывали только на нужные пакеты поставщиков. Я не могу получить каждый отдельный файл html, чтобы указать на правильные пакеты поставщиков, когда SplitChunksPlugin создает несколько пакетов поставщиков. Полученные пучки:
home.bundle.js
product.bundle.js
cart.bundle.js
vendors~cart~home~product.bundle.js
vendors~cart~product.bundle.js
Поэтому в основном домашний шаблон должен ссылаться на home.bundle.js, поставщиков ~ cart ~ home ~ product.bundle.js, а не на второй комплект поставщиков. Только шаблоны корзины и продукта должны ссылаться на пакеты поставщиков. Я использую параметр chunks для HtmlWebpackPlugin, но не могу заставить его вытащить правильные пакеты поставщиков, если я явно не укажу его имя так:
chunks: ['vendors~cart~home~product.bundle','home']
Но этот вид поражает цель динамического рендеринга ваших тегов скриптов. Я попытался создать точку входа поставщика, но это объединяет всех моих продавцов. Есть ли какая-то простая конфигурация, которую мне не хватает?
Мой 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']
}),
], ...
Мои модули js:
/* home.js */
import jQuery from 'jquery';
import 'bootstrap';
тележка и продукт также ссылаются на реакционную библиотеку:
/* 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';
Пример html output 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>
Ответы
Ответ 1
Один из вариантов заключается в том, чтобы вручную создать куски вашего поставщика, а затем включить любой из этих фрагментов, необходимых для страницы в опции chunks
для 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']
}),
], ...
Компонент vendor-all
должен поймать любые другие библиотеки поставщиков, которые не включены в другие куски.
Ответ 2
Используйте версию4 html-webpack-plugin (которая сейчас находится в бета-версии) и включайте только фрагмент ввода в опции chunks.
npm i -D [email protected]
а также
module.exports = {
new HtmlWebpackPlugin({
filename: 'home.html',
chunks: ['home']
}),
new HtmlWebpackPlugin({
filename: 'product.html',
chunks: ['product']
}),
new HtmlWebpackPlugin({
filename: 'cart.html',
chunks: ['cart']
}),
};
Это будет включать связанные куски автоматически.