The introduction

This article mainly introduces

  • Analysis and use of Sourcemap
  • Extraction of common resources of the page
  • The principle and use of Tree Shaking

1.sourcemap

Source Map is an information file that stores location information. With it, in the event of an error, the development tool will display the original code, rather than the converted code. It is generally recommended to enable this function in the development environment (to quickly locate error information and improve development efficiency) and disable it in the online environment (to avoid exposing business code). Webpack also opens devTool, a custom configuration option for soucemap.

1.1 Learn about Webapck devTool

Devtool is an option for WebPack. Controls whether and how a Source map is generated. This function is disabled by default.

const path = require('path');

module.exports = {
  devtool: 'none'.// SourceMap
  entry: './src/index.js'.// Import file
  output: {
    filename: 'bundle.js'./ / file name
    path: path.resolve(__dirname, 'dist')  / / folder}}Copy the code

2.2 Optional values for devtool

Here is a form of official document interception:

In the table:` + + + `Very quickly,` + + `Fast,` + `Faster,`o`Medium,` - `Slowly,` - ` 慢
Copy the code

Some of these values are suitable for development environments and some are suitable for production environments.

Those of you looking at the table should not be intimidated by the number of options available. In fact, most of these options are made up of the combination of these keywords, we only need to remember the meaning of the keywords can guess the approximate ~

The keyword On behalf of the meaning
eval Use eval to wrap module code
source-map The. Map file is generated
cheap Contains no column information
inline Embed the.map as a DataUrl and do not generate a separate.map file
module Contains the sourcemap of the loader

2.3 DevTool Best Practices

For development environments, you usually want faster source maps that need to be added to the bundle at the cost of increased volume, but for production environments, you want more accurate source maps that need to be separated from the bundle and exist independently. In general, it is recommended for development environments

devtool: 'cheap-module-eval-source-map',
Copy the code

Production environment use

devtool: 'cheap-module-source-map',
Copy the code

2. Extraction of public resources on the page

2.1 Configuration and Use of externals

For third-party libraries that are updated infrequently, we can configure externals to be introduced using CDN instead of webPack packaging. This can speed up packaging and reduce the bundle size without affecting the use of CMD, AMD or Window /global global in the program (generally referred to as import). Let’s take React, ReactDOM as an example

The way a: use the plug-in HtmlWebpackExternalsPlugin
npm i HtmlWebpackExternalsPlugin -D
Copy the code

The use of HtmlWebpackExternalsPlugin in webpack plugins

const HtmlWebpackExternalsPlugin = require('HtmlWebpackExternalsPlugin');
module.exports = {
    ...
    plugins: [
        new HtmlWebpackExternalsPlugin({
            externals: [{module: 'react'.entry: 'https://unpkg.com/react@16/umd/react.production.min.js'.global: 'React'
                },
                {
                    module: 'react-dom'.entry: 'https://unpkg.com/react-dom@16/umd/react-dom.production.min.js'.global: 'ReactDOM'}}),new HtmlWebpackPlugin({
            meta: {viewport: 'width=device-width, initial-scale=1, shrink-to-fit=no'},
            favicon: './src/images/favicon.ico'.scriptLoading: 'blocking'.template: path.join(__dirname, './src/index.html'),
            minify: true}})]Copy the code

Executing the package command, accessing dist/index.html in the browser, you can see that the following code has been dynamically added to the index.html:

Observe the change in the size of the package file before and after using the plug-in

Before use:After use:

Method 2: Configure externals

Start by introducing static resources in the index.html page

<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
Copy the code

Then configure externals

const HtmlWebpackExternalsPlugin = require('HtmlWebpackExternalsPlugin');
module.exports = {
    ...
    externals: {
        'react': 'React'.'react-dom': 'ReactDOM'}}Copy the code

Execute the package command, access dist/index.html in the browser, and access normally. As above, React and ReactDOM are not packaged with WebPack.

2.2 Separating basic Packages

When we use a common resource for multiple modules, we can use webPack4’s built-in splitChunksPlugin to extract the common resource to reduce packaging volume.

const HtmlWebpackExternalsPlugin = require('HtmlWebpackExternalsPlugin');
module.exports = {
    ...
    optimization: {
        splitChunks: {
            cacheGroups: {
                commons: {
                    test: /(react|react-dom)/,
                    name: 'vendors'.chunks: 'all'
                }
            }
        }
    }
}
Copy the code

As you can see, react and react-DOM have been separated

More configuration items stamp the split-chunks-plugin configuration item document

3. The principle and use of Tree Shaking

3.1 What is Tree Shaking

Tree shaking Think of webapck as a tree, the entry file is the trunk of the tree, and the dependent modules are the branches of the tree. To shake the tree, as the name implies, is to shake off the useless branches of the webpack tree. Its essence is to eliminate useless JS code. Dead code Elimination, which is widely used in traditional programming language compilers, allows the compiler to determine that certain code doesn’t affect output at all and then eliminate it. This is called dead code elimination (DCE).

Webpack2 and later have tree Shaking built in.

3.2 How Do I Trigger Tree Shaking

What kind of code is deemed useless and does not affect the output and is tossed by WebPack?

  • 1 never reaches the code
  • 2. Write code but don’t read it
  • 3 execution results in code that will never be used

Such as:

    // Code that will never be executed
    if (false) {
        console.log('Am I still there? ');
    }
    // Write code without reading it
    let unusedVar = 'Var am I still there?'

    // The result of execution is code that is never used
    const Search = () = > {
    // Code that will never be executed
    if (false) {
        console.log('Am I still there? ');
    }
    // Write code without reading it
    let unusedVar = 'Var am I still there?'

    // The result of execution is code that is never used
    const fn = () = > {
        return 'Am I still there?'
    }

    
    useEffect(() = > {
        fn()
    }, [])

    console.log('Am I still there? ')
    const [comp, setComp] = useState();
    const clicked = () = > {
        import('./test.js').then(text= >{ setComp(text.default); })}return <div>
        <div className="search-text less" onClick={clicked}>Search Text</div>
        {comp && comp}
    </div>
}
Copy the code

With the above code, take a look at the webapck output file after packaging:

The above useless code has been shaken up

3.3 Tree Shaking Principle

Tree Shaking takes advantage of the features of the ES6 module to identify and mark unwanted code during the precompilation phase of the code, and then erase the marked unwanted code during the Uglify phase. Tree Shaking can only work in static modules because the precompile phase is needed to determine which code is useless. ECMAScript 6 module loading is static, so the entire dependency tree can be statically derived from the parse tree.

ES6 features:

  • Appears only as a statement at the top level of the module
  • The import module name must be a string constant, not a variable
  • The value cannot be changed after import

These features ensure that the module is static.

Note: To take advantage of Tree Shaking, you must use the ES2015 module syntax (import and export) and make sure that no compiler converts the ES2015 module syntax to CommonJS (by the way, This is the default behavior of the now-common @babel/preset-env, see the documentation for more information).