I am writing a JavaScript library that I would like to be importable via script tag, ES6 imports, and traditional (Node) requires, with or without TypeScript or any build systems. I am finding this all bafflingly difficult.
In my package.json file, I have defined the following exports (simplifying to only relevant exports):
"exports": {
".": {
"require": "./dist/slim.copper.cjs",
"import": "./dist/slim.copper.js",
"types": "./dist/typed.copper.d.ts"
},
}
In a test TypeScript project, I import my library like this: import Copper from "@jwrunge/copper";
Type hints and intellisense work great, and I can compile the code to JavaScript without error. However, when I run the JS code with Node, I get this error:
C:UsersjrungeDocumentsCODEcopper_testsrcindex.js:3
var copper_1 = require("@jwrunge/copper");
^
Instead change the require of slim.copper.js in C:UsersjrungeDocumentsCODEcopper_testsrcindex.js to a dynamic import() which is available in all CommonJS modules.
at Object.<anonymous> (C:UsersjrungeDocumentsCODEcopper_testsrcindex.js:3:16) {
code: 'ERR_REQUIRE_ESM'
}
The JavaScript output from TypeScript is still appropriately typed, but interestingly uses require:
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var copper_1 = require("@jwrunge/copper");
var store1 = copper_1.default.store("foo", { value: 12 });
Interestingly, when I console.log
copper_1
in the JS output and comment out all other code, I get this:
{
store: [Function: store],
ustore: [Function: ustore],
getFunc: [Function: getFunc],
addFuncs: [Function: addFuncs],
config: [Function: config]
}
where default
does not exist on the imported copper_1
and instead appears to be a direct import of the .cjs
file (as I would expect from the use of require
).
- Is that what’s happening? The JS output is using the .cjs version of the library, which does not (like the .js version) have an
export
property? - What is a graceful / standard way of working around this while still allowing for
require
imports? I would settle for simple instructions for my users, but would prefer something I can do to better prepare for their use cases.
Not supporting require
and providing only the es (.js) module files, I get this (the result of trying to require
an ES module):
Error [ERR_REQUIRE_ESM]: require() of ES Module C:UsersjrungeDocumentsCODEpubsubdistslim.copper.js from C:UsersjrungeDocumentsCODEcopper_testsrcindex.js not supported.
Instead change the require of slim.copper.js in C:UsersjrungeDocumentsCODEcopper_testsrcindex.js to a dynamic import() which is available in all CommonJS modules.
at Object.<anonymous> (C:UsersjrungeDocumentsCODEcopper_testsrcindex.js:3:16) {
code: 'ERR_REQUIRE_ESM'
}