Bundling Emscripten-generated JS with Vite

227 views
Skip to first unread message

Zach Mertens

unread,
Jul 15, 2024, 9:56:44 AM7/15/24
to emscripten-discuss
Hi all,

I'm running into some issues bundling my Emscripten-generated JS/WASM files in a Vite+React project. I will quickly note I can run the files in a local server ("npm run dev"), and the issue seems related to running a production build.
When I run "npm run preview (tsc -b && vite build)", I get a console error: index-Bw7omusj.js:1 Uncaught ReferenceError: document is not defined at index-Bw7omusj.js:1:364 at index-Bw7omusj.js:1:1051 I have done research and found that the error means the DOM is being used on a server side (where it's not available). I was recommended to conditionally check if it's available in my component...
Here's my entry React component (main.tsx):
// imports .... // Importing the Emscripten-generated JS module works fine - I compiled the C++ with MODULARIZE=1, EXPORT_ES6=1 // and added type definitions for TypeScript
if (typeof window !== 'undefined') {
  const rootElement = document.getElementById('root');
  ReactDOM.createRoot(rootElement!).render(
    <React.StrictMode>
      <App />
    </React.StrictMode>,
  )
} else {
  console.error('Root element is null');
}
I think the issue is that Vite is bundling the DOM (using the Emscripten-generated "maze_builder.js / maze_builder.wasm" which I put in the Vite project (see screenshot).


vite_files2.PNG

Sam Clegg

unread,
Jul 15, 2024, 10:17:26 AM7/15/24
to emscripte...@googlegroups.com
Hi Zach,

Are you saying there is code in the emscripten-generated maze_builder.js that is using the DOM without first checking the API exists?  Which code is that can you point it?  

Where does `index-Bw7omusj.js` come from?  Is that the compiled version of your main.tsx?  

What does "bundling the DOM" mean?   Are you saying there is some kind of DOM emulation being included?  If so, then wouldn't you expect the check for the DOM APIs to succeed?   If vite is defining things like `window`, even under node, do you know why it is doing that?   Why do you think this is an emscripten issue?


cheers,
sam

--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-disc...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/emscripten-discuss/e3999811-471a-4970-a66a-705e8a6b5dc9n%40googlegroups.com.

Zach Mertens

unread,
Jul 15, 2024, 11:59:04 AM7/15/24
to emscripten-discuss
Hi Sam, thanks for checking this, this might be more of any issue with my Vite configuration but I wanted to respond with my train of thought to see if it helps clarify my question:

"Are you saying there is code in the emscripten-generated maze_builder.js that is using the DOM without first checking the API exists"

I have checked my generated "maze_builder.js" and it uses the DOM correctly and with correctly checks for undefined globals. I think the issue may be on the Vite bundling side then, but I wanted to check if there was a convention for bundling an Emscripten-generated Module within Vite (see my last response please).

"Where does `index-Bw7omusj.js` come from?  Is that the compiled version of your main.tsx?"

Yes, this file is generated by Vite and can have different naming each build. 

"What does "bundling the DOM" mean?"

From my understanding, Vite will bundle and minify the React components in a React app into the file "index-Bw7omusj.js" (or whatever naming is chosen). 
I guess I'm confused between running my app in the client browser (where DOM is available), and where/why/how Vite is running the production server with no DOM (unless Server-Side Rendering is available, which I'm not using).

I'm thinking Vite grabs the generated "maze_builder.js" when it's imported in a React component -- and maybe Vite is not verifying or stripping out the DOM when it bundles and generates "index-Bw7omusj.js". I opened the minified file "index-Bw7omusj.js" and looked for certain lines of code shown in Chrome dev tools that threw errors:

for(const l of document.querySelectorAll('link[rel="modulepreload"]'))r(l);

This line threw an error in Chrome Dev Tools with "Uncaught ReferenceError: document is not defined at index-Bw7omusj.js:1:364 " and along those lines. I kind of got my hands dirty and tried editing the minified file to include "if (typeof window !== 'undefined')" but that didn't feel like the right approach.

"If vite is defining things like `window`, even under node, do you know why it is doing that - "Why do you think this is an emscripten issue?"

From the research that I've done thus far, the DOM is not present in Node or server environments so that condition should fail. I thought there might be an Emscripten configuration I missed... ? I think this might be a Vite-related bundling issue.

I wanted to make sure I was using the Emscripten compiler switches correctly too. ("-s ENVIRONMENT=web,node, etc.."). I did a build with "-s ENVIRONMENT=node" only, but that didn't really solve the issue because then I can't run the app in the client browser locally or in Vite's production preview.

Sam Clegg

unread,
Jul 15, 2024, 12:03:33 PM7/15/24
to emscripte...@googlegroups.com
This does sound like a vite bundling issue.   I dont know of anything in emscripten that is specific to vite (i honestly don't really know what vite is).

I suggest you bring this up with the vite folks and then if there is anything specific that we can do on the emscripten side to make things better please let us know.

cheers,
sam

Reply all
Reply to author
Forward
0 new messages