Weekly Update, April 16, 2025 – Faster Bundle Times with 3.3-beta.0! 🚀

Hello everyone, it’s time for our weekly update! :rocket:

We’ve got some exciting news, Meteor 3.3-beta.0 is out now!

This release brings a major update to the Meteor bundler, including several improvements and optimizations. The highlight is the adoption of the SWC transpiler.

It also includes important community contributions, especially around Meteor React packages, improving stability and performance for commonly used hooks.

Tasks and fixes for Meteor 3.3-beta.0

  • Support SWC transpiler for faster dev and builds PR#13657
  • Default to modern architecture in new apps PR#13665
  • Support CPU profiling in Meteor 3 bundler PR#13650
  • Improve meteor profile: show rebuild steps, support --build PR#13694
  • Improve useFind and useSubscribe React hooks
  • Add replaceEmailAsync helper to Accounts PR#13677
  • Fix user agent detection and oplog collection filtering
  • Refine type definitions for Meteor methods and SSR’s ServerSink
  • Update Express to 5.1.0

:link: All merged PRs: GitHub PRs 3.3

:link: React packages changelog: 4.0.0-beta.0

Your feedback is crucial in adjusting this beta before the official launch. Our core team is running tests, but community testing is key to ensuring Meteor 3.3 is stable. Let us know what you find!

Hands on

To use it, please do:

meteor update --release 3.3-beta.0

or create a new app:

meteor create --release 3.3-beta.0

Add the following to your package.json to quickly get started with the new bundler setup:

"meteor": {
  "modernWebArchsOnly": true,
  "modernTranspiler": true
}

These settings are on by default for new apps.


Highlights

Modern transpiler: SWC

We’ve started improving the bundler experience. Meteor bundler includes different components: a transpiler to convert files into browser-friendly syntax, a linker to build the final output, and a dev server for fast feedback and runtime features.

In Meteor 3.3, we focused on the transpiler. meteor profile showed most build time is spent transpiling with Babel. To address this, we’ve added SWC (written in Rust), which makes rebuilds significantly faster.

  • Cold and cache starts are ~2.6x faster than 3.2 in all build phases.

  • Rebuilds and HMR are ~1.5x faster in client and server phases.

Results are from fredmaiaarantes/simpletasks app on a specific machine. Your app may vary, test it yourself.

Modern transpiler is enabled by default for new apps. To enable it in existing ones, add this to your package.json:

"meteor": {
  "modernTranspiler": true
}

There are no breaking changes. However, if your app uses nested imports (not dynamic ones), it may fall back to Babel. The same applies if you’re using Babel plugins not supported by SWC yet. You can look for SWC equivalents or exclude SWC for specific file contexts. We’ve also created a doc page with tips for migrating and debugging the new transpiler setup, Modern Transpiler: SWC docs.

Want to help us test? Try Meteor 3.3 on your apps, compare profiles between versions, and share the results, we’d love to see the numbers and profiles for further improvements.

Don’t forget to enable the config in the next section for extra speed gains! :rocket:

Modern builds by default

As mentioned in a previous release, skipping web.browser.legacy and web.cordova makes builds faster. We’ve now made this the default in new apps only in dev mode.

For existing apps use the next config in your package.json.

"meteor": {
  "modernWebArchsOnly": true
}

Thanks to @9Morello for driving this one forward!

CPU profiling tool for the bundler

We’ve added an automated way for Meteor developers to generate CPU profiles for deeper bundler analysis. This is mainly for contributors looking to identify performance issues in specific app cases.

@italojs explains the new Meteor environment variables and how to generate and inspect CPU profiles in his article: “Enhancing Performance in MeteorJS bundler: Complete Guide to CPU Profiling”. He also shows how Babel has been a key bottleneck, which we’re addressing with the SWC replacement in 3.3.

Want to help us? Join the Effort to Speed Up Meteor bundler

React hooks, now faster

We’ve updated the meteor/react-packages repo to restore tests and CI, keeping compatibility with the latest React 18 and Meteor 3. This also encouraged updates from contributors to make more efficient useFind and useSubscribe.

If you use react-meteor-data, a new beta is available. Try it out:

meteor add react-meteor-data@4.0.0-beta.0

Big thanks to @welkinwong, @Poyoman39, and @PedroMarianoAlmeida for actively contributing and adding clear tests to help ship these improvements safely!

Be aware of a breaking change: useFind describes no deps by default #431

Huge thanks to our contributors

Join us and contribute! Check out Meteor GitHub issues or start with Good first issues.

What’s Next?

  • Meteor 3.3 – Coming Soon

    • The beta phase is open and may include multiple versions, depending on your feedback.
    • We’ll continue testing bundler improvements and other updates. If we find quick wins or issues, we’ll address them.
    • After a solid testing period, we’ll ship the official 3.3 release.
  • Meteor 3.4 – On the Horizon

    • Expect a deeper bundler integration to enable new production features, broader plugin support, and even faster builds by shifting more Meteor bundler processes to a modern tool.

Stay tuned, and as always, happy coding! :comet:

7 Likes

The first 3.3-beta.0 includes the SWC modern transpiler, builds only for modern web architectures, and adds other optimizations.

We’ve already found more ways to improve Meteor’s performance before introducing an external bundler.

We’re measuring the impact of upcoming changes to include in the next beta, with further optimizations:

  • Skip compilation for excluded architectures (legacy) PR#13698

  • Add support for @parcel/watcher as an alternative faster and cross-OS compatible file watcher PR#13699

  • Investigate performance issue with offline catalog database (SQLite) affecting speed in published releases. PR#13702

We need help to make sure these changes are properly delivered across your Meteor projects. This will let us move forward with more internal updates. Time to modernize! :grin:

5 Likes

what do you mean nested imports? could you give some examples? is that related to npm packages?

https://www.perplexity.ai/search/9ecf68d4-4215-4796-9804-127b4852f4e3

1 Like

Nested imports are a Meteor-specific feature in its bundler, unlike standard bundlers. Meteor introduced them during a time when bundling standards were still evolving and experimented with its own approach. This feature comes from the reify module and works with Babel transpilation. SWC doesn’t support them since they were never standardized.

Example with a nested import:

if (condition) {
  import { a as b } from "./c";
  console.log(b);
}

Without a nested import (moved to top):

import { a as b } from "./c";

if (condition) {
  console.log(b);
}

For background, see: Why nested import.


As mentioned, SWC doesn’t support nested imports. In version 3.3-beta.0, if SWC encounters one, it silently falls back to Babel without any visible error. This isn’t standard, and most modern projects work fine without them, using other deferred loading strategies instead. So you may want to move imports to the top or use require, getting more build speed out of it as SWC would transpile. Still, it’s your call, we know some Meteor devs use them for valid reasons.

We’ve also added docs showing how to check for nested imports or SWC issues using verbose mode: Adapt your code to benefit from SWC.

1 Like

@nachocodoner

Feel free to send me full logs using the METEOR_DEBUG_SQL=1 meteor profile command for your apps.

Make sure to add the following under the meteor key in your package.json. I enabled verbosity to get full details on your app’s behavior.

"meteor": {
  "modernWebArchsOnly": true,
  "modernTranspiler": {
     "verbose": true
  }
}

I added METEOR_DEBUG_SQL=1 because I noticed some SQL queries in published versions take longer or run distinctly, and this info helps with upcoming fixes. This may change the results slightly, so you can try again later without METEOR_DEBUG_SQL=1.

I’ve already received some feedback and found a few areas to adjust based on the variety of project setups, so this is useful.

You can send the logs privately via the forums or to my email: nacho@meteor.com. Please include your forum username so I can reply. You can also message me privately on the forums or Discord for a chat-like conversation on specific issues you get.

Make sure to review the profiles sensitive information first and remove it if exists. :rofl:

Interesting, why I don’t have -- Notice -- part likes yours?

@minhna I am really sorry to hear that. I can copy and paste it in a file for you to have it too :)))).

Ok, let’s see. As advised by @nachocodoner I was not supposed to see that.

Maybe related to how I installed Meteor on this M1. I have it installed the “old way” with the curl command and not with npx.

Then how do I know if it uses SWC or Babel?

I added more details in the docs: Adapt your code to benefit from SWC. These are in the staging environment.

To enable it, add this to your package.json:

"meteor": {
  "modernTranspiler": {
	  "verbose": true
  }
}

You will see logs like these:

2 Likes

My app before and after enable modernWebArchsOnly

3 Likes

3.2.0 vs 3.3-beta.0 SWC off vs 3.3-beta.0 SWC on

5 Likes

I think the DO_NOT_TRACK flag also made it to this release. :smiley:
Good job, y’all!

2 Likes

We’ve wrapped up the latest performance improvements mentioned above. 3.3-beta.1 is coming soon, we’re just revisiting the docs, testing, addressing some feedback, and clearing up a few remaining issues.

We’ve received private profiles that helped us understand different setups and gather focused feedback. This has been really helpful to see how updates behave in various environments. Thanks to everyone who tested early. :pray:

Here’s a quick look at how the numbers shift from 3.2 and 3.3-beta.0 in the upcoming 3.3-beta.1.

Results are from fredmaiaarantes/simpletasks app on a specific machine, and using Meteor checkout

An issue in published Meteor version was also fixed, so using it when published should show more noticeable performance gains than checkout results above.

We are likely hitting already performance improvement limits on Meteor 3.3, or at least, we consider it sufficient for now. Meteor 3.4 will push those numbers down further, as more of the app’s code and dependencies processes, like watching, transpiling, compiling, and minifying, will be delegated to a modern bundler. That will allow Meteor concentrate on what matters: Atmosphere packages, dev server app, Mongo dev server, CLI, produce the final bundle and other specifics.

8 Likes

Published a new version of react-meteor-data. This time I bumped to a major 4.0.0-beta.0 since it includes a breaking change: useFind describes no deps by default #431. Changelog

meteor add react-meteor-data@4.0.0-beta.0

4 Likes

Curl installs can be less stable on M1 systems consider reinstalling Meteor via npx for smoother performance

1 Like

In my first job in tech, in 2000, we were running a full hotel on a Compaq computer. I learnt the concept which guided my entire career: “Never touch a running machine”.
My station now runs so well with Meteor and a local Mongo Server, I am reluctant to even change my OS from dark to light theme :).

I’m getting this error in my frontend application when I try to start my app after updating to Meteor 3.3 Beta 0. It seems like browser-policy-content package needs an update/fix.

Any idea?

[[[[[ ~/yourdnafamily/frontend ]]]]]          

=> Started proxy.                             
I20250425-10:24:11.489(-4)? error on boot.js /home/ferjep/yourdnafamily/frontend/.meteor/local/build/programs/server/packages/browser-policy-content.js:363
I20250425-10:24:11.494(-4)? await setDefaultPolicy();
I20250425-10:24:11.494(-4)? ^^^^^
I20250425-10:24:11.494(-4)? 
I20250425-10:24:11.494(-4)? SyntaxError: await is only valid in async functions and the top level bodies of modules
I20250425-10:24:11.494(-4)?     at new Script (node:vm:117:7)
I20250425-10:24:11.495(-4)?     at createScript (node:vm:269:10)
I20250425-10:24:11.495(-4)?     at Object.runInThisContext (node:vm:317:10)
I20250425-10:24:11.495(-4)?     at /tools/static-assets/server/boot.js:414:32
I20250425-10:24:11.495(-4)?     at /tools/static-assets/server/boot.js:502:11
I20250425-10:24:11.495(-4)?     at Function.run (/home/ferjep/yourdnafamily/frontend/.meteor/local/build/programs/server/tools/tool-env/profile.ts:651:14)
I20250425-10:24:11.495(-4)?     at startServerProcess (/tools/static-assets/server/boot.js:501:17)
I20250425-10:24:11.495(-4)?     at Object.<anonymous> (/tools/static-assets/server/boot.js:506:2)
I20250425-10:24:11.495(-4)?     at Object.<anonymous> (/tools/static-assets/server/boot.js:510:4)
I20250425-10:24:11.495(-4)?     at Module.<anonymous> (node:internal/modules/cjs/loader:1554:14)
I20250425-10:24:11.495(-4)?     at Module.Mp._compile (/tools/static-assets/server/runtime.js:78:21)
I20250425-10:24:11.495(-4)?     at Object.Module._extensions..js (/tools/static-assets/server/runtime.js:112:21)
I20250425-10:24:11.495(-4)?     at Module.<anonymous> (node:internal/modules/cjs/loader:1289:32)
I20250425-10:24:11.496(-4)?     at Module.Mp.load (/tools/static-assets/server/runtime.js:35:31)
I20250425-10:24:11.496(-4)?     at Function._load (node:internal/modules/cjs/loader:1108:12)
I20250425-10:24:11.496(-4)?     at TracingChannel.traceSync (node:diagnostics_channel:322:14)
I20250425-10:24:11.496(-4)? /home/ferjep/yourdnafamily/frontend/.meteor/local/build/programs/server/packages/browser-policy-content.js:363
I20250425-10:24:11.496(-4)? await setDefaultPolicy();
I20250425-10:24:11.496(-4)? ^^^^^
I20250425-10:24:11.496(-4)? 
I20250425-10:24:11.496(-4)? SyntaxError: await is only valid in async functions and the top level bodies of modules
I20250425-10:24:11.496(-4)?     at new Script (node:vm:117:7)
I20250425-10:24:11.496(-4)?     at createScript (node:vm:269:10)
I20250425-10:24:11.496(-4)?     at Object.runInThisContext (node:vm:317:10)
I20250425-10:24:11.496(-4)?     at /tools/static-assets/server/boot.js:414:32
I20250425-10:24:11.496(-4)?     at /tools/static-assets/server/boot.js:502:11
I20250425-10:24:11.496(-4)?     at Function.run (/home/ferjep/yourdnafamily/frontend/.meteor/local/build/programs/server/tools/tool-env/profile.ts:651:14)
I20250425-10:24:11.497(-4)?     at startServerProcess (/tools/static-assets/server/boot.js:501:17)
I20250425-10:24:11.497(-4)?     at Object.<anonymous> (/tools/static-assets/server/boot.js:506:2)
I20250425-10:24:11.497(-4)?     at Object.<anonymous> (/tools/static-assets/server/boot.js:510:4)
I20250425-10:24:11.497(-4)?     at Module.<anonymous> (node:internal/modules/cjs/loader:1554:14)
I20250425-10:24:11.497(-4)?     at Module.Mp._compile (/tools/static-assets/server/runtime.js:78:21)
I20250425-10:24:11.497(-4)?     at Object.Module._extensions..js (/tools/static-assets/server/runtime.js:112:21)
I20250425-10:24:11.497(-4)?     at Module.<anonymous> (node:internal/modules/cjs/loader:1289:32)
I20250425-10:24:11.497(-4)?     at Module.Mp.load (/tools/static-assets/server/runtime.js:35:31)
I20250425-10:24:11.497(-4)?     at Function._load (node:internal/modules/cjs/loader:1108:12)
I20250425-10:24:11.497(-4)?     at TracingChannel.traceSync (node:diagnostics_channel:322:14)
=> Exited with code: 1
=> Your application is crashing. Waiting for file change.

Meteor configs

  "meteor": {
    "modernWebArchsOnly": true,
    "modernTranspiler": true,
    "mainModule": {
      "client": "client/main.js",
      "server": "server/main.js"
    }
  },