Webpack best practices summary (1)

in Tutorials with 2 comments

I haven't written any articles for a long time. I expect to bring three webpack articles this time, It will be updated in the next few days (Updated).

I wrote about the basics before Basic course of webpack 2 It's enough to get started. I don't want to say more.

Webpack3 Since its official release on June 20 this year, it has brought us Scope Hoisting and Magic Comments Two major functions, Unfortunately, it is not in the scope of this series of articles The main content of this article is summarized from the project. Of course, I also read many articles written by others, which can be applied to production. This paper mainly introduces three aspects: compressing JavaScript and CSS, configuring environment variables, and tree shaping brought by ES module mechanism.

Suppose we have a front-end development requirement, which is a little special, not a business requirement, but a requirement to reduce the file size. It can be seen that this requirement is in the category of performance optimization, reducing file size, accelerating network transmission, shortening web page loading time, increasing user experience and improving user satisfaction. This is a positive result. We have to do it~

Compress JavaScript

I have to mention Google's Closure Compiler It's better to call a function called scorched, so it's better to delete code from JavaScript and execute it with the optimized method. as follows

Before optimization

 function map(array, iteratee) {
  let index = -1
  const length = array == null ? 0 : array.length
  const result = new Array(length)

  while (++index < length) {
    result[index] = iteratee(array[index], index, array)
  }
  return result
}

After optimization

 function map(n,e){let r=-1;for(const i=null==n?0:n.length,t=Array(i);++r<i;)t[r]=e(n[r],r,b);return t}

It is found that the optimization effect is excellent UglifyJS The same optimization effect can be achieved. Since webpack has built-in plug-in, it can be used directly. The configuration is as follows

 // webpack.config.js
const webpack = require('webpack');

module.exports = {
  plugins: [
    new webpack.optimize.UglifyJsPlugin()
  ]
};

The results of the plug-in before and after optimization are as follows:

Suppose we have a piece of code, as follows:

 // comments.js
import './comments.css';
export function render(data, target) {
    console.log('Rendered!');
}

The compiled code of webpack is as follows:

 // bundle.js (part of)
"use strict";
Object.defineProperty(__ webpack_ exports__ , "__ esModule", { value: true });
var __ WEBPACK_ IMPORTED_ MODULE_ 0__ comments_ css__  =
  __ webpack_ require__ (4);
var __ WEBPACK_ IMPORTED_ MODULE_ 0__ comments_ css___ default =
  __ webpack_ require__ .n(__ WEBPACK_ IMPORTED_ MODULE_ 0__ comments_ css__ );
__ webpack_ exports__ ["render"] = render;

function render(data, target) {
    console.log('Rendered!');
}

If the uglifyjs plug-in is used, the recompiled code is as follows:

 // bundle.js (part of)
"use strict";function r(e,t){console.log("Rendered!")}
Object.defineProperty(t,"__ esModule",{value:!0});
var o=n(4);n.n(o);t.render=r

Special case description : Currently, uglifyjs 2 (which comes with webpack) cannot compile es2015 + code, which means that if there are classes, arrow functions or other new features in the code, and you do not compile the code into Es5, the uglifyjs plug-in cannot process the code. Here are two methods to handle it:

Method 1: add Babel support to webpack. The basic process is as follows

install babel-core babel-loader babel-preset-es2015

 npm i babel-core babel-loader babel-preset-es2015 --save-dev

Add configuration information to webpack

 // webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.js[x]$/,
        use: [{'babel-loader', options: {
          presets: ['es2015']
        }]
      }
    ]
  }
};

Method 2: replace uglifyjs 2 with babili, a Babel based compression tool. Learn more babili-webpack-plugin I don't give too much description here

Compress CSS

The method of compressing CSS is relatively simple, css-loader With the compression function, the configuration is as follows:

 // webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          'style-loader',
          { loader: 'css-loader', options: { minimize: true } }
        ]
      }
    ]
  }
};

In addition, I have written webpack, less and sass configuration tutorials here1 , here2

Configure environment variables

take NODE_ ENV Set to production It can also help reduce the size of front-end projects

NODE_ ENV It is usually used as environment variables by various JS frameworks or libraries as judgment conditions to determine which execution mode, such as development mode or production mode, these frameworks or libraries are based on NODE_ ENV To represent the corresponding behavior. When doing detection and warning, for example, in react mode:

 // … 
if (process.env.NODE_ ENV !== 'production') {
  validateTypeDef(Constructor, propTypes, 'prop');
}
// …

If you want to package a build project into a production environment, it's best to tell the framework or library in the project that the current environment variable is the production environment. For libraries for node. JS, configure the NODE_ ENV by production For plug-ins, you can use webpack process.env.NODE_ ENV The settings are as follows

 // webpack.config.js
const webpack = require('webpack');

module.exports = {
  plugins: {
    new webpack.DefinePlugin({
      'process.env.NODE_ ENV': JSON.stringify('production')
    })
  }
};

DefinePlugin It allows us to create global variables that will be used during the package compile time of webpack. It will replace all of them process.env.NODE_ ENV The value of the instance is "production" To make uglifyjs know that the judgment expression is always wrong, delete the relevant code and further compress the package file

ECMAScript module mechanism

Using ECMAScript in the project import export Webpack can further reduce the size through tree shaking and by packaging useful code. Tree shaking can examine the entire package dependency tree and find the parts used. Therefore, if ECMAScript module mechanism is used, webpack will remove useless code, as follows:

Suppose two files are written, but only one of them is used

 // comments.js
export const commentRestEndpoint = '/rest/comments';
export const render = () => { return 'Rendered!'; };

// index.js
import { render } from './a.js';
render();

Webpack knows componentRestEndpoint It is not used, and the package file will not have this entry

 // bundle.js (part of)
(function(module, __ webpack_ exports__ , __ webpack_ require__ ) {
  "use strict";
  /* unused harmony export commentRestEndpoint */
  /* harmony export */__ webpack_ exports__ ["b"] = render;

  var commentRestEndpoint = '/rest/comments';
  var render = function () { return 'Rendered!'; }
})

The uglifyjs plug-in removes the useless parts

 // bundle.js (part of)
(function(n,e){"use strict";e.b=r;var r=function(){return"Rendered!"}})

If the JavaScript framework or library uses the ECMAScript module mechanism, tree shaking is also valid for it

matters needing attention

1. Without uglifyjs, tree shaking will not work

The uglify code itself is not useless. In this way, the export expressions can no longer be compressed so that they can only be used in export. So if you don't use compression when you pack, the packaged file won't get smaller

2. Do not compile es module mechanism to commonjs

If you use babel-preset-env or babel-preset-es2015 You need to check the configuration of these presets. By default, they all recompile to commonjs the syntax features of the ES module mechanism, such as import and export Compiled as commonjs require and module.exports We can use it { modules: false } Compilation is prohibited as follows:

 // webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.js[x]$/,
        use: [{'babel-loader', options: {
          presets: [['es2015', { modules: false }]]
        }]
      }
    ]
  }
};

3. Webpack will not be optimized under special conditions

When you use export * from 'file.js' Or typescript. Webpack will not be optimized. These special conditions are difficult to detect in the code, and it is difficult to know whether the code with these special conditions has been fixed. More information can be viewed here

summary

There are many ways to optimize the front-end project by webpack. Four techniques are provided here. They are compression of JavaScript files by uglifyjs plug-in, compression function provided by CSS loader, and configuration NODE_ ENV You can get rid of the useless code further, and tree shaking helps to find more useless code

It's a lot of content. That's about it~

Responses
  1. Ezreal

    Test 1233

    Reply
  2. Big guy's research is too advanced

    Reply