Webpack 4 code splitting not working with React.lazy - reactjs

Hi all I am using webpack 4 and having issues in code-splitting, I have a file main.js that ned to import 5 components that also need to be code-splitted and lazy-loaded with react-router. Now each of the components has their own directory in the source code with an index.js file(it export the component as default export) being the main export file and Is also the file I am importing in main.js for each of the 5 components. I am using lazy loading for these 5 components with React.lazy, but for some reason, they all get bundled into the same chunk for example - packs/js/index.chunk.js. But when I change the name of the main export file(index.js) to something else for each of the 5 components and the file name also is unique for each component then lazy-loading works. What I want is to keep the file name the same as the index.js for each of the components and attain lazy-loading.
I tried magic comments like below but had no success with it.
const x1 = lazy(() => import(/* webpackChunkName: "x1" */ './x1'));
Below is the webpack config
optimization: {
concatenateModules: false,
splitChunks: {
chunks(chunk) {
return true;
},
minSize: 30000,
minChunks: 1,
maxAsyncRequests: Infinity,
maxInitialRequests: Infinity,
automaticNameMaxLength: 30,
},
}
output: {
filename: 'js/[name].[chunkHash:6].js',
chunkFilename: 'js/[name].[chunkHash:6].chunk.js',
publicPath: `${process.env.CDN_HOST}/packs/`,
}

see this doc: https://v4.webpack.js.org/guides/code-splitting/#prevent-duplication
https://v4.webpack.js.org/plugins/split-chunks-plugin/
optimization: {
splitChunks: {
chunks: 'all',
},
},
==========
optimization: {
splitChunks: {
chunks: 'all',
minSize: 30000,
minChunks: 1,
maxAsyncRequests: Infinity,
maxInitialRequests: Infinity,
automaticNameMaxLength: 30,
},
},

Related

Code Splitting causes chunks to not reload

I have a core component used in various parts of our project. The component is exported as default based on a condition.
export default isLightWeightPdfGlobal || isSchedulingDisabled() ? CSSModules(GraphTableModule, Styles, { allowMultiple: true }) : connect(mapStateToProps)(CSSModules(GraphTableModule, Styles, { allowMultiple: true }));
This module is being used on the homepage; once it gets loaded, it doesn't reload when I go to other modules.
I want the else part of the export to be executed.
webpack split chunk config:
optimization: {
splitChunks: {
chunks: "all",
maxInitialRequests: Infinity,
minSize: 0,
cacheGroups: {
commons: {
chunks: "all",
minChunks: 2,
maxInitialRequests: 5,
minSize: 0
},
vendor: {
test: /node_modules/,
chunks: "initial",
priority: 10,
enforce: true
}
}
}
}

Webpack configuration - DLL's optimization

I'm using webpack in my react project.
I'm looking for the best approach about the DLL's configuration,
my latest approach is to split the DLL's to many small files.
the code in my webpack.cofig is:
optimization: {
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
maxInitialRequests: Infinity,
minSize: 0,
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name(module) {
const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
return `npm.${packageName.replace('#', '')}`;
},
},
},
},
},
The result is a long bundle time.
This is a good approach or it's better to have bigger DLL's files?

Webpack: Include vendor in only one module

I try to migrate one of my project building from browserify to webpack. It's AngularJS#1.7 project and I have multiple bundles: core with AngularJS and its dependenciy imports and other specific lazy-loading modules with its specific dependencies. So I have multiple entry points but I only load core.js script in index.html. Another modules resolve while routing by my resolver.
One of the lazy-loading modules imports AngularJS and it leads to duplicate code and WARNING: Tried to load AngularJS more than once. I want to Webpack check if modules were imported in core and load them from it.
I made it work but need to import one extra file common-vendors.js in index.html.
My config:
export default {
context: path.resolve(__dirname, './src/app'),
//...
entry: {
'core': './core/core.module',
'back-office': './back-office/back-office.module',
'front-office-1': './front-office-2/front-office-2.module',
'front-office-2': './front-office-3/front-office-3.module'
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'www')
},
mode: config.env,
optimization: {
splitChunks: {
cacheGroups: {
'common-vendors': {
test: /[\\/]node_modules[\\/]/,
name: 'common-vendors',
chunks: 'initial',
minChunks: 2
}
}
},
runtimeChunk: {name: 'core'},
minimizer: [
new UglifyJsPlugin({
uglifyOptions: {mangle: false}
})
]
},
plugins: [
new CompressionPlugin()
]
}
If you know a better solution, feel free to comment.

webpack 4 react loadable is not spliting vendor base on chucking point

I am currently using webpack 4 with react loadable to create chunks.
It actually chunks depends on the break point. However, vendor size remains same. React loadable is not supporting webpack 4 yet ? or I am missing some setup ?
css actually seems to splited into the chunk, though
{
output: {
path: 'tothe path',
publicPath: `/publicPath/`,
filename: '[name] + '.js',
chunkFilename: '[name]',
},
resolve: {
extensions: ['.js', '.json', '.css'],
alias: aliases
},
stats: {
warnings: false,
children: false,
},
optimization: {
splitChunks: {
chunks: "all",
name: true,
cacheGroups: {
common: {
name: "vendor" + ".js",
test: /[\\/]node_modules[\\/]/,
chunks: "all",
enforce: true,
reuseExistingChunk: false,
},
}
}
}
}
React-loadable doesn't work well with Webpack 4 yet,
take a look at this pull request.
There's a fork of react-loadable (by the author of PR),
but it didn't work for me either. I had a problem that some components wrapped in Loadable won't load.
#Bohdan Other
I also ran into this problem.
I found that the components can't load all import style. If I remove the style, the component will load normally.
I move all the styles to the entry file as a workaround.

Webpack - react works even when it's not in 'vendors'

I'm working with Webpack+React and I'm using the CommonsChunkPlugin. The thing is that react works even when I don't put it in the 'vendors' entry (same for other packages). Does that make sense?
My config looks like this:
config.entry.vendors = ['mobx', 'jquery', 'highcharts', 'react-highcharts', 'moment', 'numeral', 'jquery-ui', 'jquery.cookie', 'lodash', 'jquery.waitforimages', 'raven-js'];
config.module.loaders = config.module.loaders.concat([
{
test : /\.less$/,
loader: ExtractTextPlugin.extract({
fallback: "style-loader",
loader : "css-loader?sourceMap!postcss-loader!less-loader?sourceMap"
})
}
]);
config.plugins = config.plugins.concat([
new ExtractTextPlugin('[name]-[chunkhash].min.css'),
new webpack.optimize.UglifyJsPlugin({
minimize : true,
mangle : false, // { except: ['$super', '$', 'exports', 'require'] },
compressor: {
warnings : false,
screw_ie8: true
},
sourceMap : true
}),
new StatsPlugin('webpack.stats.json', {
source : false,
modules: false
}),
new webpack.optimize.CommonsChunkPlugin({name: 'vendors', filename: 'vendors-[chunkhash].min.js'}),
new WebpackMd5Hash(),
new ManifestPlugin(),
new InlineManifestWebpackPlugin({
name: 'webpackManifest'
})
]);
The output value of webpack is:
output: {
filename : '[name].bundle.js',
publicPath : '/',
path : paths.dist,
sourceMapFilename: "[name].js.map",
},
CommonsChunkPlugin is smart enough, you didn't specify chunks property for CommonsChunkPlugin, that means that plugin will try to go through all your entries and move common parts to vendors chunk and then into vendors-[chunkhash].min.js file.
e.g. you have 2 entry points: index.js, signin.js and in both you have next code:
const React = require('react')
const ReactDOM = require('react-dom')
So with configuration like
entry: {
app: './index.js',
signin: './signin.js',
vendor: ['react']
},
*****
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
filename: 'vendor-[chunkhash].js'
})
]
you will still have react-dom in vendor chunk.
On another hand if you have third entry point without requiring react-dom, only react will be moved to vendor chunk.
But even in this case you will still have react-dom included into first two entry chunks.
The thing is that react works event when I don't put it in the 'vendors' entry (same for other packages).
So react will work in any case, the only difference will be, will react chunk be moved to vendors or not, if not, it still will be included in your entry point file.
Hope it helps.

Resources