webpack 提取页面公共资源
基础库分离
- 思路路:将 react、react-dom 基础 包通过 cdn 引⼊入,不不打⼊入 bundle 中
- ⽅方法:使⽤用 html-webpack- externals-plugin
const HtmlWebpackExternalPlugin = require('html-webpack-externals-plugin');
plugins: [
new HtmlWebpackExternalPlugin([
{
module: 'react',
entry: 'https://unpkg.com/react@16/umd/react.development.js',
global: 'React',
},
{
module: 'react-dom',
entry: 'https://unpkg.com/react-dom@16/umd/react-dom.development.js',
global: 'ReactDOM'
}
])
]
利用 SplitChunksPlugin 进行公共脚本分离
Webpack4 内置的,替代CommonsChunkPlugin插件
chunks 参数说明:
- async 异步引⼊入的库进⾏行行分离(默认)
- initial 同步引⼊入的库进⾏行行分离
- all 所有引⼊入的库进⾏行行分离(推荐)
module.exports = {
optimization: {
splitChunks: {
chunks: "async",
minSize: 30000,
maxSize: 0,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: "~",
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
},
},
},
},
};
利用 SplitChunksPlugin 分离基础包
test: 匹配出需要分离的包
module.exports = {
optimization: {
splitChunks: {
cacheGroups: {
commons: {
test: /(react|react-dom)/,
name: "vendors",
chunks: "all",
},
},
},
},
};
利利⽤用 SplitChunksPlugin 分离⻚页⾯面公共⽂文件
minChunks: 设置最⼩小引⽤用次数为2次
minuSize: 分离的包体积的⼤大⼩小
module.exports = {
optimization: {
splitChunks: {
minSize: 0,
cacheGroups: {
commons: {
name: "commons",
chunks: "all",
minChunks: 2,
},
},
},
},
};
完整的webpack.prod.js
'use strict';
const glob = require('glob');
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin');
const setMPA = () => {
const entry = {};
const htmlWebpackPlugins = [];
const entryFiles = glob.sync(path.join(__dirname, './src/*/index.js'));
Object.keys(entryFiles)
.map((index) => {
const entryFile = entryFiles[index];
// '/Users/cpselvis/my-project/src/index/index.js'
const match = entryFile.match(/src\/(.*)\/index\.js/);
const pageName = match && match[1];
entry[pageName] = entryFile;
htmlWebpackPlugins.push(
new HtmlWebpackPlugin({
inlineSource: '.css$',
template: path.join(__dirname, `src/${pageName}/index.html`),
filename: `${pageName}.html`,
chunks: ['vendors', pageName],
inject: true,
minify: {
html5: true,
collapseWhitespace: true,
preserveLineBreaks: false,
minifyCSS: true,
minifyJS: true,
removeComments: false
}
})
);
});
return {
entry,
htmlWebpackPlugins
}
}
const { entry, htmlWebpackPlugins } = setMPA();
module.exports = {
entry: entry,
output: {
path: path.join(__dirname, 'dist'),
filename: '[name]_[chunkhash:8].js'
},
mode: 'production',
module: {
rules: [
{
test: /.js$/,
use: [
'babel-loader',
// 'eslint-loader'
]
},
{
test: /.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader'
]
},
{
test: /.less$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'less-loader',
{
loader: 'postcss-loader',
options: {
plugins: () => [
require('autoprefixer')({
browsers: ['last 2 version', '>1%', 'ios 7']
})
]
}
},
{
loader: 'px2rem-loader',
options: {
remUnit: 75,
remPrecision: 8
}
}
]
},
{
test: /.(png|jpg|gif|jpeg)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name]_[hash:8].[ext]'
}
}
]
},
{
test: /.(woff|woff2|eot|ttf|otf)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name]_[hash:8][ext]'
}
}
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name]_[contenthash:8].css'
}),
new OptimizeCSSAssetsPlugin({
assetNameRegExp: /\.css$/g,
cssProcessor: require('cssnano')
}),
new CleanWebpackPlugin(),
new HtmlWebpackExternalsPlugin({
externals: [
{
module: 'react',
entry: 'https://11.url.cn/now/lib/16.2.0/react.min.js',
global: 'React',
},
{
module: 'react-dom',
entry: 'https://11.url.cn/now/lib/16.2.0/react-dom.min.js',
global: 'ReactDOM',
},
]
})
].concat(htmlWebpackPlugins),
};