I am not sure how to address this. If you have any ideas, please let me know. As the image shows, these are bundles from main app, and vendors js files. They both show massive unused js for both. They are mostly third party vendors and such, but I don't know how one would go about removing the unused portions.
Anything look amiss? See anything I can improve.
I am doing the following in my app.
- Code splitting, and using React.Lazy
Here is my base webpack file:
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({}),
],
};