Skip to content

Improve ESM support through CommonJS #50

Closed
@bogeychan

Description

@bogeychan

At the moment it is not possible to import CommonJS into ESM because the exports defined in package.json (of all projects) are sorted incorrectly.


Example: (run with node main.js)

// main.js
import Elysia from 'elysia';

new Elysia.Elysia();

Error: (yes, i've "type": "module" in my package.json)

SyntaxError: Cannot use import statement outside a module

The sorting is important. Node.js & Deno apparently check from top to bottom. This means that if it is ESM-context, import is used instead of require or node.

Therefore node must move further up and point to CommonJS (in all exports):

{
  "bun": "./dist/index.js",
+ "node": "./dist/cjs/index.js"
  "require": "./dist/cjs/index.js",
  "import": "./dist/index.js",
  "default": "./dist/index.js",
- "node": "./dist/index.js"
}

Furthermore, type or runtime errors occur when CommonJS is imported into ESM, because SWC breaks named exports for ESM in CommonJS build (i.e. module.exports):

❌ SWC

(function (e, t) {
  for (var r in t) Object.defineProperty(e, r, { enumerable: !0, get: t[r] });
})(exports, {
  Elysia: function () {
    return h;
  },
  default: function () {
    return u;
  }
});

Runtime Error

import { Elysia } from 'elysia';
         ^^^^^^
SyntaxError: Named export 'Elysia' not found. The requested module 'elysia' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from 'elysia';
const { Elysia } = pkg;

OR Type error

import Elysia from 'elysia';

const app = new Elysia.Elysia() // Property 'Elysia' does not exist on type 'typeof Elysia'.ts(2339)

✅TSC (without SWC)

exports.Elysia = Elysia;
exports.default = Elysia;

I can make (or help you with) the changes to exports in all package.json, but I don't know how you wanna handle SWC.

An alternative would be to drop CommonJS and only support ESM → "moduleResolution": "nodenext" & "type": "module" (i.e. specify all imports and exports with .js extension). This would work for Node.js and Deno too.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions