I've heard that when importing ES modules, you're supposed to include a file extension. However, I came across some Node projects that import ES modules without an extension, like in this example.
I'm wondering how they do that.
I've heard that when importing ES modules, you're supposed to include a file extension. However, I came across some Node projects that import ES modules without an extension, like in this example.
I'm wondering how they do that.
Share Improve this question asked Nov 2, 2023 at 1:54 yuanzui_cfyuanzui_cf 1331 gold badge1 silver badge7 bronze badges 2- 1 Hi yuanzui_cf, wele to Stackoverflow :). One reason your question may have been downvoted is that you did not follow the "How do I ask a good question" guide on Stackoverflow. For example, the "Search, and Research" section. Providing references to similar questions or any relevant documentation you find online is a good start. I've answered your question below, although I remend following the guidelines for future questions. Hope it helps :). – nktnet Commented Nov 2, 2023 at 5:30
- 1 There's some good answers here, but from a strictly practical point of view I would strongly suggest that the extension is needed. While it might be possible to configure all the tools to not require it, things will work with fewer problems if you don't. – Evert Commented Nov 2, 2023 at 5:32
1 Answer
Reset to default 13Regarding your statement
I've heard that when importing ES modules, you're supposed to include a file extension
Yes, this is covered in the documentation for NodeJS ESM, under import-specifiers:
Relative specifiers like './startup.js' or '../config.mjs'. They refer to a path relative to the location of the importing file. The file extension is always necessary for these.
and under the Mandatory File Extensions section:
A file extension must be provided when using the import keyword to resolve relative or absolute specifiers. Directory indexes (e.g. './startup/index.js') must also be fully specified.
This behaviour matches how import behaves in browser environments, assuming a typically configured server.
As for your next statement,
However, I came across some Node projects that import ES modules without an extension, like in this example.
The example you linked is for a TypeScript project, not a regular ESM JavaScript/NodeJS project.
Looking at lines 4 and 5 of the project's tsconfig.json, we can see that there is
"module": "CommonJS",
"moduleResolution": "Node",
A good place to start is TypeScript's documentation on Module Resolution. which explains how the extensions can be omitted.
For example, under the description for "node10" (which aliases to node for backwards patibility), the following is stated:
It supports looking up packages from node_modules, loading directory index.js files, and omitting .js extensions in relative module specifiers.
and again in the Module - References: Extensionless Relative Paths section, we see that:
In some cases, the runtime or bundler allows omitting a .js file extension from a relative path. TypeScript supports this behavior where the moduleResolution setting and the context indicate that the runtime or bundler supports it:
// @Filename: a.ts export {}; // @Filename: b.ts import {} from "./a";
If TypeScript determines that the runtime will perform a lookup for ./a.js given the module specifier "./a", then ./a.js will undergo extension substitution, and resolve to the file a.ts in this example.
Hope this helps :).