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

ESM: Dynamic import of module does not work with Vite v4.3 #19886

Open
WolfgangDrescher opened this issue Jul 23, 2023 · 5 comments
Open

ESM: Dynamic import of module does not work with Vite v4.3 #19886

WolfgangDrescher opened this issue Jul 23, 2023 · 5 comments

Comments

@WolfgangDrescher
Copy link

I have a project that uses Verovio (https://github.com/rism-digital/verovio) which is a music notation engraving library in C++ that uses Emscripten with EXPORT_ES6 to allow using it via JavaScript in the browser. When I build the project with Vite.js I get an error:

Module "module" has been externalized for browser compatibility, imported by "~/node_modules/verovio/dist/verovio-module-hum.mjs". See http://vitejs.dev/guide/troubleshooting.html#module-externalized-for-browser-compatibility for more details

If you follow the link (http://vitejs.dev/guide/troubleshooting.html#module-externalized-for-browser-compatibility) to the docs of Vite, it says:

If the module is imported from a third-party library (that's meant to be used in the browser), it's advised to report the issue to the respective library.

I think this is thrown because of the dynamic import statement import('module'):

emscripten/src/shell.js

Lines 194 to 202 in bec42da

// `require()` is no-op in an ESM module, use `createRequire()` to construct
// the require()` function. This is only necessary for multi-environment
// builds, `-sENVIRONMENT=node` emits a static import declaration instead.
// TODO: Swap all `require()`'s with `import()`'s?
#if EXPORT_ES6 && ENVIRONMENT_MAY_BE_WEB
const { createRequire } = await import('module');
/** @suppress{duplicate} */
var require = createRequire(import.meta.url);
#endif

I guess the dynamic import is used to support ES6? In production mode with Vite everything works fine (the above error message is thrown as a warning), but when you use it development mode Vite is not able to import the Emscripten module because of the dynamic import. Is there a way Emscripten could improve this for a better support with Vite?

Also have a look at vitejs/vite#13530 and nuxt/nuxt#21578 and the reproduction repo: https://stackblitz.com/edit/github-rjaduf?file=src%2Fpages%2FHome.vue

Maybe @kleisauke or @curiousdannii have a better understanding about this than I do?

@WolfgangDrescher
Copy link
Author

With Vite 5 this got even more problematic. Here is a reproduction repository: https://stackblitz.com/edit/github-rjaduf-38mdms?file=src%2Fpages%2FHome.vue

Because vitejs/vite#13530 is closed as duplicate please also have a look at vitejs/vite#14169.

Is there any chance we can get rid of the dynamic await import('module') statement in the EXPORT_ES6 build?

Pinging @kleisauke, @curiousdannii, @sbc100 and @RReverser that were involved into the EXPORT_ES6 refactoring and discussion. Sorry for the spam.

@sbc100
Copy link
Collaborator

sbc100 commented Jan 23, 2024

Looking at the comment around the await import('module') statement it seems that one solution that would avoid importing 'module would be to switch from using require to using await import everywhere.

Would that help in this case? i.e. is its specifically the import of module that is the issue or are dynamic imports in general a problem?

@curiousdannii
Copy link
Contributor

@sbc100 That was the original plan, but it would've required a massive rewrite as none of the rest of the code is designed for async importing. Using createRequire was a clever way of getting things working without needing to rewrite the lot.

This seems like a particular issue with Vite's bundler. It's a shame they don't appear to be interested in fixing it on their end, but maybe there are legitimate reasons why they can't.

@WolfgangDrescher do you need multi environment builds? If you set it to only build for browser that code won't be emitted.

@WolfgangDrescher
Copy link
Author

It looks like this specific problem did get resolved since Vite v5.1.1: https://stackblitz.com/edit/github-rjaduf-caswxa?file=package.json

However, a rewrite for asynchronous importing, as suggested by @curiousdannii, would probably be the best long-term solution for Emscripten.

@vogel76
Copy link

vogel76 commented Jul 4, 2024

We have same problem while developing Hive Blockchain TS communication library. When our package is installed in next application, next.js bundler fails on given import('module');
Maybe you could consider then rewriting parts of such code to await import?

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

No branches or pull requests

4 participants