October 27, 2019 • ☕️☕️☕️ 13 min read
Node.js runtime brings so much capability to web development; we need process managers to manage Node.js servers in both development and production, or debuggers to fix bugs.
Each tool can belong to multiple categories, I’ll put it where it is famous for. These tools are evolving very fast, you better check official documents before using to minimize duplication and complexity in your development workflow.
Static type checking, the process of checking type safety based on source code at compile-time, has several awesome benefits like caching errors early, limiting type errors, supporting auto-completion, generating documentation, and resulting in faster compilation.
TypeScript is getting more and more popular when many companies and open source projects are migrating into it.
Linters are tools that analyze source code to detect problems based on formatting and code quality rules then output as warnings or errors. They are used to increase code quality, configured manually, and often run automatically when code changes.
The three most popular JS linters are ESLint, JSHint and JSLint, they provide online GUI to test some code, they also all offer plugins for text editors like Sublime Text, VS Code, and Atom.
ESLint is an extremely configurable linter that also supports JSX and can auto format scripts to match your preferred code formatting style, too much customization makes it harder to just pick up and start using.
JSHint comes loaded with sensible defaults but allows for a lot more configuration than JSLint, provides the perfect blend of ease and functionality.
Code formatters are tools to format the codebase automatically based on formatting rules to enforce a consistent coding style. They can behave like linters in term of formatting rules, but can not do anything to help with code quality rules. They can also be integrated into workflows with linters to do both formating and linting in one step.
Packages are pieces of code that you can share and reuse like basic components, libraries or frameworks. These packages are versioned and installed based on semantic versioning, your applications can use these packages as dependencies, and each package may or may not depend on other packages.
Package managers are tools that help you manage packages as dependencies and might also provide a global package registry. They work based on manifest files that keep track application metadata and needed dependencies, lock files to offer deterministic installs.
In the Node ecosystem, dependencies get placed within a
node_modules directory in your project. The install process starts with resolving dependencies by making requests to the registry and recursively looking up each dependency, then fetching the package tarballs if needed, and finally linking everything together.
bower.json and puts installed packages in
bower_components folder. It was created at the time npm only supported node packages, now fading away when both npm and yarn can support both node and browser packages with little help from module bundlers like Webpack or Browserify.
There are many repetitive tasks, sometimes also mundane, painful, or time-consuming, need to be automated like concatenating files, minification, compilation, unit testing, linting, etc.
Task runners are tools to orchestrate those kinds of tasks in an efficient way, the workflow made easy with the ecosystem of plugins to automate all kinds of tasks you can imagine, the speed can be optimized behind the scene to leverage multi-threads, and can be used as standalone or integrated into a more complicated pipeline.
Grunt and Gulp are two generic task runners with huge plugins ecosystem; other less capable alternatives are Broccoli.js and Brunch. If you think the above task runners are overkill, you can make other tools like bash scripts, npm scripts or webpack to behave like task runners with trade-offs of implementing many tasks yourself.
Module bundlers can be considered as limited task runners and built tools as well, like focusing on automating frontend tasks and generate a website only.
Parcel is a zero-configuration module bundler, only used for web applications, has support for many common transforms and transpilers built-in out of the box.
Browserify is a tool for bundling Node packages for the browser, happens to work for browser-based apps pretending to be Node packages.
Build tools are tools that can generate production build artifacts - web apps, server-only apps, libraries - through an automated process including multiple tasks like compiling, packaging, testing, linking, etc.
Backpack is a minimalistic build tool, lets you create modern Node.js apps and services with zero configuration; handles all the file-watching, live-reloading, transpiling, and bundling, so you don’t have to.
Debuggers are tools that allow you to inspect running code in Node.js, in browser, or both; They often support pausing execution, stepping through function calls manually, inspecting variables, profiling memory allocations, and CPU usage, viewing execution logs, etc.
node-inspector is a Node.js debugger based on Blink Developer Tools, already deprecated because Node.js already provides a built-in DevTools-based debugger.
Module loaders are libraries that can handle loading modules using the above formats for further processing or executing, they may be different in terms of synchronous or asynchronous loading, static or dynamic loading.
ES Module Loader has been implemented in most browsers, available in Node.js via
Node process managers are tools to manage your Node applications at run time; they provide high availability, automatic restart, file watcher, runtime performance and resource consumption insights, and clustering.
Forever is a simple command-line interface tool to ensure that a script runs continuously forever, simple interface makes it ideal for running smaller deployments of Node.js apps and scripts.
PM2 is a production process manager for Node.js applications that has a built-in load balancer, enables you to keep applications alive forever, reloads them without downtime, helps you to manage application logging, monitoring, and clustering.
StrongLoop Process Manager (Strong-PM) is a production process manager for Node.js applications with built-in load balancing, monitoring, and multi-host deployment. Includes a CLI to build, package, and deploy Node.js applications to a local or remote system.
SystemD is the default process manager on modern Linux distributions, which makes it simple to run a Node application as a service.
Scaffolding tools allow you to generate projects automatically, also help with upgrading an existing project that has already been generated with the tool, keep it up to date with new best practices, enforce standards, allow for rapidly getting started on new projects and streamlines the maintenance of existing projects.
Yeoman is a generic scaffolding system, language-agnostic, allows the creation of any kind of app in any language, every decision is made by generators which are basically plugins in the Yeoman environment, can be integrated seamlessly with build-tools and package managers to streamline your workflows.
Monorepo is an architecture of organizing source codes of multiple applications, services, and libraries into a single repository.
Lerna is a tool that optimizes the workflow around managing multi-package repositories with git and npm/yarn, link any cross-dependencies, shares common dependencies across packages, share common commands across packages.
Yarn workspaces allows you to setup multiple packages in such a way that you only need to run yarn install once to install all of them in a single pass.
These tools could have started in one category and then expanding into multiple categories, the boundary is sometimes very blurred. Emerging technologies approach the problem from different angles, sometimes they build on top of other tools, and at times they can be used together.
There is no right or wrong silver bullet solution. The combination of tools you use can be completely up to you depending on how much effort you can put into configuring and setting up. You can achieve the same results with different tools and settings.
It’s best for beginners to use starter projects with recommended configurations especially in production builds. Configuring a production-ready build system requires a steep learning curve, very time consuming, and best suited for experienced developers.
Start small, keep the system simple, expand gradually, and stop when you’re happy.