Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: Invalid ESM build #152

Closed
martines3000 opened this issue Oct 4, 2023 · 13 comments · Fixed by #175
Closed

bug: Invalid ESM build #152

martines3000 opened this issue Oct 4, 2023 · 13 comments · Fixed by #175

Comments

@martines3000
Copy link

The ESM build of the library should use the .js file extension for relative imports, else it is not a valid ES module.

Reference: https://nodejs.org/api/esm.html#mandatory-file-extensions

This also causes issues (MODULE_NOT_FOUND) with tools that support ESM (like Vitest).

Adding file extensions to relative imports should also cause no issues with the CJS build of the package.

@Mrtenz
Copy link
Member

Mrtenz commented Oct 8, 2023

Interesting. Does this apply to imports from folders as well? For example with a folder structure like this:

src/
├─ foo/
│  ├─ index.ts
├─ index.ts

Is src/index.ts able to import ./foo (referencing src/foo/index.ts), or does it have to import ./foo/index.js?

@martines3000
Copy link
Author

martines3000 commented Oct 8, 2023

Maybe you can achieve the src/foo/index.ts import with this: tsconfig paths.
Also, you need to write the imports using the .js file extension, even though you are using typescript.

It is a little bit confusing at first, but I think this gives a solid explanation (a little bit long 🙂)

@Mrtenz
Copy link
Member

Mrtenz commented Oct 8, 2023

Maybe you can achieve the src/foo/index.ts import with this: tsconfig paths. Also, you need to write the imports using the .js file extension, even though you are using typescript.

It is a little bit confusing at first, but I think this gives a solid explanation (a little bit long 🙂)

Much appreciated! It seems like hybrid CJS/ES builds are more complicated than I thought. Will look more into this next week.

@martines3000
Copy link
Author

martines3000 commented Oct 8, 2023

Here is some extra information, maybe it will be of some help:

  • If you need some reference implementation, I tested the fixes in this repo here: fork.
  • Adding .js to relative imports produces a correct output, but the solution is not that simple. The same issue is also present in the @metamask/utils dependency.
  • If you set module resolution to nodenext example, it will show you some more problems.
  • If you want eslint to show errors for missing .js file extensions you need to set module resolution to nodenext and set the type in package.json to module. I am not sure how this impacts the CJS build though.

Thank you for looking into it! 🚀

@Mrtenz
Copy link
Member

Mrtenz commented Oct 9, 2023

There is a fix for this in the @metamask/utils repository (MetaMask/utils#144). When that is merged I will apply the same fix to key-tree.

@martines3000
Copy link
Author

Thank you for looking into it so fast. I like the solution you chose, it didn't require any actual code change, only replacing the build tool and bundling everything as 1 file. Smart 👍.

@martines3000
Copy link
Author

Does bundling everything as 1 file impact tree-shaking? I'm not worried about the bundle size here, just curious if you maybe know or thought about that.

@Mrtenz
Copy link
Member

Mrtenz commented Oct 9, 2023

I like the solution you chose, it didn't require any actual code change, only replacing the build tool and bundling everything as 1 file. Smart 👍.

Thanks! I definitely wanted to avoid having to change every import, update linting rules, and so on. I couldn't find a good way with TSC or SWC to add extensions to the imports at build time, and tsup seems to do just what we need out-of-the-box.

Does bundling everything as 1 file impact tree-shaking? I'm not worried about the bundle size here, just curious if you maybe know or thought about that.

I don't think it makes any difference (but don't quote me on that). Currently, the entire bundle is imported regardless (through the root index.js). And most bundlers, like Webpack and Rollup, are pretty good at tree-shaking ESM code (not so much at tree-shaking CJS, but that's why we provide the ESM file), especially considering that most of our libraries are free from side effects.

@davidmurdoch
Copy link

Ran into this today. Is a fix on the horizon?

@mcmire
Copy link

mcmire commented Jan 31, 2024

@Mrtenz It seems like this is addressed via #157, is this true?

@davidmurdoch
Copy link

Will there be a release soon?

@Mrtenz
Copy link
Member

Mrtenz commented Mar 8, 2024

I thought we released this already, but apparently not. We weren't planning to do a release before the next audit (mid April), so I have to figure out if we can release without including the latest PR.

@davidmurdoch
Copy link

Thanks for the update.

This is the only esm package in metamask-extension that requires non-standard (er, for webpack -- so we're not really "standard" anyway) import resolution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants