Webpack configuration - DLL's optimization - reactjs

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?

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 4 code splitting not working with React.lazy

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,
},
},

How to produce readable stack trace in production Webpack build from source maps and minified bundles? Are source maps included in code split bundles?

Hi I am learning React in a Typescript environment with Webpack and trying to display error stack trace in production.
I have enabled sourceMaps in tsconfig.json and have dev-tools: source-map setting in my production webconfig. I am performing minification using the Terser plugin with source maps enabled as follows:
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
sourceMap: true,
....
I can see that the source map url is included as a comment at the end of a minified bundle file, e.g.
//# sourceMappingURL=course-list.6ccadc639a7a607e7b4e.bundle.js.map%
I can also see that the minified map files are produced in the dist folder as expected. However, when I display a stack trace and error message for an Error thrown, the message is unreadable using minified content.
http://localhost:8080/vendors~course-list.3042c44300bc08021f63.bundle.js:2:6029
http://localhost:8080/vendors~course-list.3042c44300bc08021f63.bundle.js:2:5067
in w in b in withRouter(b) in e in e in Suspense in div in e in e in S
How do I display readable stack trace for users in production environments?
Further Information 1
I am testing that a network connection error is thrown (in production environment) by the axios library when trying to connect to a local rest API endpoint. If I run in a development environment I can see further details in stack trace relating to Network connection failure. Details are sparse and garbled in production environment with minified bundle and devtool option set to source-map.
The bundle report generated from the production build is as follows:
Further Information 2
I have used code splitting at the route level to create some bundles. Running source-map-explorer for the route code split bundle that throws the error:
npx source-map-explorer dist/vendors~course-list.3042c44300bc08021f63.bundle.js
results in error message:
dist/vendors~course-list.3042c44300bc08021f63.bundle.js
Unable to map 265/14948 bytes (1.77%)
This is the bundle that contains axios library to make the REST API request. The source map analyse report for the bundle is illustrated in the image below:
My production webpack config is as follows:
module.exports = merge(config.CommonConfig, {
devtool: 'source-map',
mode: 'production', // https://webpack.js.org/configuration/mode/#mode-production
module: {
rules: [
{
// link css modules
test: /\.css$/,
include: path.resolve(constants.dir.SRC, 'app'),
use: [
{ loader: MiniCssExtractPlugin.loader },
{
loader: require.resolve('css-loader'),
options: {
modules: {
localIdentName: '[hash:base64]',
},
importLoaders: 1,
sourceMap: true,
},
},
],
},
{
// link global css module in styles
test: /\.css$/,
include: path.resolve(constants.dir.SRC, 'styles'),
use: [
{ loader: MiniCssExtractPlugin.loader },
{
loader: require.resolve('css-loader'),
options: { sourceMap: true },
},
],
},
],
},
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
sourceMap: true,
terserOptions: {
output: {
comments: false,
},
extractComments: false,
},
}),
new OptimizeCSSAssetsPlugin(),
],
},
plugins: [
// inject react and react-dom CDN to scripts in index.html
new WebpackCdnPlugin({
modules: {
react: [
{ name: 'react', version: 16, path: 'umd/react.production.min.js' },
{
name: 'react-dom',
version: 16,
path: 'umd/react-dom.production.min.js',
},
],
},
prod: true,
}),
// extract css to file, minimize in optimization
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css',
ignoreOrder: false,
}),
// use brotli compression to compress resources larger than ~10K
new CompressionPlugin({
filename: '[path].br[query]',
algorithm: 'brotliCompress',
test: /\.(css|gif|html|jpg|jpeg|js|png|svg|)$/,
compressionOptions: { level: 11 },
threshold: 10240,
minRatio: 0.8,
deleteOriginalAssets: false,
}),
// use gzip compression to compress resources larger than ~10K
new CompressionPlugin({
filename: '[path].gz[query]',
algorithm: 'gzip',
test: /\.(css|gif|html|jpg|jpeg|js|png|svg|)$/,
compressionOptions: { level: 9 },
threshold: 10240,
minRatio: 0.8,
deleteOriginalAssets: false,
}),
],
externals: [
// add libraries to be excluded from bundle add here
// for example loaded from CDN
{ react: 'React' },
{ 'react-dom': 'ReactDOM' },
],
});

Failed to load angularjs $templateCache template on dependencies with webpack

Sorry for such a similar question to others out there, but I cant seem to make any of them work.
I understand that when using webpack, the standard way of incluing templates in your angular application is via the require. ie
template: require('./sometemplte.html')
I have done that in all of my app code and that works fine.
But i have four dependent libraries that use templateUrl, lets focus on angular-ui-boostrap.
my webpack.conf.js
entry: {
vendor: "./src/vendor.ts",
app: "./src/ClientApp/app.ts"
},
output: {
filename: "[name].js",
path: __dirname + "/wwwroot"
},
module: {
rules: [
{ test: /\.ts$/,
loader: "ts-loader"
}, {
test: /\.html$/,
loader: 'raw-loader'
}
inside vendor.ts i have
require('angular');
require('angular-ui-bootstrap');
and inside my app i am simply using the directive
<uib-typeahead></uib-typeahead>
the code inside my node_modules is not code that I can to modify. But currently i am getting the following error
angular.js:14700 Error: [$compile:tpload] Failed to load template: uib/template/typeahead/typeahead-popup.html
http://errors.angularjs.org/1.6.6/$compile/tpload?p0=ui-grid%2Fui-grid&p1=undefined&p2=undefined
I verified that the template is within $templateCache in my app. but for whatever reason it is not available for $compile to do its thing.
So how can i get $templateCache to work with webpack so my external dependencies will work?
Thanks in advance.
Thanks to John Reilly i finally figured it out.
There is a plugin called splitChunks , which use to be CommonsChunksPlugin. Once i inlcuded that into my configuration everyting just worked. I just used the default configuation mentioned here
https://webpack.js.org/plugins/split-chunks-plugin/
note: although it is a plugin, it does not go in the plugins array. it goes into the optimization object.
entry: {...},
output: {...},
optimization: {
splitChunks: {
chunks: "async",
minSize: 30000,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}

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.

Resources