Webpack Best Practice Summary (I)
in Tutorial with 0 comment
Webpack Best Practice Summary (I)
in Tutorial with 0 comment

I haven't written an article for a long time. This time, it is expected to bring three Webpack series articles, It will be updated in these days (Updated).

I wrote an article about basic knowledge before Webpack2 Basic Tutorial , enough to get started, no more.

Webpack3 Since the official release on June 20 this year Scope Hoisting and Magic Comments Two functions, Unfortunately, it is not in the scope of this series of articles (I broke my promise). The main content of this article is summarized from the project. Of course, I have seen many articles written by others, which can be applied to production. This article mainly introduces three aspects: compressing JavaScript and CSS, configuring environment variables, and Tree Shaking brought by ES module mechanism.

Suppose we have a front-end development requirement, which is a bit special. It is not a business requirement, but a requirement to reduce the file size. It can be seen that this requirement is a performance optimization category, reducing file size, accelerating network transmission, shortening 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 , a tool that can make JavaScript download and execute faster. Its approach is to implement some "scorched earth" optimization strategies. It expands functions, rewrites variable names, filters redundant code, and deletes functions that will never be called, thus generating code that may be optimized. 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 by comparison UglifyJS The same optimization effect can be achieved. Because Webpack has this plug-in built 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 comparison results before and after optimization using the plug-in 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 : At present, 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 have not compiled the code into ES5, then the UglifyJS plug-in cannot process these codes. Here are two processing methods:

Method 1: Add support babel 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: Use Babili instead of UglifyJS 2, a Babel based compression tool. For more information, see babili-webpack-plugin , not too much description here

Compress CSS

The method of compressing CSS is relatively simple, css-loader With its own 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 also written a configuration tutorial for Webpack, Less and Sass. See: 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 an environment variable by various js frameworks or libraries as a judgment condition to determine which execution mode, such as development mode or production mode. These frameworks or libraries are based on NODE_ENV Value to represent the corresponding behavior. For example, when in development mode, React will do additional detection and print warnings:

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

If you want to package the construction project into the production environment, you'd better tell the framework or library in the project that the current environment variable is the production environment. For the libraries applicable to Node.js, configure them directly NODE_ENV by production OK, but for the Web side, you can use the plug-in provided with Webpack to process.env. NODE_ENV The settings of 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, which will act during the packaging and compilation period of webpack. It will replace all process.env. NODE_ENV The value of the instance is "production" So that UglifyJS knows that the expression is always wrong, so it can delete the relevant code and further compress the packaged file

ECMAScript module mechanism

ECMAScript used in the project import export Webpack can also further reduce the size by packaging useful code through tree Shaking. Tree shaking can check the entire packaging dependency tree to find the part used. So if the 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 packaged 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!'; } })

UglifyJS plug-in removes 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 effective for it

matters needing attention

1. If there is no UglifyJS, tree shaking will not work

In fact, removing useless code is not the Webpack itself, but UglifyJS. Webpack just removes the export expression to make those exports no longer used, so that they can be removed during compression. Therefore, if you do not use compression when packaging, the packaging file will not become smaller

2. Do not compile the ES module mechanism into CommonJS

If you use babel-preset-env or babel-preset-es2015 , you need to check the configuration of these presets. By default, they will recompile the syntax features of the ES module mechanism to CommonJS, such as import and export Compiled as CommonJS require and module.exports We can use { 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 hard to find in the code, and it is hard to know whether the code for these special conditions has been repaired. For more information, see here

summary

Webpack optimizes front-end projects in many ways. Here, four techniques are provided, namely, the compression of JavaScript files through the UglifyJS plug-in, the compression function provided by css loader, and configuration NODE_ENV You can further remove useless code. Tree Shaking helps you find more useless code

More content, about that~

Responses