Skip to content

Dealing with ESM requirement for import assertions JSON imports #2900

@acolytec3

Description

@acolytec3

On our new:tm: ESM builds, we proudly proclaim we are "fully browser compatible", which may well be true, but I suspect it will break as soon as you try to load one of our modules in browser that also imports JSON.. The issue is that if you try to import the ESM build (at least in NodeJS) without a bundler step that either intentionally or magically handles the import assertion requirement, you get unfriendly errors like this:

TypeError [ERR_IMPORT_ASSERTION_TYPE_MISSING]: Module "file:///home/jim/development/ultralight/node_modules/@ethereumjs/common/dist/esm/chains/goerli.json" needs an import assertion of type "json"
    at new NodeError (node:internal/errors:387:5)
    at validateAssertions (node:internal/modules/esm/assert:82:15)
    at defaultLoad (node:internal/modules/esm/load:84:3)
    at nextLoad (node:internal/modules/esm/loader:173:28)
    at /home/jim/development/ultralight/node_modules/ts-node/src/esm.ts:255:45
    at async addShortCircuitFlag (/home/jim/development/ultralight/node_modules/ts-node/src/esm.ts:409:15)
    at async nextLoad (node:internal/modules/esm/loader:173:22)
    at async ESMLoader.load (node:internal/modules/esm/loader:616:20)
    at async ESMLoader.moduleProvider (node:internal/modules/esm/loader:472:11) {
  code: 'ERR_IMPORT_ASSERTION_TYPE_MISSING'

So, we need to make sure our JSON imports look something like this in the ESM output of our code:

import * as goerli from './chains/goerli.json' assert {type: "json"};
import * as mainnet from './chains/mainnet.json' assert {type: "json"};
import * as sepolia from './chains/sepolia.json' assert {type: "json"};

Vite seems to do this magically for our our browser examples but ideally we add some sort of code transform that would be applied by a bundler (either rollup or ts-patch or webpack or whatever).

One additional note: we can't just add these into our sources or Typescript complains about them not being allowed unless we change the module setting in our tsconfig from Node16 to NodeNext (which in turn will open a bunch of other challenges I haven't fully explored.

One simple hack that works for the Ultralight build process is to use this sed command from whatever project directory root where you have imported the @ethereumjs modules in your node_modules directory.

sed -i '/from \S\+\.json'\''/ s/;//;/from \S\+\.json/ s/.*/& assert {type: \"json\"};/' node_modules/@ethereumjs/**/dist/esm/**/*.js

Unfortunately, this also is brittle and probably not an ideal solution for our build process (proved problematic when run repeatedly because my regex would not recognize that the type assertion had already been added on previous builds).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions