Just upgraded webpack 4 to webpack 5 on our react project that only required a few minor tweaks to get it to actually build. After being built and deployed, it appears that the code splitting aspect is working, but it also appears that a main app.js file is still being created and then fetched upon each load/reload of the page.
Here is what I believe is the applicable code in our webpack config:
this.config = {
devServer: {
static: ['./public/', './src/'],
historyApiFallback: true,
hot: true,
devMiddleware: {
publicPath: '/assets/js/',
},
port: 2612,
host: 'localhost'
},
cache: false,
devtool: 'source-map',
entry: ['babel-polyfill', './index.js'],
output: {
path: root('app'),
publicPath: '',
filename: 'assets/js/app.js',
chunkFilename: 'assets/js/[id].[contenthash].chunk.js',
// Point sourcemap entries to original disk location (format as URL on Windows)
devtoolModuleFilenameTemplate: (info) =>
path.relative('src', info.absoluteResourcePath).replace(/\\/g, '/')
},
optimization: {
splitChunks: {
chunks: 'async',
minSize: 20000,
minChunks: 1,
maxAsyncRequests: 30,
maxInitialRequests: 30,
enforceSizeThreshold: 50000,
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
reuseExistingChunk: true,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
minimize: true,
minimizer: [
new TerserPlugin(),
new CssMinimizerPlugin()
]
},
resolve: {
alias: {
assets: `${this.srcPathAbsolute}/assets/`,
actions: `${this.srcPathAbsolute}/actions/`,
components: `${this.srcPathAbsolute}/components/`,
constants: `${this.srcPathAbsolute}/constants`,
config: `${this.srcPathAbsolute}/config/${this.env}.js`,
containers: `${this.srcPathAbsolute}/containers/`,
reducers: `${this.srcPathAbsolute}/reducers/`,
app: `${this.srcPathAbsolute}/app/`,
styles: `${this.srcPathAbsolute}/styles/`,
themes: `${this.srcPathAbsolute}/themes/`,
utilities: `${this.srcPathAbsolute}/utilities/`
},
extensions: ['.js', '.jsx'],
modules: [this.srcPathAbsolute, 'node_modules'],
fallback: {
"stream": false,
"zlib": false,
"assert": false,
"buffer": require.resolve('buffer/'),
"process": require.resolve('process/browser'),
"util": require.resolve('util/'),
"stream": require.resolve("stream-browserify"),
}
},
module: {
rules: [
{
enforce: 'pre',
test: /\.js?$/,
include: this.srcPathAbsolute,
use: {
loader: 'babel-loader'
// options: {
// presets: ['es2015', 'react', 'stage-2']
// }
}
},
{
test: /^.((?!cssmodule).)*\.css$/,
use: [{ loader: 'style-loader' }, { loader: 'css-loader' }]
},
{
test: /\.(png|jpg|gif|mp4|ogg|svg|woff|woff2|ttf|eot|ico)$/,
use: [
{
loader: 'file-loader',
options: {
outputPath: 'assets/fonts'
}
}
]
},
{
test: /^.((?!cssmodule).)*\.styl$/,
use: [{ loader: 'style-loader' }, { loader: 'css-loader' }, { loader: 'stylus-loader' }]
},
{
test: /\.cssmodule\.(sass|scss)$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: cssModulesQuery
},
{ loader: 'sass-loader' }
]
},
{
test: /\.cssmodule\.css$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: cssModulesQuery
}
]
},
{
test: /\.cssmodule\.less$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: cssModulesQuery
},
{ loader: 'less-loader' }
]
},
{
test: /\.cssmodule\.styl$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: cssModulesQuery
},
{ loader: 'stylus-loader' }
]
},
{
test: /\.js?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
extends: path.join(__dirname, '../../.babelrc'),
cacheDirectory: true
}
}
},
{
test: /^.((?!cssmodule).)*\.(sass|scss)$/,
use: [{ loader: 'style-loader' }, { loader: 'css-loader' }, { loader: 'sass-loader' }]
},
{
test: /^.((?!cssmodule).)*\.less$/,
use: [{ loader: 'style-loader' }, { loader: 'css-loader' }, { loader: 'less-loader' }]
}
]
},
};
This config is creating a TON of small (5-100kb) chunked out files and map files that look something like this: 250.2edde99552a0e46f7950.chunk.js 250.2edde99552a0e46f7950.chunk.js.map
and then what appears to be a main app.js file (1.8MB) and app.js.map...
I guess what I don't understand is why does the app.js need to be fetched each time (or why this file is even being created at all) if we are supposedly code splitting here and only fetching the necessary chunks in real time of what we actually need.
The small chunks are only taking a few milleseconds to fetch for each one, but that initial fetch of the app.js is 2-3 seconds since it is so large so I'd rather avoid that if possible.
Full disclosure is that I am a webpack newbie so I'm sure there is something I am missing in the docs or something along the build process that might be causing this.
EDIT HERE:
Maybe if it helps I thought about including a screenshot of the network requests happening over the course of our ridiculously long load time (5+ seconds) on the site with the app.js vs. the individual chunks: