Skip to content

Commit 8af0320

Browse files
authored
Merge pull request webpack#7344 from asapach/master
feat: support tree shaking in DllPlugin
2 parents 713292f + aa99385 commit 8af0320

File tree

21 files changed

+479
-1
lines changed

21 files changed

+479
-1
lines changed

examples/dll-entry-only/README.md

Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
# Dll scope hoisting
2+
3+
[DllPlugin documentation](https://webpack.js.org/plugins/dll-plugin)
4+
5+
This example demonstrates the usage of `entryOnly` option in combination with module concatenation / scope hoisting.
6+
7+
By default `DllPlugin` exposes all the modules referenced in the bundle as separate entries.
8+
The manifest includes the individual modules available for use by `DllReferencePlugin`.
9+
Since all the modules are being accounted for, this prevents advanced optimizations such as tree shaking.
10+
11+
The `entryOnly` flag tells `DllPlugin` to only expose the modules which are configured as entry points;
12+
this affects both the manifest and the resulting bundle.
13+
Since some of the modules are no longer included in the "public contract" of the Dll,
14+
they can be optimized by merging (concatenating) multiple modules together or removing unused code.
15+
This allows to take advantage of tree shaking (scope hoisting and dead code removal) optimizations.
16+
17+
In this example only `example.js` module is exposed, since it's the entry point.
18+
Modules `a.js` and `b.js` are concatenated into `example.js`.
19+
Module `cjs.js` is left as is, since it's in CommonJS format.
20+
21+
The manifest includes `example.js` as the only exposed module and lists the exports as `["a","b","c"]`
22+
from the corresponding modules `a.js`, `b.js` and `cjs.js`. None of the other modules are exposed.
23+
24+
Also see [tree shaking](https://github.com/webpack/webpack/tree/master/examples/harmony-unused)
25+
and [scope hoisting example](https://github.com/webpack/webpack/tree/master/examples/scope-hoisting).
26+
27+
28+
# example.js
29+
30+
``` javascript
31+
export { a, b } from "./a";
32+
export { c } from "./cjs";
33+
```
34+
35+
# webpack.config.js
36+
37+
``` javascript
38+
var path = require("path");
39+
var webpack = require("../../");
40+
41+
module.exports = {
42+
// mode: "development" || "production",
43+
entry: {
44+
dll: ["./example"]
45+
},
46+
output: {
47+
path: path.join(__dirname, "dist"),
48+
filename: "[name].js",
49+
library: "[name]_[hash]"
50+
},
51+
optimization: {
52+
concatenateModules: true // this is enabled by default in production mode
53+
},
54+
plugins: [
55+
new webpack.DllPlugin({
56+
path: path.join(__dirname, "dist", "[name]-manifest.json"),
57+
name: "[name]_[hash]",
58+
entryOnly: true
59+
})
60+
]
61+
};
62+
```
63+
64+
# dist/dll.js
65+
66+
``` javascript
67+
var dll_3392692e94d8b928900f =
68+
```
69+
<details><summary><code>/******/ (function(modules) { /* webpackBootstrap */ })</code></summary>
70+
71+
``` js
72+
/******/ (function(modules) { // webpackBootstrap
73+
/******/ // The module cache
74+
/******/ var installedModules = {};
75+
/******/
76+
/******/ // The require function
77+
/******/ function __webpack_require__(moduleId) {
78+
/******/
79+
/******/ // Check if module is in cache
80+
/******/ if(installedModules[moduleId]) {
81+
/******/ return installedModules[moduleId].exports;
82+
/******/ }
83+
/******/ // Create a new module (and put it into the cache)
84+
/******/ var module = installedModules[moduleId] = {
85+
/******/ i: moduleId,
86+
/******/ l: false,
87+
/******/ exports: {}
88+
/******/ };
89+
/******/
90+
/******/ // Execute the module function
91+
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
92+
/******/
93+
/******/ // Flag the module as loaded
94+
/******/ module.l = true;
95+
/******/
96+
/******/ // Return the exports of the module
97+
/******/ return module.exports;
98+
/******/ }
99+
/******/
100+
/******/
101+
/******/ // expose the modules object (__webpack_modules__)
102+
/******/ __webpack_require__.m = modules;
103+
/******/
104+
/******/ // expose the module cache
105+
/******/ __webpack_require__.c = installedModules;
106+
/******/
107+
/******/ // define getter function for harmony exports
108+
/******/ __webpack_require__.d = function(exports, name, getter) {
109+
/******/ if(!__webpack_require__.o(exports, name)) {
110+
/******/ Object.defineProperty(exports, name, {
111+
/******/ configurable: false,
112+
/******/ enumerable: true,
113+
/******/ get: getter
114+
/******/ });
115+
/******/ }
116+
/******/ };
117+
/******/
118+
/******/ // define __esModule on exports
119+
/******/ __webpack_require__.r = function(exports) {
120+
/******/ Object.defineProperty(exports, '__esModule', { value: true });
121+
/******/ };
122+
/******/
123+
/******/ // getDefaultExport function for compatibility with non-harmony modules
124+
/******/ __webpack_require__.n = function(module) {
125+
/******/ var getter = module && module.__esModule ?
126+
/******/ function getDefault() { return module['default']; } :
127+
/******/ function getModuleExports() { return module; };
128+
/******/ __webpack_require__.d(getter, 'a', getter);
129+
/******/ return getter;
130+
/******/ };
131+
/******/
132+
/******/ // Object.prototype.hasOwnProperty.call
133+
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
134+
/******/
135+
/******/ // __webpack_public_path__
136+
/******/ __webpack_require__.p = "dist/";
137+
/******/
138+
/******/
139+
/******/ // Load entry module and return exports
140+
/******/ return __webpack_require__(__webpack_require__.s = 0);
141+
/******/ })
142+
/************************************************************************/
143+
```
144+
145+
</details>
146+
147+
``` js
148+
/******/ ([
149+
/* 0 */
150+
/*!***************!*\
151+
!*** dll dll ***!
152+
\***************/
153+
/*! no static exports found */
154+
/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
155+
/***/ (function(module, exports, __webpack_require__) {
156+
157+
module.exports = __webpack_require__;
158+
159+
/***/ }),
160+
/* 1 */
161+
/*!****************!*\
162+
!*** ./cjs.js ***!
163+
\****************/
164+
/*! no static exports found */
165+
/*! ModuleConcatenation bailout: Module is not an ECMAScript module */
166+
/***/ (function(module, exports) {
167+
168+
// module cjs (commonjs)
169+
exports.c = "c";
170+
171+
172+
/***/ }),
173+
/* 2 */
174+
/*!********************************!*\
175+
!*** ./example.js + 2 modules ***!
176+
\********************************/
177+
/*! exports provided: a, b, c */
178+
/*! ModuleConcatenation bailout: Cannot concat with ./cjs.js (<- Module is not an ECMAScript module) */
179+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
180+
181+
"use strict";
182+
183+
// CONCATENATED MODULE: ./b.js
184+
// module b
185+
function b() {
186+
return "b";
187+
}
188+
189+
// CONCATENATED MODULE: ./a.js
190+
// module a
191+
var a = "a";
192+
193+
194+
// EXTERNAL MODULE: ./cjs.js
195+
var cjs = __webpack_require__(1);
196+
197+
// CONCATENATED MODULE: ./example.js
198+
/* concated harmony reexport */__webpack_require__.d(__webpack_exports__, "a", function() { return a; });
199+
/* concated harmony reexport */__webpack_require__.d(__webpack_exports__, "b", function() { return b; });
200+
/* concated harmony reexport */__webpack_require__.d(__webpack_exports__, "c", function() { return cjs["c"]; });
201+
202+
203+
204+
205+
/***/ })
206+
/******/ ]);
207+
```
208+
209+
# dist/dll-manifest.json
210+
211+
``` javascript
212+
{"name":"dll_3392692e94d8b928900f","content":{"./example.js":{"id":2,"buildMeta":{"exportsType":"namespace","providedExports":["a","b","c"]}}}}
213+
```
214+
215+
# Info
216+
217+
## Unoptimized
218+
219+
```
220+
Hash: 0a1b2c3d4e5f6a7b8c9d
221+
Version: webpack 4.8.3
222+
Asset Size Chunks Chunk Names
223+
dll.js 4.01 KiB 0 [emitted] dll
224+
Entrypoint dll = dll.js
225+
chunk {0} dll.js (dll) 216 bytes [entry] [rendered]
226+
> dll
227+
[0] dll dll 12 bytes {0} [built]
228+
dll entry
229+
[1] ./cjs.js 42 bytes {0} [built]
230+
harmony side effect evaluation ./cjs [2] ./example.js + 2 modules 2:0-26
231+
harmony export imported specifier ./cjs [2] ./example.js + 2 modules 2:0-26
232+
[2] ./example.js + 2 modules 162 bytes {0} [built]
233+
[exports: a, b, c]
234+
single entry ./example [0] dll dll dll:0
235+
| ./example.js 55 bytes [built]
236+
| [exports: a, b, c]
237+
| single entry ./example [0] dll dll dll:0
238+
| ./a.js 53 bytes [built]
239+
| [exports: a, b]
240+
| harmony side effect evaluation ./a ./example.js 1:0-27
241+
| harmony export imported specifier ./a ./example.js 1:0-27
242+
| harmony export imported specifier ./a ./example.js 1:0-27
243+
| ./b.js 49 bytes [built]
244+
| [exports: b]
245+
| harmony side effect evaluation ./b ./a.js 3:0-20
246+
| harmony export imported specifier ./b ./a.js 3:0-20
247+
```
248+
249+
## Production mode
250+
251+
```
252+
Hash: 0a1b2c3d4e5f6a7b8c9d
253+
Version: webpack 4.8.3
254+
Asset Size Chunks Chunk Names
255+
dll.js 791 bytes 0 [emitted] dll
256+
Entrypoint dll = dll.js
257+
chunk {0} dll.js (dll) 216 bytes [entry] [rendered]
258+
> dll
259+
[0] ./cjs.js 42 bytes {0} [built]
260+
[only some exports used: c]
261+
harmony side effect evaluation ./cjs [1] ./example.js + 2 modules 2:0-26
262+
harmony export imported specifier ./cjs [1] ./example.js + 2 modules 2:0-26
263+
[1] ./example.js + 2 modules 162 bytes {0} [built]
264+
[exports: a, b, c]
265+
single entry ./example [2] dll dll dll:0
266+
| ./example.js 55 bytes [built]
267+
| [exports: a, b, c]
268+
| single entry ./example [2] dll dll dll:0
269+
| ./a.js 53 bytes [built]
270+
| [exports: a, b]
271+
| [all exports used]
272+
| harmony side effect evaluation ./a ./example.js 1:0-27
273+
| harmony export imported specifier ./a ./example.js 1:0-27
274+
| harmony export imported specifier ./a ./example.js 1:0-27
275+
| ./b.js 49 bytes [built]
276+
| [exports: b]
277+
| [all exports used]
278+
| harmony side effect evaluation ./b ./a.js 3:0-20
279+
| harmony export imported specifier ./b ./a.js 3:0-20
280+
[2] dll dll 12 bytes {0} [built]
281+
dll entry
282+
```

examples/dll-entry-only/a.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// module a
2+
export var a = "a";
3+
export * from "./b";

examples/dll-entry-only/b.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// module b
2+
export function b() {
3+
return "b";
4+
}

examples/dll-entry-only/build.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
global.NO_TARGET_ARGS = true;
2+
require("../build-common");

examples/dll-entry-only/cjs.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// module cjs (commonjs)
2+
exports.c = "c";

examples/dll-entry-only/example.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { a, b } from "./a";
2+
export { c } from "./cjs";

examples/dll-entry-only/template.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Dll scope hoisting
2+
3+
[DllPlugin documentation](https://webpack.js.org/plugins/dll-plugin)
4+
5+
This example demonstrates the usage of `entryOnly` option in combination with module concatenation / scope hoisting.
6+
7+
By default `DllPlugin` exposes all the modules referenced in the bundle as separate entries.
8+
The manifest includes the individual modules available for use by `DllReferencePlugin`.
9+
Since all the modules are being accounted for, this prevents advanced optimizations such as tree shaking.
10+
11+
The `entryOnly` flag tells `DllPlugin` to only expose the modules which are configured as entry points;
12+
this affects both the manifest and the resulting bundle.
13+
Since some of the modules are no longer included in the "public contract" of the Dll,
14+
they can be optimized by merging (concatenating) multiple modules together or removing unused code.
15+
This allows to take advantage of tree shaking (scope hoisting and dead code removal) optimizations.
16+
17+
In this example only `example.js` module is exposed, since it's the entry point.
18+
Modules `a.js` and `b.js` are concatenated into `example.js`.
19+
Module `cjs.js` is left as is, since it's in CommonJS format.
20+
21+
The manifest includes `example.js` as the only exposed module and lists the exports as `["a","b","c"]`
22+
from the corresponding modules `a.js`, `b.js` and `cjs.js`. None of the other modules are exposed.
23+
24+
Also see [tree shaking](https://github.com/webpack/webpack/tree/master/examples/harmony-unused)
25+
and [scope hoisting example](https://github.com/webpack/webpack/tree/master/examples/scope-hoisting).
26+
27+
28+
# example.js
29+
30+
``` javascript
31+
{{example.js}}
32+
```
33+
34+
# webpack.config.js
35+
36+
``` javascript
37+
{{webpack.config.js}}
38+
```
39+
40+
# dist/dll.js
41+
42+
``` javascript
43+
{{dist/dll.js}}
44+
```
45+
46+
# dist/dll-manifest.json
47+
48+
``` javascript
49+
{{dist/dll-manifest.json}}
50+
```
51+
52+
# Info
53+
54+
## Unoptimized
55+
56+
```
57+
{{stdout}}
58+
```
59+
60+
## Production mode
61+
62+
```
63+
{{production:stdout}}
64+
```
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
var path = require("path");
2+
var webpack = require("../../");
3+
4+
module.exports = {
5+
// mode: "development" || "production",
6+
entry: {
7+
dll: ["./example"]
8+
},
9+
output: {
10+
path: path.join(__dirname, "dist"),
11+
filename: "[name].js",
12+
library: "[name]_[hash]"
13+
},
14+
optimization: {
15+
concatenateModules: true // this is enabled by default in production mode
16+
},
17+
plugins: [
18+
new webpack.DllPlugin({
19+
path: path.join(__dirname, "dist", "[name]-manifest.json"),
20+
name: "[name]_[hash]",
21+
entryOnly: true
22+
})
23+
]
24+
};

0 commit comments

Comments
 (0)