question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Concerning ES Modules: `node --experimental-modules` cannot load `iter-tools/es2018/index.mjs` due to import URLs lacking .mjs extension

See original GitHub issue

iter-tools provides *.mjs files alongside *.js files as an ES module alternative. However, Node.js cannot load it due to import URLs lacking extension, which is required for ES modules.

Take this example repo:

  • If you run npm run import-iter-tools-and-print-it, it will emit an error.
  • However, if you run npm run import-tsfun-and-print-it, it will succeed. (@tsfun/* are packages that I made which support both CommonJS modules and ES modules)

I also doubt that bundlers (such as parcel, webpack) are going to prioritize loading *.mjs first.

Proposal

Use @make-mjs/main to convert *.mjs files that import URLs without extension to *.mjs files that import URLs with proper suffixes (either .mjs, /index.mjs or others depend on importing targets).

Example Code:

import main, { EventType } from '@make-mjs/main'
import path from 'path'

// main() returns an async iterator
const events = main({
  dirname: 'src',
  getNewPath: filename => path.join('dist/es2018', path.basename(filename)),
  /* more options */
})

for await (const event of events) {
  if (event.type === EventType.BeforeWrite) {
    console.log('Making', event.file.path)
  }

  if (event.type === EventType.AfterWrite) {
    console.log('Made', event.file.path)
  }
}

How does @make-mjs/* work?

It uses @babel/parser to convert a file into AST, then find import/export URLs within that AST and correct it, and then uses @babel/generator to create output code.

Be aware

  • I just completed that package yesterday, feature is lacking (enough for my use case).
  • I did not have iter-tools in mind when I created @make-mjs/*. I only made it for my own packages (such as @tsfun/*). As such, it won’t adapt to iter-tools’s need unless developers of iter-tools submit pull requests to it.
  • I am lazy, and I am busy with other things, so while feature requests is welcomed, pull requests is more welcomed.
  • Tests are barely enough: While I am confident that my package works when all tests passed, when they fail, I am not sure if I know where it went wrong. For this reason, pull requests that add tests are most welcomed.
  • May not work properly on Windows: It is because the difference between URL separator (always be /) and filesystem path separator (/ on POSIX and \ on Windows), combined with the fact that I do not use Windows. If someone can ensure it works on Windows, I will gladly accept pull requests.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:20 (10 by maintainers)

github_iconTop GitHub Comments

1reaction
conartist6commented, Sep 18, 2019

Ah, right. OK. I’ll do a similar setup iter-tools then, though I think I’ll just write a babel plugin if I end up needing to, since I’m using babel already.

0reactions
KSXGitHubcommented, Sep 19, 2019

I’m glad you agreed. Few things:

  1. Don’t add "type": "module": It breaks CommonJS modules.
  2. If you can, choose/make production dependencies that supports .mjs, append /index.mjs (or other module entry) to import URLs that point to them (this is why @make-mjs is not so simple).
  3. Every .mjs file needs its own TypeScript definition. Copy every *.d.ts to *.mjs.d.ts.
Read more comments on GitHub >

github_iconTop Results From Across the Web

Support ES modules with .js extension and package type ...
mjs files, but I can't see any information on how to use ES modules with "type": "module" in package.json. Unfortunately, TypeScript cannot emit ......
Read more >
Unable to load .mjs file and run tests with Mocha
0 with flag --experimental-modules and v.10.0.0 without flag. I am using node v.14.15.4. The import statement that I have in my code to...
Read more >
ECMAScript modules | Node.js v19.3.0 Documentation
Modules are defined using a variety of import and export statements. The following example of an ES module exports a function: // addTwo.mjs...
Read more >
Using ES modules in Node.js - LogRocket Blog
To be able to load an ES module, we need to set “type”: “module” in this file or, as an alternative, we can...
Read more >
How to use MJS files in Node.js? - DEV Community ‍ ‍
Let me show you how to do it. 1. Create a ES Module / MJS File. Setting up an ES module is simple:...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found