Reactjs 未使用的JS数量巨大,即使代码拆分并使用react.lazy
我不知道如何解决这个问题。如果你有什么想法,请告诉我。 如图所示,这些是来自主应用程序和供应商js文件的捆绑包。 它们都显示了大量未使用的js。他们大多是第三方供应商之类的,但我不知道如何删除未使用的部分 有什么不对劲吗?看看我能改进什么。 我正在我的应用程序中执行以下操作Reactjs 未使用的JS数量巨大,即使代码拆分并使用react.lazy,reactjs,performance,webpack,single-page-application,lighthouse,Reactjs,Performance,Webpack,Single Page Application,Lighthouse,我不知道如何解决这个问题。如果你有什么想法,请告诉我。 如图所示,这些是来自主应用程序和供应商js文件的捆绑包。 它们都显示了大量未使用的js。他们大多是第三方供应商之类的,但我不知道如何删除未使用的部分 有什么不对劲吗?看看我能改进什么。 我正在我的应用程序中执行以下操作 代码拆分,并使用React.Lazy 这是我的基本网页包文件: const path = require('path'); const webpack = require('webpack'); const MiniCss
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const AsyncStylesheetWebpackPlugin = require('async-stylesheet-webpack-plugin');
const ScriptExtHtmlWebPackPlugin = require('script-ext-html-webpack-plugin');
const MomentLocalesPlugin = require('moment-locales-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const InlineManifestWebpackPlugin = require('inline-manifest-webpack-plugin');
const ProgressBarPlugin = require('progress-bar-webpack-plugin');
const FaviconsWebpackPlugin = require('favicons-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const { getConfigFileByEnv } = require('./src/utils/getConfigFileByEnv');
const imageWebpackQuery = require('./imageWebpackQuery');
const vendor = require('./vendor');
const configFile = getConfigFileByEnv();
const publicPath = process.env.CLIENT_HOST || '';
const assetsPath = `${process.env.PROTOCOL}://${publicPath}/assets/`;
module.exports = {
mode: 'production',
entry: {
vendor,
app: './src/index.js'
},
output: {
filename: '[name].[chunkhash].js',
chunkFilename: '[name].[chunkhash].chunk.js',
publicPath: assetsPath,
path: path.resolve(__dirname, 'build', 'public'), // string
},
devtool: 'source-map',
module: {
rules: [
{
test: /\.js?$/,
include: [/src/],
use: ['babel-loader'],
},
{
test: /\.s?css$/,
include: [
path.resolve(__dirname, 'src/styles'),
],
use: [
MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'resolve-url-loader', 'sass-loader'
],
},
{
test: /\.s?css$/,
exclude: [
path.resolve(__dirname, 'src/styles'),
],
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
query: {
modules: {
localIdentName: '[hash:base64]',
},
importLoaders: true,
sourceMap: true,
},
},
'postcss-loader',
'sass-loader',
],
},
{
test: /\.(eot|otf|ttf|woff|woff2)$/,
use: 'file-loader?name=[name]_[hash:base64:5].[ext]',
},
{
test: /\.(jpg|png|gif|svg)$/,
use: [
{
loader: 'file-loader',
query: {
name: '[name]_[contenthash].[ext]',
publicPath: assetsPath,
},
},
{
loader: 'image-webpack-loader',
options: imageWebpackQuery,
},
],
},
{
test: /\.(mp4)$/,
loader: 'file-loader',
query: {
name: '[name]_[contenthash].[ext]',
publicPath: assetsPath,
},
}
],
},
resolve: {
modules: ['src', 'node_modules'],
alias: {
config: path.resolve(__dirname, `src/config/`)
}
},
optimization: {
minimizer: [
new TerserPlugin({
sourceMap: true,
terserOptions: {
warnings: false,
ie8: true,
},
}),
],
splitChunks: {
cacheGroups: {
vendors: {
name: 'vendor',
// chunks: 'all',
reuseExistingChunk: true,
priority: -10,
test(module, chunks) {
const name = module.nameForCondition && module.nameForCondition();
return chunks.some((chunk) => chunk.name === 'app' && /[\\/]node_modules[\\/]/.test(name));
}
},
appStyles: {
name: 'appStyles',
test: (m, chunks) => {
return m.constructor.name === 'CssModule' && !m.issuer.rawRequest.includes('vendor.main.scss') && chunks.some((chunk) => chunk.name === 'app');
},
chunks: 'all',
enforce: true,
},
vendorStyles: {
name: 'vendorStyles',
test: (m) => {
return m.constructor.name === 'CssModule' && m.issuer.rawRequest.includes('vendor.main.scss');
},
chunks: 'all',
enforce: true,
},
default: {
priority: -20,
reuseExistingChunk: true
},
},
},
},
plugins: [
new webpack.DefinePlugin({
'process.browser': JSON.stringify(true),
__CONFIG__: JSON.stringify(configFile)
}),
new ProgressBarPlugin(),
new webpack.ContextReplacementPlugin(/\.\/locale$/, 'empty-module', false, /js$/),
new MiniCssExtractPlugin({
filename: '[name]-[contenthash].min.css',
ignoreOrder: true,
}),
new OptimizeCssAssetsPlugin({}),
new HtmlWebpackPlugin({
template: './src/document/index.html',
chunks: ['vendorStyles', 'appStyles', 'app', 'vendor'],
chunksSortMode: 'manual',
config: configFile
}),
new AsyncStylesheetWebpackPlugin({
preloadPolyfill: true,
}),
new ScriptExtHtmlWebPackPlugin({
defaultAttribute: 'async'
}),
new MomentLocalesPlugin(),
new InlineManifestWebpackPlugin(),
new webpack.NamedModulesPlugin(),
new webpack.LoaderOptionsPlugin({
minimize: true,
debug: false,
}),
new FaviconsWebpackPlugin({}),
],
};
当使用第三方代码时,简单的答案是,如果不花费大量的时间,你不能做很多事情 代码拆分实际上并不会改变未使用代码的数量,它只是意味着您稍后将交付非必要的代码(这对初始页面呈现等很有好处) 所以您有两个选择。 第一个是检查代码中“未使用”的每个函数并将其删除。显然,这是充满危险的,因为您可以很容易地删除一些在初始页面加载时可能不使用但以后需要的内容 第二个是完全使用不同的库,或者更好的是从头开始编写 正如你可能知道的,这里没有好的选择 因此,我的建议是看看是否有任何快速的成功(即,您是否加载整个库只是为了延迟加载可以用几行JS完成的图像)。如果是这样的话,找一个较小的库,或者只编写自己的实现,而不需要所有可能不需要的额外特性 然后,不用担心,集中精力发送最少数量的JS,以呈现“高于折叠”的内容,并使站点最初可用。只要网站不感到迟钝,初始(感知)页面加载速度比总加载速度更重要 我不得不承认,超过4兆字节的JS是多余的,但我不知道这是一个需要它的复杂应用程序,还是你只是选择了“错误的工作工具”(这总是一个真正的痛苦,取决于你离项目有多远!) 你还需要权衡时间和回报。我发现以下问题很有用:-