Why We’re Dropping CommonJS from Our JavaScript Packages
Storyblok is the first headless CMS that works for developers & marketers alike.
Spotted a DeprecationWarning with the code STORYBLOK_CJS_DEPRECATED in your terminal? That means a CommonJS build of one of our JavaScript packages just loaded, and you probably want to know what’s going on. Here’s the short version: upcoming releases of our packages ship ESM only. For now, the warning is the only change, and the versions you run today keep working.
To be clear, this isn’t a case against CommonJS. Plenty of great software still runs on it.
What changes, and what doesn’t
Our packages follow semantic versioning (semver), so a removal like this arrives with a breaking release. For packages at 1.0 or above, that means a new major version. Several of our packages are still on 0.x, where semver allows breaking changes in a minor release, so we might drop CommonJS from those before they reach 1.0. We haven’t decided yet.
Here’s what that means for you:
- Every version that ships CommonJS today stays on npm and keeps working. Pin it, and
require()keeps working too. - The warning prints once per JavaScript realm (the main thread, each worker thread, and each isolated test environment) and changes nothing else.
require()returns the same exports as before. - The next major version of each package at 1.0 or above won’t contain a CommonJS build.
We haven’t announced a removal date. The table at the end lists the current version of each package.
Why ESM only
ECMAScript modules (ESM) are the module system of the JavaScript language itself. For a long time, the awkward part was that CommonJS code couldn’t load them synchronously, which is why so many packages published both formats. That’s no longer the case: since Node.js 20.19 and 22.12, require() can load an ES module without a flag, as long as the module graph has no top-level await. In other words, a CommonJS project can keep calling require() on an ESM-only package.
That removes the main argument for shipping two builds, and two builds cost us something on every release. Each one needs its own tests, and a bug can hide in one format while the other looks perfectly fine. We’ve run into exactly that before.
If you consume a dual package, the formats don’t map onto each other cleanly either. A CommonJS module can export a function or a primitive, which a namespace import can’t represent, and every tool works around that in its own way. The TypeScript handbook explains the problem in its ESM/CJS interoperability appendix, and Modules - Theory covers how the two systems differ.
In Move on to ESM-only (February 2025), Anthony Fu explains why he went from advocating dual publishing to advocating ESM only. He names the same costs: interop trouble, dependency resolution that has to pick the right format, and packages roughly twice the size. He also stresses that the right call depends on the project. For our SDKs, with require(esm) available on current Node.js releases, the scale tips toward ESM.
What you should do
If you write import, you probably don’t need to do anything. If you call require() on one of our packages, you have two options.
Move to import:
// before
const { storyblokInit } = require("@storyblok/js");
// after
import { storyblokInit } from "@storyblok/js"; Or stay on require(). Once the ESM-only releases ship, require() of an ESM-only package works on Node.js 20.19, 22.12, and later. Jest is the exception (refer to Test runners). One difference to know about: require() of an ES module returns the module namespace object, so named exports are properties of the returned object, and the package’s module graph must not use top-level await.
Whichever option you pick, a ^ range in your package.json keeps you on the current major, so you won’t get the ESM-only version by accident. For 0.x packages, a caret only covers patch releases of the same minor, so a minor bump can bring the change. Read the release notes before you bump.
Silence the warning while you migrate
Run Node.js with the --disable-warning flag. It works on Node.js 20.11, 21.3, and later; older versions refuse to start with it.
node --disable-warning=STORYBLOK_CJS_DEPRECATED app.js Or set STORYBLOK_SILENCE_CJS_DEPRECATION to any non-empty value. Even 0 and false count.
STORYBLOK_SILENCE_CJS_DEPRECATION=1 node app.js --throw-deprecation turns the warning into an uncaught error that ends the process on the next tick, and a try/catch around require() won’t catch it. If you run with that flag, use the environment variable instead.
Test runners
A test runner that loads your code through require() or a CommonJS transform can trigger the warning, even when your own code only uses import. Runners that isolate each test file print it once per file. To silence it, set STORYBLOK_SILENCE_CJS_DEPRECATION in your test script.
Jest in its default CommonJS mode needs more work once the ESM-only releases ship. In our tests, Jest 30.5 couldn’t load an ESM-only package from node_modules on Node.js 20.19 to 24.18 (“Must use import to load ES Module”). Jest’s docs say it supports require() of ES modules on Node.js 24.9 and later, but in our run, that worked only with NODE_OPTIONS=--experimental-vm-modules. Jest’s ECMAScript modules guide covers the options.
Vitest, which we use ourselves, loads dependencies from node_modules through Node.js, so import gets the ESM build and ESM-only packages load without extra setup. In our test with Vitest 5.1, that held for both import and require() on Node.js 22.12 to 26.13. A require() call, in your test or in a CommonJS dependency, still loads the CommonJS build and triggers the warning.
To find out where a CommonJS load comes from, trace the deprecation:
node --trace-deprecation --stack-trace-limit=50 app.js Latest versions with CommonJS support
These are the latest versions on npm as of November 3, 2026, and all of them ship a CommonJS build today. The removal comes with the next major version of each package at 1.0 or above, and possibly with a minor release for 0.x packages.
Package | Latest version with CommonJS |
|---|---|
| 0.1.1 |
| 0.10.0 |
| 1.2.2 |
| 6.4.1 |
| 0.8.0 |
| 0.11.0 |
| 0.4.2 |
| 7.4.0 |
| 1.6.0 |
| 5.4.0 |
| 0.6.0 |
| 11.4.0 |
| 7.8.1 |
Run into trouble with the warning or a migration? Let us know by opening an issue in the monoblok repository.






