Hey guys, I hope everyone’s doing well!
I am upgrading a Meteor project to 3.4 and ran into an issue with getting rspack to work. After upgrading to Meteor 3.4 and setting everything up, rspack is unable to find my project’s main.html file and due to this Vue 3 cannot mount when I start the project. The problem seems to stem from my project’s file structure. Instead of having a /client directory directly at the project’s root, I have the following structure:
/src/client/startup/main.js
/src/client/startup/main.html
And in package.json I have the following:
"meteor": {
"modern": true,
"mainModule": {
"client": "src/client/startup/main.js",
"server": "src/server/startup/main.js"
},
"testModule": "tests/main.js"
},
This worked fine with previous Meteor versions that used the jorgenvatle package with vite. But now with rspack it seems that having the /client directory under /src causes an issue whereby rspack just ignores the main.html inside src/client/startup. Even though in package.json I have marked the client side mainModule to “src/client/startup/main.js”.
If I add the following line in package.json to the meteor object, everything starts working fine again:
"modules": ["src/client/startup/main.html"],
However this seems like an undocumented option that I would prefer not to rely on. Can anyone suggest a better way to achieve this? Or am I being too skeptical about this line and perhaps it is exactly the right tool for this job without any negative side effects?
If at all possible I would like to avoid having to move everything inside the /src directory to root. Having a /src directory for code is a common pattern.
If anyone’s interested, this is what Claude had to say about the issue:
Root cause: The rspack Meteor package’s configureMeteorForRspack() function builds a list of directories to ignore. It takes all top-level
project directories and excludes only public/, private/, .meteor/, packages/, and the build context. Every other top-level directory —
including src/ — ends up in extraFoldersToIgnore as src/**.This ignore list is passed to setMeteorAppIgnore(), which tells Meteor’s build pipeline to skip those directories. As a result, static-html
never sees src/client/startup/main.html, so body.html in the compiled output is empty, andnever gets injected into the served
page.Why myapp (Meteor’s Vue 3 skeleton for 3.4) works: Its HTML is at client/main.html. The root-level client/ directory is similarly placed in the ignore list for rspack — but
that only tells rspack not to bundle those files. The difference is that client/ being at the root level seems to be handled correctly by this
mechanism (or the ignore only applies to rspack bundling, not to the Meteor static-html plugin processing pipeline).
Claude’s second long-winded explanation:
- The rspack Meteor package calls configureMeteorForRspack() during startup. It collects all top-level project directories, then adds every non-whitelisted one to METEOR_IGNORE as
dirname/**.- In myapp (Meteor’s Vue 3 skeleton for 3.4): entrypoint is client/main.js → ignores client/**, but adds the counter-pattern !client/.html → gitignore semantics allow this because client/ directory itself is not directly
excluded, only its contents — so !client/.html successfully un-ignores client/main.html.- In tmk4 (my app): entrypoint is src/client/startup/main.js → ignores src/** (the entire source tree), and adds !src/client/startup/.html as the counter-pattern. This fails — gitignore’s rule
is: “It is not possible to re-include a file if a parent directory of that file is excluded.” src/** causes src/client/startup/ to be treated as excluded, so the
!src/client/startup/.html exception has no effect.- METEOR_IGNORE is read by optimisticReadMeteorIgnore() in Meteor’s file scanner. With src/** active and no working counter-pattern, the scanner never delivers
src/client/startup/main.html to the static-html build plugin.- body.html stays empty → no
→ Vue can’t mount.The fix: The structure src/client/startup/main.html is fundamentally incompatible with how the rspack package generates its ignore rules.