Faster Builds in Meteor 3.3: Modern Build Stack with SWC and Bundler Optimizations

Just to double-check, where did you add your "modern": true config? It needs to go in your app project’s package.json file (no settings.json). Also, make sure it isn’t already there, most Meteor apps already include the Meteor config with mainModule and testModule settings.

I attach an example of package.json config:

image

Also, to understand if SWC or Babel is used you should activate the verbose mode, adding modern like:

"meteor": {
  "modern": {
    "transpiler": {
      "verbose": true
    }
  }
}

I’ll send you a DM to help enable your SWC, and you can forward me the verbose logs so I can verify everything is set up correctly.

Edit:

The “Server startup” log you provided doesn’t prove SWC isn’t used, since SWC runs at build time and the startup phase is runtime, where Babel may still be in use. Instead, the “Build App” phase can be used to confirm SWC is enabled.

1 Like

Do we still need modernWebArchsOnly and modernTranspiler in our package.json file?

like here:

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

Also running the app with --exclude-archs web.browser.legacy. When I run it, I get this warning:

modern.webArchOnly and --exclude-archs are both active. If both are set, --exclude-archs takes priority.

Thanks in advance, congrats to the team on this milestone,

Andreas

modernTranspiler and modernWebArchsOnly are no longer needed. They were added in the first beta, but in the next beta we replaced them with a single modern field that activates all context optimizations by default. You can opt out of each one within modern.

Please check the docs and each component’s section for more details.

Also running the app with --exclude-archs web.browser.legacy . When I run it, I get this warning:

The warning is harmless. It just means that enabling “modern” already applies “exclude-archs,” so you don’t need to include it.

Thanks @nachocodoner . I’ll reply on the DM.

FANTASTIC SPEEDUP FOUND

Initial Build Timings
Meteor 3.2, with METEOR_PROFILE turned off: 63 seconds

Meteor 3.3, with METEOR_PROFILE and verbose transpiler logs both turned off: 31 seconds

Meteor 3.3, with METEOR_PROFILE and verbose transpiler logs both turned on: 50 seconds

2 Likes

Here’s what I learned from @nachocodoner:

If you’re not seeing a speedup, turn on verbose logging by adding this to package.json:

  "meteor": {
    "modern": {
      "transpiler": {
        "verbose": true
      }
    }
  },

The logs will call out things that need to be fixed.

If you use React and have some functions in .js files that return jsx, add this file to the root of your app directory:

filename: .swcrc — first character is . – it’s an invisible file
contents:

{
  "jsc": {
    "parser": {
      "syntax": "ecmascript",
      "jsx": true
    }
  }
}

That tells SWC to treat all .js files like .jsx files.

1 Like

Great work, the speed improvements are amazing :smile:

2 Likes

Something I noticed.
After upgrading 3.3 from 3.3-rc.0 I could no longer deploy some of my projects. They would upload to AWS EBS with MUP and fail to start on the EC2.

Deleting the local builds from the .meteor folder and rebuilding again fixed the issue. This happened on 2 (the largest) of 5 projects. 2 others had no issues, the 5th I haven’t tried yet.

It looks like sometimes could be needed meteor reset first, especially after the inclusion of SWC, or as moving from legacy to modern build stack, probably due to transpilation caching inconsistencies. I hope this doesn’t recur with each new release, or it’ll become a hassle.

Please let me know if this happens on future deploys, in the same version or in new ones, including betas. :pray:

It happened to me in the past when moving from one version to another within Meteor 3. I imagined this had something to do with some caching of files in the build, and once enough is changed in Meteor, incompatibilities arise.
If I remember right, meteor reset no longer deletes the local DB. Perhaps, when a new version is published, the announcement could include a suggestion to do a meteor reset just to make sure things are “fresh”

So this issue isn’t limited to the modern build stack? It probably existed earlier. If you learn more, please open an issue in the tracker.

Yes, we avoided deleting the database, that change came in Meteor 3.0.x (the first official version I think). It might be related. I’ll still include the meteor reset suggestion in the announcements.

Thanks for the tip, I’ve got this fallback that I don’t understand:

[Transpiler] Used Babel for blaze/exceptions.js                               (package)                          ⚠️  Fallback (web.browser)

  ↳ Error:   x 'eval' and 'arguments' cannot be used as a binding identifier in strict mode
    ,-[packages/blaze/exceptions.js:56:1]
 53 |   if (typeof f !== 'function')
 54 |     return f;
 55 | 
 56 |   return function (...arguments) {
    :                       ^^^^^^^^^
 57 |     try {
 58 |       return f.apply(this, arguments);
 59 |     } catch (e) {
    `----


Caused by:
    Syntax Error

Also it seems that the owner of ostrio:flow-router-extra and montiapm need to fix these:

[Transpiler] Used Babel for ostrio:flow-router-extra/server/plugins/fast-render.js(package)                          ⚠️  Fallback (os.osx.x86_64)

↳ Error:   x Return statement is not allowed here
,-[packages/ostrio:flow-router-extra/server/plugins/fast-render.js:6:1]
3 | import { FlowRouter } from '../_init.js';
4 |
5 | if(!Package['communitypackages:fast-render']) {
6 |   return;
:   ^^^^^^^
7 | }
8 |
9 | const FastRender = Package['communitypackages:fast-render'].FastRender;
`----

Caused by:
Syntax Error
[Transpiler] Used Babel for montiapm:meteorx/src/fiberless/mongo.js           (package)                          ⚠️  Fallback (os.osx.x86_64)

  ↳ Error:   x 'import', and 'export' cannot be used outside of module code
   ,-[packages/montiapm:meteorx/src/fiberless/mongo.js:6:1]
 3 | export async function exposeMongoAsync(MeteorX) {
 4 |   if (!MeteorX._mongoInstalled) return
 5 | 
 6 |   import { MongoInternals } from "meteor/mongo";
   :   ^^^^^^
 7 | 
 8 |   const coll = _getDummyCollection();
   `----


Caused by:
    Syntax Error

  💡 Tip: Remove nested imports or replace them with require to support SWC and improve speed.

Am I correct?

x ‘eval’ and ‘arguments’ cannot be used as a binding identifier in strict mode

If you rename arguments to args, it passes the SWC syntax check. In strict mode, eval and args are reserved identifiers. Though, that seems to be within the blaze package? If that is, could you provide a PR fixing this?

Also it seems that the owner of ostrio:flow-router-extra and montiapm need to fix these:

Yes, if you can report to those repositories or fix these in a PR it would be great.

Verbose mode lets you check SWC compatibility with your project and ensures you fix all fallbacks using this mechanism.

When we deliver the Meteor-RSPack integration, which uses SWC to transpile and bundle your app code, your project will need to be fully compatible with SWC since RSPack likely won’t offer fallbacks. In Meteor 3.3 modern build stack, you can keep Babel fallbacks for the few affected files and still get good performance. If you want the full benefits of the future modern bundler integration, start preparing now.

1 Like

I see that oxc.rs is not mentioned in this forum at all, and also not compared at swc.rs (or mentioned anywhere on the SWC website). Was oxc considered at all in this iteration of Meteor? Will it be in the future? Why? Why not?

There are always new tools araising, known or unknown. Honestly, this is the first time I’ve heard of Oxc transpiler.

One immediate reason for not including it is that it’s still in development. For example, we’ve reworked the minifier, but Oxc doesn’t have its own implementation yet.

There are other points we could discuss. SWC is the most popular and supports many Babel plugins after years of work, which makes integration straightforward. It’s also used in Meteor packages like zodern/minify-js-sourcemaps, and it’s already built into bundlers such as Rspack and Vite, with most issues solved, ensuring proper development for production envs.

I think we should stick with tools that are mature enough for smooth adoption. SWC meets that bar. I still see some gaps in Oxc (minifier, supported plugins, and much more), but if it closes them and keeps a Babel-compatible API, we can revisit switching.

Anyway, our work integrating SWC is public via PRs to guide other adopters (mostly on babel-compiler package). If anyone wants to test a different tool, just open a PR replacing SWC references with the new tool and measure stability and performance. I think Oxc will give us problems nowadays at first glance, but maybe someone could fix those limits and prove it’s convenient.

We’re currently root causing an issue we’re having where after upgrading to 3.3, the mobile app is not loading / HMR is not pulling the latest from the server. I’ll report back when we know more.

EDIT:
Other findings:

1 Like

Can you confirm this issue didn’t occur in Meteor 3.2 but does after updating to 3.3?

Does it still occur with the legacy build stack, that is, if you remove modern or set it to false in package.json?

My native tests were ok. I will do extra verifications next week.

Apologies for not getting back. We found the issue was related to a mutation observer trying to attach document.body before it was available, which only happened on iOS! We fixed our bug and the app is working fine now.

We have occasional issues where images and other resources don’t load in the mobile apps, not sure if anyone else has experienced that with their apps.

We have been running 3.3 in production all day! Going smooth so far :slight_smile:

5 Likes

Amazing work Nacho. I’m glad you were to able to carry the torch and start working deeply with Meteor internals. :clap:

After years and years of work. Meteor is finally starting to catch its breath no longer bound by maintenance work but rather actively working to improve it. I’m super super glad that I get to witness this and even the upcoming work. :slight_smile:

I think it’d be great if you can present a talk about this work in the upcoming Meteor Impact. Because I feel lost a bit: bundler, transpiler, zodern:standard-minifier-js, reify, vite, swc, babel, rust?? What’s Meteor made of on a low level? How does it take your code and what stages does it go through till it reaches the deploy-able version? Does Meteor offer source-maps as a built-in feature now?? So many questions. I really hope your work is not only documented but also transferable to a future generation of core Meteor devs.

4 Likes

Thank you for this amazing release, I updated two codebases and indeed saw a 50% improvement in app startup time for development !
Looking forward to using meteor build to deploy and compare build times with the previous version!

4 Likes