No Result
View All Result
Cloud Reports
  • Home
  • Linux
  • Web development
  • Javascript
  • SQL
  • Ant Design tutorial
  • PC & Laptop
  • Technology & Digital
  • Home
  • Linux
  • Web development
  • Javascript
  • SQL
  • Ant Design tutorial
  • PC & Laptop
  • Technology & Digital
No Result
View All Result
Cloud Reports
No Result
View All Result

Tips for optimizing Webpack

npn by npn
December 18, 2020
in Javascript
Reading Time: 8min read
A A
0
Tips for optimizing Webpack

Here’s a guide to the 8 most useful optimizations for optimizing Webpack size and build speed.

READ ALSO

Javascript developer should stop for … in for now

Javascript developer should stop for … in for now

December 31, 2020
13
Understanding the difference between Number.isNaN and isNaN in javascript

Understanding the difference between Number.isNaN and isNaN in javascript

December 29, 2020
7

This article will be updated when a permanently stable version of Webpack 5 is released (version 5.6 is not yet fully complete).

For information, you can find the complete configuration that I use in this article #Configuration de Webpack.

The following options are sorted in order of efficiency which allowed me to reduce the size of the generated bundle by 80% and the build time by a factor of 5!

Measuring tools

First, to understand the effectiveness of these options, here are two tools to measure the impact of changes.

Calculate the size of the bundles

The package webpack-bundle-analyzerallows you to see the detailed content of each bundle generated as well as their total size. At a glance, it is possible to identify redundant packages between bundles.

Start by adding the package to your sources:

yarn add -D webpack-bundle-analyzer

Then add it to the configuration of your project (it will then be launched automatically for each build in a dedicated window using port 8888):

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

Then in the list of plugins, add it with this configuration:

new BundleAnalyzerPlugin({
    /* Can be `server`, `static` or `disabled`. */
    /* In `server` mode analyzer will start HTTP server to show bundle report. */
    /* In `static` mode single HTML file with bundle report will be generated. */
    /* In `disabled` mode you can use this plugin to just generate Webpack Stats JSON file by setting `generateStatsFile` to `true`. */
    analyzerMode: 'server',
    /* Host that will be used in `server` mode to start HTTP server. */
    analyzerHost: '127.0.0.1',
    /* Port that will be used in `server` mode to start HTTP server. */
    analyzerPort: 8888,
    /* Path to bundle report file that will be generated in `static` mode. */
    /* Relative to bundles output directory. */
    reportFilename: 'report.html',
    /* Module sizes to show in report by default. */
    /* Should be one of `stat`, `parsed` or `gzip`. */
    /* See "Definitions" section for more information. */
    defaultSizes: 'parsed',
    /* Automatically open report in default browser */
    openAnalyzer: true,
    /* If `true`, Webpack Stats JSON file will be generated in bundles output directory */
    generateStatsFile: false,
    /* Name of Webpack Stats JSON file that will be generated if `generateStatsFile` is `true`. */
    /* Relative to bundles output directory. */
    statsFilename: 'stats.json',
    /* Options for `stats.toJson()` method. */
    /* For example you can exclude sources of your modules from stats file with `source: false` option.
    /* See more options here: https://github.com/webpack/webpack/blob/webpack-1/lib/Stats.js#L21 */
    statsOptions: null,
    /* Log level. Can be 'info', 'warn', 'error' or 'silent'. */
    logLevel: 'info'
})

Generation time

The simplest tools are often the most effective.

ADVERTISEMENT

On Linux, launch the build by prefixing the command with:

time npm run build

The total time will be displayed at the end of the execution of the order.

1. Tree Shaking

Since version 4, Wepack offers to automatically remove dependencies not used in the project.

To activate it, add the following line in optimizationthe configuration part of Webpack:

sideEffects: true

It will then delete all the packages that are called directly but also all the indirect dependencies like polyfills or external libs!

To solve this problem, add the files to ignore in package.json, for example:

"sideEffects": [
    "*.scss",
    "*.css",
    "*polyfills.js",
    "*application.js",
    "*other-libs*"
],

Typically, it is necessary to include in this list the libraries which call jQuery without an importor require. Likewise, be sure to include css type files when using CSS-in-JS.

2. Automatic chunks

Webpack proposes to automatically create “chunks” to pool the imports present in the various files declared in entry.

In the configuration of Webpack, declare the chunks to be shared. For example :

runtimeChunk: {
    name: 'runtime'
},
splitChunks: {
    chunks: 'async',
    minSize: 30000,
    maxSize: 0,
    minChunks: 2,
    maxAsyncRequests: 7,
    maxInitialRequests: 4,
    name: true,
    cacheGroups: {
        default: false,
        commonsAdmins: {
            name: 'admins-commons',
            minChunks: 2,
            reuseExistingChunk: true,
            chunks: function (chunk) {
                return chunk.name.includes('admin');
            }
        },
        commons: {
            name: 'commons',
            minChunks: 2,
            reuseExistingChunk: true,
            chunks: function (chunk) {
                return !module.resource.includes('/admin/');
            }
        }
    }
},

In this configuration, two modules are created by default: a common one commonsand one for the components used by the admin part admin-commons(often contain unwanted dependencies for simple visitors or users).

Additionally some useful properties are specified:

  • minSize: the component must be at least 30kb to be generated
  • minChunks: minimum number of chunks that must contain a dependency to be pooled
  • maxAsyncRequests: maximum number of async requests to load components
  • maxInitialRequests: maximum number of requests at initial load

All that remains is to include the chunks in common in the code:

<script src="/runtime.js"></script>
<script src="/commons.js"></script>
<script src="/user.js"></script>

3. Load the components asynchronously

Since ES2015 and Babel 7, dynamic imports are managed natively. So, it is very easy to call JS files dynamically and on demand. In addition, in the case of React, it provides a utility,, React.lazyto manage it even more easily.

Create the following function in your sources:

export const lazyWithPreload = (factory) => {
    const Component = React.lazy(factory);
    Component.preload = factory;
    return Component;
};

Then declare all the components you want to call dynamically as follows:

export const CommentBox = lazyWithPreload(() => import(/* webpackChunkName: "comment-box */ '../comments/box'));

While thinking about naming the import with the comment “magic”: webpackChunkName.

Then import your component, like a normal component:

import CommentBox from '../loaders/commentBox';

In the code, then call the component CommentBoxas usual:

{
  this.state.isCommentDisplay &&
  <CommentBox props={...}/>
}

Webpack will then take care of loading all the components asynchronously during the actual call in the code and only then.

4. Change the file generation mode

By default, Webpack does not generate SourceMaps (essential files to find the origin of errors). Several options are available: webpack.js.org

The most efficient option in terms of generation time and available source is:

webPackConfig.devtool = 'cheap-module-source-map';

5. Caching builds

Fastest option to implement, enable cache to optimize the following builds:

webPackConfig.cache = true;

6. Limit the number of files in entries

Try not to create new files for each new page on your site. The greater the number of files, the longer the build time will be. By mutualizing the files, I reduced the incremental build time by more than 5. A single modification took more than 10 seconds, going to 5 base files, I am only 2 seconds.

One solution is to create a generic file which will be in charge of calling the dynamic component to load. This file can be used for example only to display the header and the footer, all the content will then be loaded dynamically.

7. Limit the total number of files to parse

In the options of rules, provide Webpack only with local components (those of external libraries are already compiled normally, no need to do the job twice):

rules: [
    {
        test: /\.(js|jsx)$/,
        include: path.resolve('./assets/javascripts'),
        options: {
            babelrc: true,
            cacheDirectory: true
        }
    },
    {
        test: /\.s?[ac]ss$/,
        exclude: /node_modules/,
        use: ...
    },
    {
        test: /\.(gif|png|jpe?g|svg)$/i,
        exclude: /node_modules/,
        use: ...
    },
    {
        test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/i,
        exclude: /node_modules/,
        use: ...
    }
]

8. Decrease the size of big libs

Libraries like lodash are often useful but can load several hundred kb. It is then necessary to use a mechanism to convert the imports so that Webpack can optimize them.

Add the package to your project:

yarn add babel-plugin-lodash

Then in .babelrc:

"plugins" : [
     "lodash" ,
    ...
]

Finally in the configuration of your project:

const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');

webPackConfig.plugins = [
    new LodashModuleReplacementPlugin({
        'caching': true,
        'collections': true,
        'flattening': true,
        'placeholders': true
    })
];

Otherwise replace the use of Lodash by native methods in JS:

https://github.com/you-dont-need/You-Dont-Need-Lodash-Underscore

Unfortunately, no equivalent package is provided for jQuery. You must import all the lib … The only option is to use the slim package provided by jQuery. Then declare an alias in your configuration so that all dependencies use it:

alias: {
    react: 'node_modules/react',
    'react-dom': 'node_modules/react-dom',
    jquery: 'node_modules/jquery/dist/jquery.slim'
},
ShareTweetShare
Previous Post

UTM Google, know everything to better use them!

Next Post

Smooth UI System: a new way to style your components

npn

npn

Related Posts

Javascript developer should stop for … in for now
Javascript

Javascript developer should stop for … in for now

December 31, 2020
13
Understanding the difference between Number.isNaN and isNaN in javascript
Javascript

Understanding the difference between Number.isNaN and isNaN in javascript

December 29, 2020
7
How to display colors (color, bgcolor) in console.log () for javascript developers!
Javascript

How to display colors (color, bgcolor) in console.log () for javascript developers!

December 29, 2020
9
If you want to learn React JS within 3 months, the following 8 basics must first be known
Javascript

If you want to learn React JS within 3 months, the following 8 basics must first be known

December 22, 2020
5
Modern JavaScript features should be used every day, for good resolution (P1).
Javascript

Modern JavaScript features should be used every day, for good resolution (P1).

December 21, 2020
8
Javascript

Getting Started with JavaScript What is DOM Manipulation?

December 17, 2020
7
Next Post
Smooth UI System: a new way to style your components

Smooth UI System: a new way to style your components

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

No Result
View All Result

Categories

  • Android (1)
  • Ant Design tutorial (7)
  • Javascript (21)
  • Layout and Routing (2)
  • Linux (3)
  • PC & Laptop (34)
  • React (17)
  • SQL (2)
  • Technology & Digital (124)
  • The Basics (5)
  • Web development (38)

Search

No Result
View All Result
No Result
View All Result
  • Home
  • Linux
  • Web development
  • Javascript
  • SQL
  • Ant Design tutorial
  • PC & Laptop
  • Technology & Digital