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

Dynamic import() in a CJS file can execute a module twice #499

Open
4 of 6 tasks
qraynaud opened this issue Mar 21, 2024 · 3 comments
Open
4 of 6 tasks

Dynamic import() in a CJS file can execute a module twice #499

qraynaud opened this issue Mar 21, 2024 · 3 comments
Labels
blocked bug Something isn't working

Comments

@qraynaud
Copy link

Acknowledgements

  • I searched existing issues to avoid duplicates
  • I understand this is a place to report a confirmed bug (not seek debugging help)
  • I understand this is a collaborative open source project, and relies on community contributions
  • I have read and understood the Contribution guide

Minimal reproduction URL

https://stackblitz.com/edit/stackblitz-starters-hfn7ts

Version

4.7.1

Node.js version

18.18.0 and 20.11.0

Package manager

npm

Operating system

Linux

Problem & expected behavior (under 200 words)

  • What happened

I’m in the process of migrating an app from CJS to ESM. This app contains some dynamic imports. The files dynamically imported are in part all the mongoose models to collect data on them and to basic checks. As soon as I started changing the extension of some models from .ts to .mts I had issues with mongoose reporting that I'm trying to register the same model twice. I made a simple repro in the provided stackblitz.

  • What I expected

You have 2 files in my minimun repro. One works.mts and one bugs.ts. They both basically contain the same code. Only the extension changes. It should execute the module.mts file alongside them only once. But in one case it is executed twice.

Contributions

  • I will open a pull request for this issue
  • I will support the work financially (any amount helps)
@qraynaud qraynaud added bug Something isn't working pending triage labels Mar 21, 2024
@privatenumber
Copy link
Owner

This is definitely unexpected.

What's happening is the first import statement gets converted to require(), and since require can't load Module (.mjs) files, it transforms them to CommonJS so it can be. The second dynamic import() remains untouched.

So the first and second files are technically different modules, where the first one is dynamically derived on demand.

This is a technical limitation but it will be resolved once nodejs/node#51977 lands

@qraynaud
Copy link
Author

qraynaud commented Mar 22, 2024

I understand that you keep the dynamic import, but since it’s using mts behind, it means that at some point tsx get to transpile it "again" right? So in this instance you do transpile it as an ESM module instead of as a CJS modules as the first time right? Could you not detect that it was previously loaded as a CJS and return the CJS version instead (since node do support import() on CJS files)? Or return to node a fake module that does export the required CJS module?

Even waiting for nodejs/node#51977 would not really resolve the issue since this patch does not support requiring modules with top level async in them.

Replacing the import() with a require() implicitely would end badly for a lot of files.
And if you replace it with a try/catch to fallback to import(), then the bug I'm reporting would still be there for those.

@privatenumber
Copy link
Owner

I'm not sure, but feel free to give it a tackle. I'd be happy to review the PR!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
blocked bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants