A tiny guide to non fancy, high-value Node.js things. Because we're folks that want to build fun things, rather than spending time fighting our tools.
Node.js is a truly neat piece of software. It has one of the largest programming communities, and somehow both a very low barrier to entry and a high skill cap. Picking Node as the hammer in your programming toolbox is not a bad choice.
Node can be a little overwhelming though. Because of the low barrier to entry for both writing and publishing software, it can sometimes become hard to find exactly what you need. That's why this tiny guide exists: a little set of opinions to help guide you in the vast world of Node.
Obviously other people will have different opinions, and that's cool. This is what I've found to work for me, over the years. It's fine if we disagree. But there might be a chance you'll find this works for you too.
Disclaimer: If you disagree enough to get angry at this guide, I urge you to take a breath, step back and reconsider. Feel free to write your own guide; hell - having more perspectives and resources is a great thing! Remember that kindness matters
There's style, and there's
syntax. Generally discussions
about punctuation and other linting things are boring, so use
standard and worry about solving actual
problems instead. standard --fix
will even take care of formatting code for
you; it's been around for a while and generally gets the job done.
ES3 is generally all you need. Really? Yup, really. The Array methods in ES5
are nice, and template strings are useful - but that's it. var
is performant,
and flexible. callbacks
are the unifying interface for asynchronous
programming, and for-loops
are about as fast as you'll get. Using a tiny
subset of the language makes your code stable, readable and predictable.
Exactly the way we like it.
Don't bother with import
, it's
unstable. require()
has worked since the dawn of Node, and works reliably for any scenario you can
come up with. And no need to worry about "tree shaking" / "dead code
elimination" - unless you've got extremely complicated applications it won't
matter. At that
point you'll probably have much larger problems to worry about.
We don't need 13 different types of
functions.
Using function foo () {}
will cover all your bases. Yup, even arrow functions
aren't worth it - we aim for boring; and removing arguments
and this
from
arrow functions makes arrow functions weird and hard to debug.
Callbacks are your ticket. They're fast, easy to reason about and easy to debug. If you ever find yourself struggling with them, consider naming and splitting them. Other paradigms build on top of callbacks and will probably make things more complicated. For example by ignoring error handling in examples, swallowing errors all together or far worse. You want errors to be predictable.
Speaking of errors: use throw
to crash and burn your program (e.g. programmer
errors, for example a wrong type) and use callbacks for expected errors (e.g.
oops, wrong input - try again).
The feross/run-* family of packages is truly wonderful. They'll give you virtually all you need for working with callbacks efficiently. There's also map-limit which is my go-to hammer when needing to run an array of things, in series, parallel or something in between.
If you ever need composable async
in Node, consider using streams. The
streams2
API isn't pretty, but it's worth learning. Streams can be passed
around synchronously and will send data from one place to another. They're
ideal for creating composable, reusable APIs. Check out
mississippi on GitHub to learn more
about good streams packages.
The Test Anything Protocol (TAP) has existed for years, and works in almost every language. tape is the way to use it in Node. Don't worry about fancy (Promise based) parallel test runners; if they provide any measurable performance improvement then your code is probably too complicated in the first place. Instead consider removing all IO from your tests for example.
If you want pretty printing for TAP
, use
tap. If you want code coverage reporting,
use nyc.
Use dependency-check to make sure you didn't miss any deps. greenkeeper is neat if you maintain applications.
Grab bag packages often lead to code creep; don't use 'em. If there's 60 functions exposed in any given package, chances are that given enough time the code base will asymptotically start using a higher percentage of these functions. And that's not good; there's a thing as being too dependent on external code.
level is the only database. Use membdb when testing and developing. Use subleveldown to split your database. Check out the wiki for more modules; there's one for virtually anything you could need (replication, caching, LRU, etc.)
I'm not a fan of other databases as they're usually peer dependencies. If you're building something, you probably want to optimize for iteration - not so much other things. And level excels at that. Unless you're building a bank; I wouldn't trust myself to build a boring money transaction system in Node. Take advice from other people if you're planning to do stuff like that.
Use lil-pids for process management
and taco-nginx to expose processes
to the outside world. scp(1)
or npm
are generally enough to deploy your
stuff with. Use npm install / npm start
for your apps to be predictable. You
probably don't need Docker
- remember that Node is a cross platform virtual
machine already; if you get started Node is probably all you need. You can
always get fancy later.
You probably don't need high performance distributed systems stuff when writing applications. Ask yourself: do you really need to run this on more than one machine? This is some of the stuff we're working on during my day job though; often it just turns a problem into a distributed problem.
If you do need to run something on multiple machines though (e.g. live video streaming!) consider using hypercore (distributed streams) or hyperdrive (distributed filesystem). They're neat, secure modules that make writing distributed system stuff relatively painless.
I've recently been working on merry which uses streams, fast logging and has loads of conventions. It's all of my opinions around API design turned to code.
It's generally a good idea to validate assumptions you make. This helps catch
mistakes early and makes fixing them easier later on. I like using Node's
built-in assert()
package for this. Got an input type you want to validate?
Assert it. Expect certain config values to exist? Assert it. Because I use it
in all my packages, having an extra compile check for static types doesn't make
sense for me. When deploying production code
unassertify removes the extra
checks.
When building APIs json-schema is a great way to validate assumptions made about incoming JSON. When building custom wire protocols protocol-buffers and similar are great.
I've recently been working on choo which uses pure HTML, JS and has a clean architecture. It's all of my opinions around frontend applications turned to code.
To serve frontend code I use bankai.
It's based on browserify which
is a super stable tool to build frontend stuff. Boring and stable is the name
of the game. budo is similar to bankai
,
maybe you'll like it too.
For css there's sheetify and
tachyons. sheetify
allows you to require css from
node_modules
. It's built right into bankai
so it's easy to work with.
tachyons
is a sane CSS system. It might feel awkward at first, but once you
get past the bump you'll be building maintainable websites faster than ever
before.
We're currently working on easy to setup account stuff through township but it's still a work in progress. If there was anything that scratched our itches already we'd be using it.
electron is cool. I've never built a mobile app, so I can't comment on that - probably building a website would be where I'd start though.
Yup, and that's it. These are my boring tools for writing software. Obviously there's much more tools to be discovered, but npm should be your friend. I hope this little guide can at least help you out a little when getting started in the wonderous world of Node.
PS. The fancy name for the tech described in this guide is The Lebron Stack. We don't kid. Happy coding!