3 ms·
In Bun, you can use import and require in the same file. There's three steps for what makes this work: 1) We patched JavaScriptCore to load ES Modules synchron
by Jarred 3y ago
In Bun, you can use import and require in the same file. There's three steps for what makes this work:
1) We patched JavaScriptCore to load ES Modules synchronously when they don't use top-level await. The main tradeoff here is that requiring an ES Module which uses top-level await is unsupported (Bun throws an exception when you try to do this)
2) To support require() inside ES Modules, we add `import.meta.require` and have a transpiler integration to convert calls to module.require() or require() into import.meta.require(). This either loads the file as an ES Module or as a CommonJS module, depending on what the transpiler says it is
3) We rely on certain heuristics to decide whether a script is an ES Module or a CommonJS module. If they use certain sloppy mode or CommonJS-only features, it becomes CommonJS. If they use ESM features or it's somewhat ambiguous, it becomes an ES Module.
- jwalton 3y agoI’ve often wondered why node doesn’t do 1 in this list. It would solve 95% of the problems, I’m sure.
- jcheng 3y agoFor 1), what about requiring an ES module that doesn’t itself use top-level await, but imports another ES module that uses top-level await?
- Jarred 3y agoThat throws since we cannot make it synchronous. It works by reading the internal state of the Promise and getting the value out of it if the Promise is fulfilled.
- TimTheTinker 3y agoWhile I appreciate the convenience that will result from this excellent engineering, I'm concerned that this could result in a lot of mixed module files that now can only work with Bun. Is there an option to require each file to use either CJS or ESM features, but not both? If not, may I suggest adding that option?
- moritzwarhier 3y agoSeems like a case for ESLint and I agree with you. Mixed require and import (the latter in both its static and dynamic variants) is already possible with Webpack and Vite. I hate it and would complain about any code introducing this in any kind of review. It's great for integration, full stop. This is an inconvenience where tradeoffs really show and demand to study the behavioral/semantic differences. Funnily enough, I still find Bun interesting. Regarding import.meta., I already love Vite's dynamic import transpilation features. They aim to work almost transparently and often do (I am not even talking about the glob feature here). That being said, I'm unsure if Bun's way of bridging the module ecosystem gap using import.meta will be as useful. If you ask me, frontend code should ban Node/CJS/require entirely or transpile it into static or dynamic ESM imports; respectively. Any case where this is not possible unambiguously is a case for human intervention and code rewrite/conversion.
- imbnwa 3y ago>If you ask me, frontend code should ban Node/CJS/require entirely or transpile it into static or dynamic ESM imports; respectively. >Any case where this is not possible unambiguously is a case for human intervention and code rewrite/conversion. Good god, yes
- silverwind 3y agoWhy go to such lengths to support a legacy module system? All three patches mentioned will lead to modules that work only in bun and not work in node/deno/browsers, further fragmentating the ecosystem.
- The_Colonel 3y agoIt's a legacy module system with a lot of code written in it. Without mixed support, you can't rewrite code incrementally to use the ES modules. As a consequence, many projects still stay with CommonJS, since the migrating everythin in one go is a big hurdle.