How to work faster with npm and webpack
One of the most beautiful parts about full-stack JavaScript is how open the community is, how easy it is to get started, and how many choices you have. With all these choices, it’s hard to find the gems. So for this post, I’m sharing all the awesome packages and practices that make me so insanely productive that I have enough time to… write a medium article about increasing productivity.
local-npm: Local and offline-first npm mirror
npm3 is a dog when it comes to download speed. Yeah, we know it does more checking & the flat folders are nice, blah blah, but that doesn’t mean much when running npm install takes 10 freaking minutes. This nifty package caches all the npm packages you’ve downloaded & then tries fetching a local copy before going out to the npm registry. If you’ve got good internet, this will save you hours. If you’re like me & live in a country where good internets aren’t always available, even moreso. To see what it’s doing, just run pm2 logs to watch all the cache hits. It’ll make your day.
Turn off the npm progress bar
Now that you can see local-npm fetching all your dependencies, there’s no reason for a npm progress bar, especially when it unexplainably slows you down. So, just disable it by running the following from a terminal:
npm set progress=false
n: Interactively Manage All Your Node Versions
n is a really simple tool to install/upgrade/downgrade node. Wanna jump on that new node v6.0.0? sudo n latest. Need to downgrade? Type n & select the version. It really couldn’t be easier.
ncu: Find newer versions of package dependencies
Upgrading packages in npm is still painful and awkward. Did a new major version drop? I don’t know, better manually check every single dependency or put greenkeeper on the job and feel bad about yourself when your repo has 30 outstanding PRs for various babel bugfixes. Or, you could roll them dice & accept any package greater than version x.y.z. The problem there is that even a patch (remember, major.minor.patch) can bork your build, and when that happens, you want to make sure you’re on the same version as the person reporting the bug.
Instead, I like to use node-check-updates (ncu). Just type ncu and see all the fresh versions available. If you want to update your package.json, just run ncu -a and you’re at the latest. Now you can keep your deps locked.
npm run watch + symlink
It’s pretty common that when you make a web app, you’ll piece out a big chunk into its own package, maybe even post it to npm, & develop the 2 concurrently. Doing this smoothly is another story. If you kept a copy in the same directory, you’d have to do a lot of copy & paste every time you wanted to update it on npm (plus if you deal with singletons or check for constructor equality, you’re gonna have a bad time). So, naturally you’ll want to keep it in its own directory & symlink it into your large project (npm link from your dependency and then npm link fooPackage from your project).
This works, but if you’re like me, you like your node_modules pre-transpiled in ES5 so your webpack builds are fast. So, you could make an exception in your webpack config (eg include: /fooPackage/), but you’ll want to be sure you remove that before you push a commit.
Alternatively, you can set up a babel watcher in your dependency. For example, in your package.json scripts, you might write:
"watch": "babel -w --presets es2015,stage-0 -d lib/ src/"
Now, every time you make a change to that dependency, it gets transpiled to Es5 automatically. The best part is that you don’t need to change a thing when it comes time to push or publish.
Speeding up webpack
There are a ton of performance improvements you can make to webpack, all well documented:
- PrefetchPlugin
- Disabling all optimization plugins (especially uglify!)
- Using DLLs for vendor packages
- devtool: ‘eval’
- include/exclude liberally for all resolvers
- babel-register#only to exclude build files
However, a new one I’m super excited about is happypack. Not only does it cache your previous builds, but it also uses multiple threads to create your new build. While I didn’t achieve the 400% gains showed in the readme, I did see solid 20–30% gains when running across 4 threads on my 2013 MBA. While not huge, that’s enough to keep me from getting bored, going to youtube, forgetting what I was doing, and then coming back 5 minutes later wondering what I was debugging. So those seconds saved turn into minutes saved real fast.
Closing remarks
So that’s my toolbox. What about yours? Is there some great tool or pattern you use to make builds faster or upgrades less painful? Go ahead & share it in the comments.