DEV Community

Cover image for 5 Node.js Tools to Learn in 2023
Camilo Reyes for AppSignal

Posted on • Originally published at blog.appsignal.com

5 Node.js Tools to Learn in 2023

The Node ecosystem comes with a wide variety of tools that have continued to evolve over the years. These tools are delivered via NPM packages and run in the command line, making them accessible to any developer (you do not need a fancy IDE to get the job done).

In this take, we will explore 5 Node tools to learn this year: TypeScript, ES modules, ESLint, the ESLint SpellCheck plugin, and Mocha. These all run via the command line and can help boost your productivity when working on Node projects.

Ready? Let’s go!

The Sample Code

If you want to get a head start, the sample code is a code kata with all the tools discussed in this article. It is an HTML5 game by Christian Clausen called bomb-guy that you can run in the browser. The emphasis will not be on the code itself but on the tools around the code solution.

Feel free to clone the repo — it is available on GitHub. The code is a fork from thedrlambda and has been refactored with all these tools.

Be sure to inspect the package.json file to get a sneak peek of all the cool tools available.

"devDependencies": {
  "@types/mocha": "^10.0.1",
  "@typescript-eslint/eslint-plugin": "^5.47.0",
  "eslint": "^8.30.0",
  "eslint-config-standard-with-typescript": "^24.0.0",
  "eslint-plugin-import": "^2.26.0",
  "eslint-plugin-n": "^15.6.0",
  "eslint-plugin-promise": "^6.1.1",
  "eslint-plugin-spellcheck": "^0.0.20",
  "http-server": "^14.1.1",
  "jsdom": "^20.0.3",
  "jsdom-global": "^3.0.2",
  "mocha": "^10.2.0",
  "ts-node": "^10.9.1",
  "typescript": "^4.9.4"
}
Enter fullscreen mode Exit fullscreen mode

Remember, these all run via the command line, so you do not need a fancy editor or IDE to use them. Simply do npm run build, npm test, or npm start to spin up all the dev tools. This is the typical dev flow for pretty much all Node projects.

We will discuss each tool as a reference guide, show you how to get started, and point out a few gotchas. The emphasis is on playing around with each tool and showing you how to use it.

Let’s start with TypeScript.

TypeScript for Your Node.js Project

I’m sure you’ve already heard this a lot, but if you haven’t tried TypeScript in a project, you really need to. TypeScript adds type safety to your projects and makes it easier to catch mistakes in the code. For this bomb-guy code kata, for example, it’s valuable to rely on the compiler when making a lot of changes.

To get started, be sure to create a package.json file if you don’t already have one via npm init. Then, add the TypeScript dependency.

> npm i typescript --save-dev
Enter fullscreen mode Exit fullscreen mode

At this point, it is possible to add the tsc command as a build script in package.json. If you have a bunch of existing JavaScript files, any file that gets renamed with a .ts extension becomes a TypeScript file, and the compiler does the rest of the work.

Most dev workflows require some tweaking of the compiler configuration. The way you do this is via the initializer.

> npx tsc --init
Enter fullscreen mode Exit fullscreen mode

This creates a tsconfig.json file with the default configuration. Each configuration is well documented within this file so that you can tailor the tool to your needs.

While you are in the configuration file, change the TypeScript configuration so we can talk about the next available tool.

"compilerOptions": {
  "module": "esnext",
  "target": "esnext"
}
Enter fullscreen mode Exit fullscreen mode

Now it is possible to declare strongly typed interfaces and classes.

As an example, let’s say we want to declare an interface every tile class must implement in this bomb-man game. The game is a 2-D style game with many different types of tiles.

interface Tile {
  isGameOver: () => boolean;
  draw: (g: CanvasRenderingContext2D, x: number, y: number) => void;
  move: (x: number, y: number) => void;
  update: (x: number, y: number) => void;
  placeBomb: () => void;
  explode: (x: number, y: number, fire: Tile) => void;
}
Enter fullscreen mode Exit fullscreen mode

Voilà! If you want more information about setting up TypeScript for your Node app, check out the post How to Set Up a Node.js Project with TypeScript.

Next up, let’s see what ES modules have to offer.

ES Modules in Node.js and the Browser

Both Node and the browser have achieved parity via export/import. This module system allows you to simply import code from different files and works natively without transpilers.

In Node, change the package.json file to a module.

"type": "module"
Enter fullscreen mode Exit fullscreen mode

This instructs Node to start using ES modules natively, without the TypeScript transpiler.

In the browser, go to index.html and change the script tag.

<script src="dist/src/index.js" type="module"></script>
Enter fullscreen mode Exit fullscreen mode

This achieves two things:

  • TypeScript does not nuke the export/import code
  • The browser can use this same module system to tackle dependencies

One gotcha here is that there is a bit of divergence between TypeScript and the browser. The spec says imported modules must declare a file extension, whereas TypeScript makes the resolution even without an extension like .js.

To tackle this issue, simply declare all dependencies as JavaScript files in your TypeScript code. The compiler is smart enough to know that you mean to declare the import as a JavaScript file.

import { TILE_SIZE, FPS, TPS } from "./constant.js"; // JavaScript file imported
Enter fullscreen mode Exit fullscreen mode

This technique works seamlessly in both Node and the browser.

ESLint with TypeScript for Your Node.js App

The linter tool ESLint statically analyzes code, supports most text editors, and can run in the command line. It adds code smell checks, checks for potential bugs, and even helps style code consistently. We recommend turning on all the features ESLint has to offer.

To get started, initialize the config package:

> npm init @eslint/config
Enter fullscreen mode Exit fullscreen mode

This CLI tool automatically guides you through a set of options where you can customize the configuration. Be sure to pick all three: check syntax, find problems, and enforce code style. Pick the standard, most popular style guide — ESM — as the module system and TypeScript.

The configuration file comes in three flavors: JavaScript, JSON, and YAML. Pick JavaScript because we need to tackle the next gotcha.

For ESLint to work with the TypeScript compiler, it needs parserOptions somewhere in the configuration file. Also, because we are using the ES module system in package.json, we must rename the configuration file to .eslintrc.cjs.

In .eslintrc.cjs be sure to set the parserOptions:

"parserOptions": {
  "project": ["tsconfig.json"],
  "tsconfigRootDir": __dirname, // JavaScript code
  "ecmaVersion": "latest"
}
Enter fullscreen mode Exit fullscreen mode

Note the use of __dirname — this allows the linter to find the tsconfig.json file from anywhere in the project folder structure. This technique is only achievable via the JavaScript configuration file.

Now lint a file in the src folder:

> npx eslint constant.ts
Enter fullscreen mode Exit fullscreen mode

There you have it! Next up is a handy ESLint plugin: SpellCheck.

ESLint Plugin — SpellCheck

ESLint is extensible via plugins. Because there is nothing less annoying than typos in code, let’s install the spellcheck plugin.

npm i eslint-plugin-spellcheck --save-dev
Enter fullscreen mode Exit fullscreen mode

To enable the spellchecker in ESLint, edit the .eslintrc.cjs file:

"plugins": ["spellcheck"],
"rules": {
  "spellcheck/spell-checker": [
    "warn", {
      "skipWords": ["rect", "keydown"]
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

This fires warnings in ESLint when it finds a spelling mistake. If you have valid words that are not found in the dictionary, just add them to the list in skipWords.

With ESLint, most caught issues trigger an error, and the build will fail until the issue is fixed. This makes the CLI tool ideal for both local development and continuous integration on a build server.

To enable these checks automatically, add ESLint to the prebuild script in package.json.

"scripts": {
  "prebuild": "eslint ."
}
Enter fullscreen mode Exit fullscreen mode

Finally, let’s take a look at Mocha.

Mocha for Testing in Node.js

If you have yet to practice test-driven development (TDD), now is your chance. Mocha integrates seamlessly with all the tools we have covered so far and can run hundreds of unit tests in less than a second.

To get started with Mocha, install the following dependencies:

npm i @types/mocha jsdom jsdom-global ts-node mocha --save-dev
Enter fullscreen mode Exit fullscreen mode

Note the use of ts-node and jsdom in the dependencies. The bomb-guy code kata runs in the browser, so jsdom allows mocking browser elements like the window object without a headless browser.

Because we are using TypeScript, ts-node is an execution engine that directly executes TypeScript on Node without precompiling. These two dependencies are useful for running unit tests in Mocha.

To enable these tools in Mocha, create a .mocharc.json file with the following configuration:

{
  "require": ["jsdom-global/register"],
  "loader": "ts-node/esm",
  "extensions": ["ts"],
  "spec": ["tests/**/*.test.ts"]
}
Enter fullscreen mode Exit fullscreen mode

This tells Mocha to enable three things: jsdom, ts-node with ES modules, and the TypeScript extensions. The spec settings specify where the tests go, and you can use a glob pattern.

Then, write the unit tests using TypeScript. Say we want to test that a player can move around the tiles and place a bomb.

it("move player", () => {
  player.moveRight();
  player.moveDown();
  player.moveDown();
  equal(2, player.x); // assertion library
});

it("place first bomb", () => {
  player.placeBomb();
  map.update();
  equal(1, player.bombs);
});
Enter fullscreen mode Exit fullscreen mode

Note that Mocha does not come with an assertion library.

Thankfully, Node comes with one built-in, so you do not have to add another dependency. If you are already familiar with Chai, the transition will feel seamless.

Lastly, be sure to include Mocha in package.json:

"scripts": {
  "test": "mocha"
}
Enter fullscreen mode Exit fullscreen mode

The .mocharc.json configuration file already tells Mocha how to run the tests. This technique keeps your package.json file clutter-free.

One gotcha is that Mocha does not support ESM in watch mode. Hopefully, this limitation will be tackled in future releases.

Keep in mind, the linter and compiler are separate from running unit tests in your continuous integration pipeline. The execution engine in ts-node is not a compiler and does not do any code checks. So a good technique is to run both ESLint and the TypeScript compiler first, then run unit tests last on the build server.

Wrapping Up

In this post, we explored 5 Node tools to learn this year: TypeScript, ES modules, ESLint, the ESLint SpellCheck plugin, and finally, Mocha for running tests.

These Node tools offer the possibility of tackling code changes without an IDE. The tools are accessible and do not shove specific IDEs or text editors on developers. They are easy to automate and can be included in continuous integration so an entire team can benefit.

Happy coding!

P.S. If you liked this post, subscribe to our JavaScript Sorcery list for a monthly deep dive into more magical JavaScript tips and tricks.

P.P.S. If you need an APM for your Node.js app, go and check out the AppSignal APM for Node.js.

Top comments (0)