Modules: ESM module load

Created on 22 Nov 2019  路  11Comments  路  Source: nodejs/modules

index.js

import {a} from './a'

console.log(a)

a.js

export const a = 3

Using Node.js 13.2 node index.js

(node:76399) ExperimentalWarning: The ESM module loader is experimental.
internal/modules/esm/default_resolve.js:94
  let url = moduleWrapResolve(specifier, parentURL);
            ^

Error: Cannot find module /Users/daniel/code/node-esm/a imported from /Users/daniel/code/node-esm/index.js
    at Loader.resolve [as _resolve] (internal/modules/esm/default_resolve.js:94:13)
    at Loader.resolve (internal/modules/esm/loader.js:74:33)
    at Loader.getModuleJob (internal/modules/esm/loader.js:148:40)
    at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:41:40)
    at link (internal/modules/esm/module_job.js:40:36) {
  code: 'ERR_MODULE_NOT_FOUND'
}

Most helpful comment

There is two downside in this

Typescript support

ts generate js code without the extension, so if I change ts output to "module": "esnext", it won't work.

Common FE writing

Also it's quite common to use without extension, like react or vue. I think this will bring much confusion.

All 11 comments

@gengjiawen file extension and directory resolution are no longer supported in the esm loader. If you put the full filename it will work

index.js

import {a} from './a.js'

console.log(a)

There are a number of reasons people on the Modules Team like this change including better performance and web compatibility.

There is support for the former algorithm with a flag --es-module-specifier-resolution=node.

There is still some discussion being had about the final behavior we'll land on with this.

I'm going to close this but please feel free to keep the conversation going.

There is two downside in this

Typescript support

ts generate js code without the extension, so if I change ts output to "module": "esnext", it won't work.

Common FE writing

Also it's quite common to use without extension, like react or vue. I think this will bring much confusion.

IMO, what we want to see in the future should take precedence over current practices. Less magic and less divergence from browsers are benefits of not doing this.

Referencing proposal that doesn't involve "magic" or --es-module-specifier-resolution=node and solves this issue: https://github.com/nodejs/modules/issues/444

ts generate js code without the extension

IIRC TS does work fine with the extension, it just doesn't add extensions not present in the source. The following should be accepted by tsc:

// a.ts
import b from './b.js';

// b.ts
export default 42;

TSC should be smart enough to figure out that you meant b.ts even though the import is using the target filename.

What I mean is generated code by tsc

image

Right, if you use the extension in your typescript, typescript will generate code that has the extension. :)

When using typescript, adding the extension only works if you're working with js files. You can't import from './a.ts'

@jcjolley -- in your typescript source, when importing another typescript file, use the .js extension, and it will work

that is, when importing b.ts, the code in a.ts should look like this:

import * as b from "b.js"

the import path reflects what ends up in the compiled output, not the path to the typescript source

the import path reflects what ends up in the compiled output, not the path to the typescript source

See https://github.com/microsoft/TypeScript/issues/35589#issuecomment-577035970 and the comments preceding it.

Was this page helpful?
0 / 5 - 0 ratings