Improved error messaging for require(ESM) in Node.js

The Eleventy code-base is now written using ESM.
However, Eleventy projects can be written using CommonJS or ESM (and we’ll continue to support both moving forward).
As Eleventy is a command line tool, this offers a bit of wiggle room navigating the Co…


This content originally appeared on Zach Leatherman and was authored by Zach Leatherman

The Eleventy code-base is now written using ESM.

However, Eleventy projects can be written using CommonJS or ESM (and we’ll continue to support both moving forward).

As Eleventy is a command line tool, this offers a bit of wiggle room navigating the CommonJS/ESM divide. That is, until we started bundling application plugins in the core library.

Consider this application configuration file, making use of Eleventy’s Render Plugin.

const { EleventyRenderPlugin } = require("@11ty/eleventy");

If you try to import an ESM package in CommonJS, you’ll receive a pretty helpful error message:

require() of ES Module ./node_modules/@11ty/eleventy/src/Eleventy.js from ./eleventy.config.js not supported. Instead change the require of Eleventy.js in ./eleventy.config.js to a dynamic import() which is available in all CommonJS modules.

This error message is decent! But I think we can do better, and doing better will mean that folks will have an easier time upgrading to Eleventy v3. In order to add my own custom error messaging, I used the Conditional Exports feature (the exports property in package.json):

{
	"type": "module",
	"main": "./Eleventy.js",
	"exports": {
		"import": "./Eleventy.js",
		"require": "./EleventyCommonJs.cjs"
	}
}

ESM code using import will receive Eleventy.js and CommonJS code using require will receive EleventyCommonJS.cjs.

Conditional Exports are typically used for dual publishing packages. When folks dual publish their packages it often involves additional tooling complexity to convert the code from its format as-written to ESM (or CommonJS). Additionally, that complexity would only be a temporary win: Node.js is adding first-party support for require(ESM) in the future (yay!).

I do want to use this feature to provide a better error message!

Inside of ./EleventyCommonJs.cjs, it looks something like this:

try {
	// Eleventy.js is ESM so this throws if require(ESM) is not supported.
	module.exports = require("./Eleventy.js");
} catch(e) {
	throw new Error("Your custom error message here");
}

Notably, the above is only necessary because I wanted a custom error message. If you’re fine with Node’s provided error message, don’t do any of this.

This feature-tested approach allows a custom error message limited to folks using CommonJS and will automatically go away when used with Node’s new --experimental-require-module flag (or when Node opts into this behavior by default in a future version).

Here’s the helpful error message this approach unlocked in Eleventy and should help folks making the upgrade:

Eleventy cannot be loaded via require("@11ty/eleventy") in 3.0 and newer. Instead, you have a few options:

  1. (Easiest) Change the require to use a dynamic import inside of an asynchronous CommonJS configuration callback, for example:
  module.exports = async function {
    const {EleventyRenderPlugin} = await import("@11ty/eleventy");
  }
  1. (Easier) Update the JavaScript syntax in your configuration file from CommonJS to ESM (change require to use import and rename the file to have an .mjs file extension).
  2. (More work) Change your project to use ESM-first by adding "type": "module" to your package.json. Any .js will need to be ported to use ESM syntax (or renamed to .cjs.)
  3. (Short term workaround) Use the --experimental-require-module flag to enable this behavior. Read more: https://nodejs.org/api/modules.html#loading-ecmascript-modules-using-require It is possible that the newest version of Node has this enabled by default—you can try upgrading your version of Node.js.


This content originally appeared on Zach Leatherman and was authored by Zach Leatherman


Print Share Comment Cite Upload Translate Updates
APA

Zach Leatherman | Sciencx (2024-07-24T00:00:00+00:00) Improved error messaging for require(ESM) in Node.js. Retrieved from https://www.scien.cx/2024/07/24/improved-error-messaging-for-requireesm-in-node-js/

MLA
" » Improved error messaging for require(ESM) in Node.js." Zach Leatherman | Sciencx - Wednesday July 24, 2024, https://www.scien.cx/2024/07/24/improved-error-messaging-for-requireesm-in-node-js/
HARVARD
Zach Leatherman | Sciencx Wednesday July 24, 2024 » Improved error messaging for require(ESM) in Node.js., viewed ,<https://www.scien.cx/2024/07/24/improved-error-messaging-for-requireesm-in-node-js/>
VANCOUVER
Zach Leatherman | Sciencx - » Improved error messaging for require(ESM) in Node.js. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2024/07/24/improved-error-messaging-for-requireesm-in-node-js/
CHICAGO
" » Improved error messaging for require(ESM) in Node.js." Zach Leatherman | Sciencx - Accessed . https://www.scien.cx/2024/07/24/improved-error-messaging-for-requireesm-in-node-js/
IEEE
" » Improved error messaging for require(ESM) in Node.js." Zach Leatherman | Sciencx [Online]. Available: https://www.scien.cx/2024/07/24/improved-error-messaging-for-requireesm-in-node-js/. [Accessed: ]
rf:citation
» Improved error messaging for require(ESM) in Node.js | Zach Leatherman | Sciencx | https://www.scien.cx/2024/07/24/improved-error-messaging-for-requireesm-in-node-js/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.