JavaScript webpack Tree-shaking
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. Four techniques are provided here, 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~
This article is written by Chakhsu Lau Creation, adoption Knowledge Sharing Attribution 4.0 International License Agreement.
All articles on this website are original or translated by this website, except for the reprint/source. Please sign your name before reprinting.