New 3.4-beta.11 Release, Faster Builds, Smaller Bundles and Modern Setups with the Rspack integration ⚡

This seems odd. I’m running Meteor 3.4-beta.11 . I was on a branch where everything runs as expected.

In package.json, I updated this:

"react-router-dom": "^6.23.1",

… to this:

"react-router": "^7.9.3",

I didn’t expect react-router 7 to work yet because there are a lot of other changes to make to the code to update from react router 6 to 7. I expected to get a lot of react router error.

But instead, the client wouldn’t load, due to this unexpected and seemingly unrelated error:

In module.js:

        } catch (error) {
            console.error(`Error loading route module \`${route.module}\`, reloading page...`);
            console.error(error);
            if (window.__reactRouterContext && window.__reactRouterContext.isSpaMode && // @ts-expect-error
            import.meta.hot) {
                throw error;
            }
            window.location.reload();
            return new Promise(()=>{});
        }

…on the line:

            import.meta.hot) {
                throw error;
            }

…I get the error:

Uncaught SyntaxError: Cannot use ‘import.meta’ outside a module (at modules.js?hash=81d9f1b41933efc36c207594a7a96b81aa72a01a:26920:20)

To further identify the file in which the error occurs, the first lines of the file are:

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// This is a generated file. You can view the original                  //
// source in your browser if your browser supports source maps.         //
// Source maps are supported by all recent versions of Chrome, Safari,  //
// and Firefox, and by Internet Explorer 11.                            //
//                                                                      //
//////////////////////////////////////////////////////////////////////////


Package["core-runtime"].queue("modules",function () {/* Imports */
var Meteor = Package.meteor.Meteor;
var global = Package.meteor.global;
var meteorEnv = Package.meteor.meteorEnv;
var meteorInstall = Package['modules-runtime'].meteorInstall;
var verifyErrors = Package['modules-runtime'].verifyErrors;

var require = meteorInstall({"node_modules":{"meteor":{"modules":{"client.[.....]

Does that make any sense?

I was able to create a tiny test example that shows the same anomaly.

  • Created a new app using meteor create --react
  • Updated to Meteor 3.4-beta.11
  • Added "react-router": "^7.9.3" to package.json
  • Asked a Claude agent to add a component to implement react router v7
  • Launched the app
  • The identical anomaly occurred

Here is a link to the tiny test app:

https://gitlab.com/VikR0001/react-router-7-anomaly

The initial post mentions the command to create an app with the latest beta.
You have that problem because you create the app with 3.3 which is set for CommonJS.
You might have this in your package.json - "type": "commonjs". It needs to go away with Meteor 3.4

The solution with Meteor 3 was to us a patch for the react-router package.
Add patch-package NPM to your dev dependencies and this is my patch file called react-router+7.7.0.patch in the patches folder in root.

What it does - it renames all the .mjs extensions to .js.

diff --git a/node_modules/react-router/package.json b/node_modules/react-router/package.json
index a93691a..5e5f72e 100644
--- a/node_modules/react-router/package.json
+++ b/node_modules/react-router/package.json
@@ -20,26 +20,26 @@
   "sideEffects": false,
   "types": "./dist/development/index.d.ts",
   "main": "./dist/development/index.js",
-  "module": "./dist/development/index.mjs",
+  "module": "./dist/development/index.js",
   "exports": {
     ".": {
       "react-server": {
-        "module": "./dist/development/index-react-server.mjs",
+        "module": "./dist/development/index-react-server.js",
         "default": "./dist/development/index-react-server.js"
       },
       "node": {
         "types": "./dist/development/index.d.ts",
-        "module": "./dist/development/index.mjs",
-        "module-sync": "./dist/development/index.mjs",
+        "module": "./dist/development/index.js",
+        "module-sync": "./dist/development/index.js",
         "default": "./dist/development/index.js"
       },
       "module": {
         "types": "./dist/development/index.d.mts",
-        "default": "./dist/development/index.mjs"
+        "default": "./dist/development/index.js"
       },
       "import": {
         "types": "./dist/development/index.d.mts",
-        "default": "./dist/development/index.mjs"
+        "default": "./dist/development/index.js"
       },
       "default": {
         "types": "./dist/development/index.d.ts",
@@ -49,17 +49,17 @@
     "./dom": {
       "node": {
         "types": "./dist/development/dom-export.d.ts",
-        "module": "./dist/development/dom-export.mjs",
-        "module-sync": "./dist/development/dom-export.mjs",
+        "module": "./dist/development/dom-export.js",
+        "module-sync": "./dist/development/dom-export.js",
         "default": "./dist/development/dom-export.js"
       },
       "module": {
         "types": "./dist/development/dom-export.d.mts",
-        "default": "./dist/development/dom-export.mjs"
+        "default": "./dist/development/dom-export.js"
       },
       "import": {
         "types": "./dist/development/dom-export.d.mts",
-        "default": "./dist/development/dom-export.mjs"
+        "default": "./dist/development/dom-export.js"
       },
       "default": {
         "types": "./dist/development/dom-export.d.ts",
@@ -79,22 +79,22 @@
     },
     "./internal/react-server-client": {
       "react-server": {
-        "module": "./dist/development/index-react-server-client.mjs",
+        "module": "./dist/development/index-react-server-client.js",
         "default": "./dist/development/index-react-server-client.js"
       },
       "node": {
         "types": "./dist/development/index.d.ts",
-        "module": "./dist/development/index.mjs",
-        "module-sync": "./dist/development/index.mjs",
+        "module": "./dist/development/index.js",
+        "module-sync": "./dist/development/index.js",
         "default": "./dist/development/index.js"
       },
       "module": {
         "types": "./dist/development/index.d.mts",
-        "default": "./dist/development/index.mjs"
+        "default": "./dist/development/index.js"
       },
       "import": {
         "types": "./dist/development/index.d.mts",
-        "default": "./dist/development/index.mjs"
+        "default": "./dist/development/index.js"
       },
       "default": {
         "types": "./dist/development/index.d.ts",
@@ -159,4 +159,4 @@
     "watch": "tsup --watch & tsup --config tsup.config.rsc.ts --watch",
     "typecheck": "tsc"
   }
-}
\ No newline at end of file
+}

I can’t access the repo you shared. I get a 404 error.

Do you have the Rspack package in your app? The error looks like it comes from the Meteor bundler compiling your code, which suggests Rspack isn’t running.

Rspack recognizes those export fields, so you don’t need the workaround @paulishca mentioned. That workaround fits a pure Meteor bundler setup without ESM config support, not a Rspack integration, which support it. I also have tests of react-router in the modern test suite confirming no patches required for Meteor when Rspack is integrated to recognize ESM packages.

Please grant repo access so I can check. I suspect Rspack isn’t compiling your app code yet, but if there is another reason I’d like to fix it.

I understand the cache problems happen mainly with your setup using a cloudflared tunnel, not on a normal localhost dev project, right?

I’ve found a few cache issues on the localhost dev server and I’m fixing them. They show up when changing config files and only on app restart. I’m making the cache system aware of these cases. But your issue seems specific to that remote dev setup.

It’s not recommended to add a hash to client-rspack.js. That file handles HMR updates, and a cache buster in the URL breaks that logic. For your setup you may need to disable HMR. Have you tried devServer.hot: false in your rspack.config.js? It should trigger a full reload instead automatically (liveReload: true is set by default).

If you want to keep HMR with your approach, we may need strict cache headers so that file is always fetched from the network. Can you try adding:

devServer: {
  headers: {
    "Cache-Control": "no-store, no-cache, must-revalidate, proxy-revalidate",
    "Pragma": "no-cache",
    "Expires": "0",
    "Surrogate-Control": "no-store"
  }
}

Meteor add rspack fixed it. :100:

I wonder if updating Meteor should give the user an alert to add rspack?

The repo link (without rspack) is now public in case anyone would like to access it.

Thanks @nachocodoner !

2 Likes