example of configuring DLLPlugin for Webpack 2.x
This repo contains two example projects:
- app-code: an admittedly pretty basic react application. It renders "Hello from react v{version} :)" to the DOM. App-code includes Vendor-code as a dependency.
- vendor-code: a platform library that includes both React and ReactDOM as a DLL.
$ # in vendor-code
$ npm install && npm run build
$ # in component-code
$ npm install && npm run build
$ # in app-code
$ npm install && npm run build
$ # in app-code
$ npm run deploy
Then start a web server in the ./app-code
directory and load the Index.html file (or just open the index.html file in your browser, either should work).
The app-code project sets up the DllReferencePlugin so that it reads the vendor-code manifest.json file (which gets generated by the DLLPlugin in vendor-code). This manifest file is very similar to the webpack.records
files that each project outputs. They map the internal webpack module ids (the numbers used in _webpack_require(XXX)
) to a specific entry point in the library. So when webpack encounters require('react')
it maps that to the physical path ./node_modules/react/index.js
. This path is listed in the manifest.json file:
"./node_modules/react/react.js": {
"id": 1,
"meta": {}
},
Which tells webpack that that dependency should be replaced with vendor_{hash}(1);
in the generated code. Webpack may alter this number (due to how it numbers dependencies internally) but thats the general idea.
Performance is a big reason. Both page loads and build speeds will benefit from this change if we can roll it out to even some of our libraries.
Hash: 4fe7ac1ae2000ee97e2b
Version: webpack 2.2.0
Time: 86ms
Asset Size Chunks Chunk Names
./output/app.js 3.41 kB 0 [emitted] app
[0] ./index.js 188 bytes {0} [built]
[180] delegated ./node_modules/react/react.js from dll-reference vendor_0ef5df22b0e16ddf1a0d 42 bytes {0} [not cacheable] [built]
[182] delegated ./node_modules/react-dom/index.js from dll-reference vendor_0ef5df22b0e16ddf1a0d 42 bytes {0} [not cacheable] [built]
[298] ./welcome.js 223 bytes {0} [built]
+ 1 hidden modules
Scoping, apparently the docs say you can scope the dependencies by setting aTurned out I was using scoping a bit incorrectly. The value specified for ascope
prop on the DllReferencePlugin config, so we could dorequire('platform/react');
instead of just requiring react. I think this scoping would be nicer and more obvious, but this option didn't work for me.scope
can't match an existing package name or path otherwise webpack will just try to resolve whatever file you've asked for there. If you use a value that isn't matched to a real path on disk or another package then webpack will delegate correctly to the DLL plugin.- Node vs browser, i think we'd have to emit separate bundles (not manifests) for node and the browser, since the libraryTarget differs between the two (browser is 'var' while node is 'commonsjs2')
Multiple DLLs, I'd like to prove out having multiple dll dependencies, e.g. the platform (vendor-code) dll and a components dll that depends on platform.This works pretty seemlessly. No issues. Was able to add another DLL to the app project even when that DLL depended on the vendor DLL. Webpack correctly resolved everything.- Upgrading platform without re-compiling app. I think as long as the manifest file stays the same we can swap vendor bundles and the code should work. This should be pretty simple to prove, just build vendor-code with a slightly older version of react and replace the file path in the HTML.