Skip to content

🛠️ Tooling: Switch from CJS to ESM #435

Description

@JoshuaKGoldberg

Overview

Splitting out from #423 / #422 -> #434: this repo right now is on the default legacy Node.js module system of CommonJS (CJS). The ecosystem as a whole is gradually moving to the more modern ECMAScript Modules (ESM). Roughly copying context from #402 (comment), there are two "module" systems (syntax) we can use for importing & exporting between files:

  • CommonJS ("CJS"): an old Node.js-specific syntax that's always been available in Node.js
    • Exporting: module.exports.key = value;
    • Importing: const { key } = require("./file");
  • ECMAScript Modules ("ESM"): a new JavaScript standard that's only become widely supported in the last few years
    • Exporting: export const key = value;
    • Importing: import { key } from "./file.js";

ESM is generally a better syntax for a bunch of technical points. But for legacy reasons Node.js defaults to interpreting .js files as CJS. Node.js can be told to change that in two ways:

  • Broad: in a package.json, setting "type": "module switches the default to ESM
  • Per-file: using an explicit .cjs or .mjs extension for a file switches the file to CJS or ESM, respectively

#402 used the per-file strategy for eslint.config.mjs. But it'd be nice to switch to ESM broadly. Proposal: shall we do this in a dedicated PR?

Additional Notes

I personally tend to do migrations like this manually as a way to ramp up on codebases. But https://nodejs.org/en/learn/getting-started/userland-migrations also exists to help out.

A really cool deep dive on require(esm) from a major Node.js contributor: https://joyeecheung.github.io/blog/2024/03/18/require-esm-in-node-js (this refers to the ability for CJS modules to require() ESM modules, which used to not be allowed).

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions