Author: God Q Superman
Translator: Front-end Xiaozhi
Source: medium
If you have dreams and dry goods, search [Moving the World] attention to this Shawanzhi who is still washing dishes in the early morning.
This article has been included in GitHub https://github.com/qq449245884/xiaozhi . There are complete test sites, materials and my series of articles for interviews with first-tier manufacturers.
When I was chatting with my friends about Webpack a while ago, I suddenly mentioned Tree Shaking, but I am ashamed that I have no way to explain how Webpack achieves Tree Shaking, so I took the time to read the Webpack files on the first day of this annual vacation, Then write down what you understand. If you are also interested, please read it together🙌.
What is Tree Shaking
Tree Shaking is an optimization, a common term used in JavaScript to denote the removal of useless code, the origin of the name Tree Shaking seems to mean "When you shake a tree vigorously, only Green leaves will remain, and other dead leaves will fall to the ground.” And those green leaves are the real useful code in the packaged file.
When using it, it should be noted that Tree Shaking can only be used on static structure
(for example: import
and export
), and 0620d9009a15e1 such as dynamic structure
require
not be detected. For example, import
must be at the top of the file if it is to be loaded into a module
, but require
can be used anywhere. For example, in the following scenario, you must wait until runtime
to know what module
is:
let module = null;
if (Math.random() * 10 > 5) {
module = require('module1');
} else {
module = require('moudle2');
}
Before starting to understand the work of Tree Shaking, some people should be curious. Even if you have never set up Tree Shaking in Webpack, the useless code will be removed!
That is because of the need to perform Tree Shaking ModuleConcatenationPlugin (Figure I), and in addition there is a Webpack mode
, especially if you have not been to set mode
value, that mode
will by default be production
(Figure II), then production
ModuleConcatenationPlugin
will be turned on in the default options (also Figure 2), so it's not surprising that you don't usually notice it, because Webpack does it for you.
How Tree Shaking works
Because Production will open ModuleConcatenationPlugin for you, so when we experiment later, we need to change the mode to none
(the Webpack file says that none
is the mode to turn off all optimization settings).
A simple initialization example configuration will be attached here. If you are interested, you can clone it and play with it.
First, create a math.js
and src
under string.js
, and then write a separate method to do export
, which are add
and composeString
respectively:
const add = (a, b) => a + b;
export default { add };
const composeString = (a, b) => `${a} ${b}`;
export default { composeString };
Open src
under index.js
, put add
and composeString
into import
, but only use the add
method:
import { add } from './math';
import { addString } from './string';
console.log(add(1, 2))
Finally, execute npm run build
or terminal
in webpack
for packaging. After packaging, we will find that although we only have import add
for use, the content of the packaged file will still have composeString
:
But this is normal. After all, we haven't done any processing yet, and Webpack doesn't know which code you use or not when packing, so there is no way to remove composeString
for you.
So what kind of code is useful and what isn't? ?
- The most obvious definition should be that it is useful if it is implemented. Like
add
in the example above. - The code with
side effect
is also used. Likeindex.js
above, it seems that no method is provided, but it will leavelog
inconsole
duringlibrary
. In addition, 0620d9009a1821 that will change the execution environment also hasside effect
ofpolyfill
.
The first case is relatively easy to distinguish, but if it is the second case, you can choose to set it with the sideEffects
property in Webpack.
sideEffects
sideEffects
can be set to Boolean
or Array
, when you set it to false
, it means that the project will not have sideEffects
, that is, export
will always be used to determine whether to use it. In addition, sideEffects
will depend on providedExports
to find 0620d9009a1895 of all export
in the module
:
Here's sideEffects is used:
{
"name": "tree-shaking",
"sideEffects": false,
"version": "1.0.0",
...
}
As long as package.json
is added to sideEffects
, and the value is set to flase
, it means that all the codes in the project do not have side effect
, so Webpack can remove the unused export
code when packing.
After adding sideEffects
and packing, you will not see composeString
in the result:
Then now we go to src
to create another polyfill.js
, create a custom method for Array in ployfill.js
, and then put it in import
to index.js
:
index.js
import './polyfill';
import { add } from './math';
import { addString } from './string';
console.log([].customMethod());
polyfill.js
Array.prototype.customMethod = () => {
console.log('customMethods');
};
If we package the above code, polyfill.js
will not be caught by providedExports
because there is no export
, and it will not be packaged into Production
, which will cause an error during execution if the project uses customMethod
of Array . Faced with this situation, it is necessary to inform in the sideEffects property that polyfill.js
has side effects. The setting method is as follows:
{
"name": "tree-shaking",
"sideEffects": ["./src/polyfill.js"],
"version": "1.0.0",
...
}
In this way ,polyfill.js
will be packaged directly:
Finally, two things to note:
- If you also use the
import.css
style in your project, remember to put the file name ending in.css
in sideEffects, such assideEffects: ["*.css"]
. webpack.config.js
inoptimization
also hassideEffects
, but the value set here is fornode_modules
.
useExported
The role of useExported
and sideEffects
are both used to determine whether to remove the code, but according to the instructions in the Webpack file, useExported
is the real Tree Shaking:
usedExports
use terser judgment code has no side effect
, if not used, and no side effect
, it would mark on its behalf during packaging unused harmony
, and minify
(with UglifyJS or other tools) when removed.
Before testing usedExports
, add square
and math.js
to export
:
const add = (a, b) => a + b;
const square = (a, b) => a * b;
export { add, square };
Next, add optimization.usedExports
webpack.config.js
module.exports = {
...
optimization: {
usedExports: true,
}
};
Then package the project and you will find that it is only export
, but the square
will be marked with unused harmony export
:
Then we use uglifyjs-webpack-plugin to shake the unused square
from the tree:
npm install -d uglifyjs-webpack-plugin
The settings for webpack.config.js
are as follows:
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
...
optimization: {
usedExports: true,
minimize: true,
minimizer: [
new UglifyJsPlugin({
uglifyOptions: {
compress: { unused: true },
mangle: false,
output: {
beautify: true
}
},
})
],
}
};
After setting minimizer
, pack it again, and you can see that square
has been removed:
The difference between usedExports
and sideEffects
is that usedExports
can use declarative sentences as a unit to determine whether there is side effect
, but sideEffects allows Webpack to skip an entire file when packaging, as long as the file appears in sideEffect
, it is directly packaged, and it is unnecessary. Side effects were assessed by terser
.
Summarize
- Tree Shaking can only be used in
static structure
. Ifbabel
in the project will compilestatic structure
intodynamic structure
, it needs to be set separately. - When using sideEffects, it should be written in
package.json
, if it is to optimize the third-party library, it should be written inwebpack.config.js
inoptimization
. usedExports
is Tree Shacking. When using it, it will automatically determine the unused code and mark the annotation ofunused harmony
. If you want to remove it, you need to useminify
.
The bugs that may exist after the code is deployed cannot be known in real time. In order to solve these bugs afterwards, a lot of time is spent on log debugging. By the way, I recommend a useful bug monitoring tool Fundebug .
comminicate
If you have dreams and dry goods, search [Moving the World] attention to this brush bowl wisdom who is still washing dishes in the early morning.
This article has been included in GitHub https://github.com/qq449245884/xiaozhi . There are complete test sites, materials and my series of articles for interviews with first-tier manufacturers.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。