Skip to content

Commit c92f0df

Browse files
committed
docs(guides): rewrite/re-outline the tree-shaking page
This continues our work #1258 and resolves most of the issues mentioned in #1331. It is a WIP though, we still need to populate the `TODO` code blocks.
1 parent 2b9b3e4 commit c92f0df

File tree

1 file changed

+94
-43
lines changed

1 file changed

+94
-43
lines changed

content/guides/tree-shaking.md

+94-43
Original file line numberDiff line numberDiff line change
@@ -14,75 +14,126 @@ related:
1414
url: https://medium.com/modus-create-front-end-development/webpack-2-tree-shaking-configuration-9f1de90f3233#.15tuaw71x
1515
---
1616

17-
_Tree shaking_ is a term commonly used in the JavaScript context for dead-code elimination, or more precisely, live-code import. It relies on ES2015 module [import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import)/[export](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export) for the [static structure](http://exploringjs.com/es6/ch_modules.html#static-module-structure) of its module system. The name and concept have been popularized by the ES2015 module bundler [rollup](https://github.com/rollup/rollup).
17+
_Tree shaking_ is a term commonly used in the JavaScript context for dead-code elimination. It relies on the [static structure](http://exploringjs.com/es6/ch_modules.html#static-module-structure) of ES2015 module syntax, i.e. [`import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) and [`export`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export). The name and concept have been popularized by the ES2015 module bundler [rollup](https://github.com/rollup/rollup).
1818

19-
webpack 2 comes with a built-in support for ES2015 modules (alias *harmony modules*) as well as unused module export detection.
19+
The webpack 2 release came with built-in support for ES2015 modules (alias _harmony modules_) as well as unused module export detection.
2020

21+
T> The remainder of this guide will stem from [Getting Started](/guides/getting-started). If you haven't read through that guide already, please do so now.
2122

22-
## Example
2323

24-
Consider a **maths.js** library file exporting two functions, `square` and `cube`:
24+
## Add a Utility
2525

26-
```javascript
27-
// This function isn't used anywhere
26+
Let's add a new utility file to our project, `src/math.js`, that exports two functions:
27+
28+
__project__
29+
30+
``` diff
31+
webpack-demo
32+
|- package.json
33+
|- webpack.config.js
34+
|- /dist
35+
|- bundle.js
36+
|- index.html
37+
|- /src
38+
|- index.js
39+
|- math.js
40+
|- /node_modules
41+
```
42+
43+
__src/math.js__
44+
45+
``` javascript
2846
export function square(x) {
2947
return x * x;
3048
}
3149

32-
// This function gets included
3350
export function cube(x) {
3451
return x * x * x;
3552
}
3653
```
3754

38-
In our **main.js** we are selectively importing `cube`:
55+
With that in place, let's update our entry script to utilize this one of these new methods:
56+
57+
``` diff
58+
import _ from 'lodash';
59+
+ import { cube } from './math.js';
3960

40-
```javascript
41-
import {cube} from './maths.js';
42-
console.log(cube(5)); // 125
61+
function component() {
62+
var element = document.createElement('div');
63+
64+
// Lodash, now imported by this script
65+
- element.innerHTML = _.join(['Hello', 'webpack'], ' ');
66+
+ element.innerHTML = _.join([
67+
'Hello webpack!',
68+
'5 cubed is equal to ' + cube(5)
69+
], '\n\n');
70+
71+
return element;
72+
}
73+
74+
document.body.appendChild(component());
4375
```
4476

45-
Running `node_modules/.bin/webpack main.js dist.js` and inspecting `dist.js` reveals that `square` is not being exported (see the "unused harmony export square" comment):
77+
Note that we __did not `import` the `square` method__ from the `src/math.js` module. That function is what's known as "dead code", meaning an unused `export` that should be dropped. Now let's run our npm script, `npm run build`, and inspect the output:
4678

47-
```javascript
48-
/* ... webpackBootstrap ... */
49-
/******/ ([
50-
/* 0 */
51-
/***/ (function(module, __webpack_exports__, __webpack_require__) {
79+
__dist/bundle.js__
5280

53-
"use strict";
54-
/* unused harmony export square */
55-
/* harmony export (immutable) */ __webpack_exports__["a"] = cube;
56-
// This function isn't used anywhere
57-
function square(x) {
58-
return x * x;
59-
}
81+
``` js
82+
// TODO: Display contents with `unused harmony export square`...
83+
```
6084

61-
// This function gets included
62-
function cube(x) {
63-
return x * x * x;
64-
}
85+
Note the `unused harmony export square` comment above. If you look at the code below it, you'll notice that `square` is not being exported, however, it is still included in the bundle. We'll fix that in the next section.
86+
87+
88+
## Minify the Output
6589

66-
/***/ }),
67-
/* 1 */
68-
/***/ (function(module, __webpack_exports__, __webpack_require__) {
90+
So we've cued up our "dead code" to be dropped by using the `import` and `export` syntax, but we still need to drop it from the bundle. To do that, we'll add a minifier that supports dead code removal -- the [`UglifyJSPlugin`](/plugins/uglifyjs-webpack-plugin) -- to our configuration...
6991

70-
"use strict";
71-
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
72-
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__maths_js__ = __webpack_require__(0);
92+
Let's start by installing it:
7393

74-
console.log(__webpack_require__.i(__WEBPACK_IMPORTED_MODULE_0__maths_js__["a" /* cube */])(5)); // 125
94+
``` bash
95+
npm i --save-dev uglifyjs-webpack-plugin
96+
```
7597

76-
/***/ })
98+
And then adding it into our config:
99+
100+
__webpack.config.js__
101+
102+
``` diff
103+
const path = require('path');
104+
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
105+
106+
module.exports = {
107+
entry: './src/index.js',
108+
output: {
109+
filename: 'bundle.js',
110+
path: path.resolve(__dirname, 'dist')
111+
- }
112+
+ },
113+
+ plugins: [
114+
+ new UglifyJSPlugin()
115+
+ ]
116+
};
77117
```
78118

79-
When running a [production build](/guides/production), `node_modules/.bin/webpack --optimize-minimize main.js dist.min.js`, only the minimized version of `cube` but not `square` remains in the build:
119+
T> Note that the `--optimize-minimize` flag can be used to insert the `UglifyJsPlugin` as well.
120+
121+
With that squared away, we can run another `npm run build` and see if anything has changed:
122+
123+
__dist/bundle.js__
80124

81-
```javascript
82-
/* ... */
83-
function(e,t,n){"use strict";function r(e){return e*e*e}t.a=r}
84-
/* ... */
85-
function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=n(0);console.log(n.i(r.a)(5))}
125+
``` js
126+
// TODO: Display contents with `square removed...
86127
```
87128

88-
T> Note that the `--optimize-minimize` flag enables tree shaking by including the `UglifyJsPlugin` behind the scenes. Alternatively, the `UglifyJsPlugin` can be included manually in the `plugins` section of your configuration file. The plugin, combined with webpack's resolving of `import` and `export` statements, is what makes tree shaking possible. See the [production build](/guides/production) guide for more information.
129+
Notice anything missing? The `square` function has been dropped and our output bundle is now a few bytes smaller! While that may not seem like much in this contrived example, tree shaking can yield a significant decrease in bundle size when working on larger applications with complex dependency trees.
130+
131+
132+
## Conclusion
133+
134+
So, what we've learned is that in order to take advantage of _tree shaking_, you must...
135+
136+
- Use ES2015 module syntax (i.e. `import` and `export`).
137+
- Include a minifier that supports dead code removal (e.g. the `UglifyJSPlugin`).
138+
139+
If you are interested in more ways to optimize your output, please jump to the next guide for details on building for [production](/guides/production).

0 commit comments

Comments
 (0)