Perhaps one of my favorite webpack performance related tricks is setting up DLLs so that you avoid work. The problem is that maintaining the setup requires time and effort. What if there was a better way?
James Wiens has been exploring a better solution with d-l-l.
👋 I'm a flow state enthusiast and crafting code is my life's passion. I'm from Vancouver, Canada, eh.
d-l-l makes your webpack build faster in just a few lines, without having to waste time on the slow manual configuration steps required to use the DllPlugin.
The DllPlugin lets you pre-build the parts of your code that don't often change (such as library code). This means when you change the parts that do change more often, webpack only needs to build these parts, which makes builds exponentially faster.
d-l-l adds some helpful utilities for finding and adding dependencies and files that do not often change.
const dll = require('d-l-l')
module.exports = dll
.init()
// Directory to resolve paths from
.dir(__dirname)
// Pass in webpack config
.config(config)
// Filter to only use non-dev dependencies
.pkgDeps((deps, dev, all) => deps)
// Find all src files
.find('src/**/*.+(js|jsx)')
// Filter to files last modified at least a day ago
.lastModifiedFilter({days: 1})
// Return an array of webpack configurations
.toConfig()
d-l-l creates an array of webpack configuration consisting of a DLL-only webpack config followed by the existing config from your webpack.config.js.
Cache files are created in a .fliphub
folder, which allows some smart-ish checks such as:
.config()
The cache files also allow d-l-l to add the decorated dll config if no cache folder or files exist or if there are no manifest files showing what was built and where.
When the cache should be cleared is configurable:
Now that we've covered a bit of background, an advanced use case should be more understandable:
const dll = require('d-l-l')
const configs = dll
.init()
// Verbose debugging
.debug(true)
// Force building of DLL
.shouldBeUsed(true)
// Return original config, makes it easy to swap side-effect free
.og(true)
// Same as in the simple example above
.dir(__dirname)
.config(config)
// Provide resolved dependency paths manually
.deps(['lodash', 'inferno'].map(dep => require.resolve(dep)))
// Filter dependencies in package.json
.pkgDeps((deps, devDeps, allDeps)) => {
// Ignore dependencies that have `dev` in them.
// Development tools are one example.
return deps.filter(dep => !/dev/.test(dep))
})
// Find files matching a glob
.find('src/**/*.+(js|jsx)')
.lastModifiedFilter({days: 1})
// Return an array of webpack configurations
.toConfig()
There are no other solutions. The only other option is do everything d-l-l does yourself manually. Doing this means maintaining the additional DLL configuration and referencing it in your code. The point of d-l-l is to avoid this complexity.
Editor's note: autodll-webpack-plugin is a comparable plugin based solution.
I was developing fliphub and found there was no webpack documentation for the DllPlugin. As I researched and experimented with the plugin, I discovered how powerful it was but how clunky it was to configure it.
To expand on what I mean by clunky, the DllPlugin requires two separate webpack configurations! The order is important - the DLL config has to be built before the normal config. If the normal config uses the DLLReferencePlugin before the DLL config has been built, the build will fail.
Adding even more commands to the build process wasn't going to happen, so d-l-l was born.
d-l-l will be updated with more features. In an ideal future, the core solution it provides would be integrated into webpack core.
The minimum, most effective plan to integrate it into the core would involve the following changes for d-l-l:
Once that would be done, the whole community could benefit from the functionality.
All of the libraries I create use chain-able, which enables me to easily create interfaces that describe their intentions and make simple solutions for complex problems.
I plan to create a wrapper library around webpack (webpack-wrap), allowing easy and smart configuration by following this plan:
I couldn't fit it reasonably in this block, so I made it into a repo: awesome-advice.
Thanks for the interview James! I hope this work eventually finds its way to webpack proper. That would make the approach more approachable to a lot of people.
You can find d-l-l on GitHub.
See also the following resources for further information: