1 | # CommonJS Tree Shaker plugin for Webpack
|
2 | [![NPM version](https://badge.fury.io/js/webpack-common-shake.svg)](http://badge.fury.io/js/webpack-common-shake)
|
3 | [![Build Status](https://secure.travis-ci.org/indutny/webpack-common-shake.svg)](http://travis-ci.org/indutny/webpack-common-shake)
|
4 |
|
5 | ![Fancy shaking logo](https://github.com/indutny/webpack-common-shake/blob/master/logo/shake.gif)
|
6 |
|
7 | Please file an [issue][0] if anything is broken.
|
8 |
|
9 | See [common-shake][1] for abstract bundler-independent implementation.
|
10 |
|
11 | _NOTE: [webpack][2] version 3 may be needed in order to run this._
|
12 |
|
13 | _NOTE: Logo is a modified version of [webpack's logo][5]_
|
14 |
|
15 | ## Why?
|
16 |
|
17 | There are vast amount of CommonJS modules out there. Thus CommonJS Tree Shaking
|
18 | is as important as the ESM module import/export shaking.
|
19 |
|
20 | ## How?
|
21 |
|
22 | This plugin removes unused assignments to `exports` properties leaving removal
|
23 | of the (presumably) dead code to UglifyJS. If, for example, you had a module:
|
24 |
|
25 | ```js
|
26 | exports.used = 1;
|
27 | var tmp = exports.unused = 2;
|
28 | ```
|
29 |
|
30 | This plugin will transform it to:
|
31 |
|
32 | ```js
|
33 | exports.used = 1;
|
34 | var tmp = 2;
|
35 | ```
|
36 |
|
37 | It is up to UglifyJS (or some other optimizer) to decide, whether `tmp` is used
|
38 | or not and delete it. Luckily it is much simpler for it to do if the uses are
|
39 | not clouded by exporting the values.
|
40 |
|
41 | ## Usage
|
42 |
|
43 | Example `webpack.config.js`:
|
44 | ```js
|
45 | const ShakePlugin = require('webpack-common-shake').Plugin;
|
46 |
|
47 | module.exports = [{
|
48 | entry: 'entry.js'
|
49 | output: {
|
50 | path: 'dist',
|
51 | filename: 'output.js'
|
52 | },
|
53 | plugins: [ new ShakePlugin() ]
|
54 | }];
|
55 | ```
|
56 |
|
57 | ## Demonstration
|
58 |
|
59 | See [webpack-common-shake-demo][4] for size comparison of output with and
|
60 | without this plugin.
|
61 |
|
62 | ## Options
|
63 |
|
64 | Plugin constructor accepts `options` object which may have following properties:
|
65 |
|
66 | ```js
|
67 | const plugin = new ShakePlugin({
|
68 | warnings: {
|
69 | global: true,
|
70 | module: false
|
71 | } /* default */,
|
72 |
|
73 | // Invoked on every deleted unused property
|
74 | onExportDelete: (resource, property) => {},
|
75 |
|
76 | // See `Limitations` section for description
|
77 | onModuleBailout: (module, bailouts) => { ... },
|
78 | onGlobalBailout: (bailouts) => { ... }
|
79 | });
|
80 | ```
|
81 |
|
82 | ## Limitations
|
83 |
|
84 | Although, generally this module works and helps removing unused code from the
|
85 | bundles. There are some limitations that may prevent it from running either
|
86 | partially or completely. Some examples are provided below, otherwise please use
|
87 | common sense (or `onModuleBailout`, `onGlobalBailout` plugin options).
|
88 |
|
89 | Some local (partial) bailouts:
|
90 |
|
91 | * Dynamic exports `exports[Math.random()] = ...`
|
92 | * Overriding imported vars `var a = require('./a'); a.lib; a = require('./b')`
|
93 | * Using `require` in unknown way `console.log(require('./lib'))`
|
94 | * Destructuring `require` dynamically `{ [prop]: name } = require('./a')`
|
95 | * Dynamic import `var fn = require('./lib')[Math.random()]`
|
96 |
|
97 | Some global (full) bailouts:
|
98 |
|
99 | * Dynamic use of require `require(Math.random())`
|
100 |
|
101 | This plugin will print some webpack warnings. In any case, bailouts may be
|
102 | obtained programmatically too:
|
103 |
|
104 | ```js
|
105 | const plugin = new ShakePlugin({
|
106 | onModuleBailout: (module, bailouts) => { ... },
|
107 | onGlobalBailout: (bailouts) => { ... }
|
108 | });
|
109 | ```
|
110 |
|
111 | ## Graph
|
112 |
|
113 | For debugging and inspection purposes a graph in [dot][3] format may be
|
114 | obtained using `onGraph` option:
|
115 |
|
116 | ```js
|
117 | const plugin = new ShakePlugin({
|
118 | onGraph: (graph) => { ... }
|
119 | });
|
120 | ```
|
121 |
|
122 | ## LICENSE
|
123 |
|
124 | This software is licensed under the MIT License.
|
125 |
|
126 | Copyright Fedor Indutny, 2017.
|
127 |
|
128 | Permission is hereby granted, free of charge, to any person obtaining a
|
129 | copy of this software and associated documentation files (the
|
130 | "Software"), to deal in the Software without restriction, including
|
131 | without limitation the rights to use, copy, modify, merge, publish,
|
132 | distribute, sublicense, and/or sell copies of the Software, and to permit
|
133 | persons to whom the Software is furnished to do so, subject to the
|
134 | following conditions:
|
135 |
|
136 | The above copyright notice and this permission notice shall be included
|
137 | in all copies or substantial portions of the Software.
|
138 |
|
139 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
140 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
141 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
142 | NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
143 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
144 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
145 | USE OR OTHER DEALINGS IN THE SOFTWARE.
|
146 |
|
147 | [0]: https://github.com/indutny/webpack-common-shake/issues
|
148 | [1]: https://github.com/indutny/common-shake
|
149 | [2]: https://webpack.github.io/
|
150 | [3]: http://www.graphviz.org/content/dot-language
|
151 | [4]: https://github.com/indutny/webpack-common-shake-demo
|
152 | [5]: https://github.com/webpack/media/issues/12
|