Webpack 代码拆分影响 Web 性能
Posted
技术标签:
【中文标题】Webpack 代码拆分影响 Web 性能【英文标题】:Webpack code splitting impacts web performance 【发布时间】:2020-10-31 06:11:48 【问题描述】:我有一个 React/Node + s-s-r 应用程序,我正在尝试创建一个生产构建,我已经设法做到了,但问题是我在构建中拥有的文件太大。 我使用最新版本的 react + webpack 4。 这是我的 webpack 配置:
clientConfig.js
const path = require('path');
const common = require('./webpack.common-config');
const clientConfig =
...common,
mode: 'production',
name: 'client',
target: 'web',
devtool: false,
entry:
client: [
'@babel/polyfill',
'./src/client.js'
],
,
output:
path: path.resolve(__dirname, 'build'),
filename: '[name].js',
,
optimization:
splitChunks:
cacheGroups:
vendor:
chunks: 'all',
name: 'vendor',
test: module => /node_modules/.test(module.resource),
enforce: true
,
common:
chunks: 'all',
name: 'client'
,
,
,
node:
fs: 'empty',
net: 'empty',
tls: 'empty',
;
module.exports = clientConfig;
serverConfig.js
const nodeExternals = require('webpack-node-externals');
const path = require('path');
const common = require('./webpack.common-config');
const serverConfig =
...common,
mode: 'production',
name: 'server',
target: 'node',
devtool: false,
externals: [nodeExternals()],
entry:
server: ['@babel/polyfill', path.resolve(__dirname, 'src', 'server.js')],
,
optimization:
splitChunks:
chunks: 'all',
,
output:
path: path.resolve(__dirname, 'build'),
filename: '[name].js',
chunkFilename: "[id].chunk.js"
,
node:
console: false,
global: false,
process: false,
Buffer: false,
__filename: false,
__dirname: false,
,
;
module.exports = serverConfig;
commonConfig.js
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const common =
module:
rules: [
test: /\.jsx?$/,
loader: 'babel-loader',
include: [path.resolve(__dirname, 'src')],
query:
presets: [
['@babel/preset-env', loose: true, modules: false],
"@babel/preset-react"
],
plugins: [
"@babel/plugin-proposal-class-properties"
]
,
,
test: /\.css$/,
use: [
loader: MiniCssExtractPlugin.loader,
,
'css-loader'
]
,
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: [
loader: 'file-loader',
options:
name: '[name].[ext]',
outputPath: 'fonts/'
]
]
,
plugins: [
new OptimizeCSSAssetsPlugin(),
new MiniCssExtractPlugin(
filename: "styles.css",
)
],
optimization:
minimize: true,
minimizer: [new TerserPlugin()]
,
;
module.exports = common;
还有另一个文件,它基本上合并了客户端和服务器配置。
我运行npm run build
,然后运行webpack -p --mode=production --optimize-minimize && node ./build/server.js
我收到以下警告:
WARNING in asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
This can impact web performance.
Assets:
vendor.js (667 KiB)
WARNING in entrypoint size limit: The following entrypoint(s) combined asset size exceeds the recommended limit (244 KiB). This can impact web performance.
Entrypoints:
client (928 KiB)
vendor.js
styles.css
client.js
任何关于上述尺寸警告的建议或想法都会很棒!谢谢!
【问题讨论】:
【参考方案1】:我建议您尝试使用core-js
而不是babel/pollyfill
,这可以帮助您减小捆绑包大小。
另外,我建议您尝试使用支持 s-s-r 的 react-loadable
进行动态导入。拆分代码有不同的策略。你可以阅读更多here(最重要的一个)
如果您使用 CSS 框架(例如 bootstrap),您应该只使用您需要的部分,避免全部导入。有一个用于清除未使用的 CSS 的工具,名为 purgecss,但请谨慎使用,您必须知道自己在做什么。
如果您使用诸如 lodash 或 material-ui 之类的库,您应该专门导入您的模块以避免将所有包导入到您的包中。
表达式:
import debounce from 'lodash/debounce'
npm dedup
或 yarn dedup
可以帮助删除包中的重复依赖项。
【讨论】:
感谢您的建议,我会从上面查看工具,看看是否可以做些什么来改进我的解决方案。【参考方案2】:你可以通过调整你的 babel 配置来减少一些。例如,为“preset-env”指定一些选项,例如bugfixes、targets
(如果您不支持旧版浏览器),并使用corejs
polyfills 而不是babel/polyfill
。
"@babel/preset-env",
"targets":
"browsers": [
"last 2 years"
]
,
"bugfixes": true,
"useBuiltIns": "entry", // experiment with "entry" vs. "usage"
"corejs": 3
...
根据您的代码库,babel-plugin-transform-runtime 也可能有所帮助。我有一些项目产生了重大影响,但其他项目没有。
"@babel/plugin-transform-runtime",
"corejs": 3,
"version": "7.9.2"
Webpack 的其他选项包括使用 webpack-cdn-plugin。这可以大大减少您的供应商捆绑包大小。当然,用户仍然需要下载这些相同的库,但它们会被缓存,并且不需要在每次您的捆绑包更改或更新时重新下载。
通过指定runtimeChunk: true
可以节省一点额外费用,并且可以选择在 index.html 中内联该块
new HTMLWebpackPlugin(
inlineSource: 'runtime~.+[.]js',
...
和html-webpack-inline-source-plugin 或类似的。
【讨论】:
【参考方案3】:您可以使用splitChunks 将文件拆分为较小的大小以消除警告:
optimization:
splitChunks:
chunks: 'all',
minSize: 10000,
maxSize: 250000,
查看更多minSize 和maxSize。
如果你想禁用警告,你可以使用performance
performance:
hints: false
或删除某些大小限制(如 1 MB)的警告:
performance:
maxAssetSize: 1000000
【讨论】:
以上是关于Webpack 代码拆分影响 Web 性能的主要内容,如果未能解决你的问题,请参考以下文章