Pnpm support in Meteor 3.4+ with Rspack

Repository example:

For a long time, the Meteor community has discussed pnpm support and the limitations of the legacy Meteor bundler around symlinks, workspace layouts, and dependency resolution. With Meteor 3.4+ and the move into the modern build stack through Rspack integration, many of these limitations are no longer blockers.

Why? Because application module resolution is now delegated to a modern bundler ecosystem through Rspack, while Meteor focuses on its own runtime specifics like Atmosphere packages. This allows Meteor applications to adopt modern package manager strategies such as:

  • pnpm workspaces
  • monorepos
  • shared local packages
  • symlink-based dependency layouts

To validate this properly, I first added E2E coverage in Meteor core:

And then created a public example repository for everybody to try:

One important detail at the moment is that when using pnpm, Meteor automatic npm installation should be disabled:

{
  "meteor": {
    "autoInstallDeps": false
  }
}

This is necessary because pnpm itself owns dependency installation and workspace linking. Otherwise Meteor’s current Rspack auto-install management may interfere with the workspace behavior.

Besides that, the setup is essentially the same as any standard Meteor + Rspack application.

Rspack integration docs:


I still want to improve autoInstallDeps behavior for pnpm workspace scenarios in future Meteor versions. We could also officially expose a pnpm skeleton through meteor create , add it as a --example , and document pnpm workflows more directly.

But sincerely, this is no longer a blocker to start using pnpm properly with Meteor projects today.

Anybody using Meteor 3.4+ with Rspack integration should now be able to adopt pnpm-based workflows without needing custom hacks around the old bundler limitations.

This is just another example of what the modern build stack migration unlocked for the Meteor ecosystem.

10 Likes

Did you test npm packages with transitive dependencies with your skeleton?

I think there will be issues.

Other than that, I love this direction

Hey, thanks for the report!

I just pushed a fix. The root cause was resolve.symlinks: false in the Rspack config of the pnpm monorepo skeleton. That setting is a small optimization that only works when your workspace packages don’t bring their own npm dependencies, which is an oversimplified setup. Removing it restores resolution for transitive dependencies that pnpm keeps inside its virtual store (node_modules/.pnpm/), which is where most real-world cases break.

Could you give it a try and let me know how it goes? Happy to look into any edge case I might have missed.

Worth noting that this is still fully compatible with current Meteor 3.4+, no new Meteor 3.x release needed.

2 Likes

Pnpm support has been improved in the latest Meteor 3.6-beta.0. This beta is important for everybody interested in understanding more about how pnpm integration works in the new Meteor-Rspack era.

Pnpm is already available for Meteor 3.4+, and there is an example in the first post about how to use it.

But as part of Meteor 3.6, we have ensured there is a skeleton available directly through meteor create:

meteor create --release 3.6-beta.0 --pnpm my-workspace

Besides, the automatic NPM dependency installation system is now aware of workspaces, so the process has been optimized to be workspace-aware and work similarly to a standalone Meteor app. Always with meteor.autoInstallDeps to false at package.json to manage them yourself.

Make sure to provide your feedback on this so that we can deliver an official Meteor 3.6 release with all the edges stable.

1 Like

@nachocodoner

Is it possible to have nobuild with Meteor 3 ?

So that when I start with Meteor with node main.js it would run Javascript code from current locations. And not copy all those 40k files to .build/bundle .

1 Like

Meteor 3 WeKan nobuild

With new loader, starts from current location of original source code, npm_modules and ~/.meteor .

git clone https://github.com/wekan/wekan

cd wekan

./build.sh

==================== WeKan ====================
1) Setup	       3) Dev server nobuild  5) Docker		     7) CLI commands	    9) Quit
2) Dev server	       4) Tests		      6) Releases	     8) Tools
Please enter your choice: 3

== Dev server nobuild ==
1) localhost:3000		       4) CURRENT-IP:3000		      7) CUSTOM PORT + SUBDOMAIN
2) localhost:3000 + trace warnings     5) CURRENT-IP:3000 + MONGO_URL 27019   8) Kill all dev servers
3) localhost:3000 + bundle visualizer  6) CUSTOM-IP:PORT		      9) Back
Please enter your choice: 1

# Both menus share their URL/port prompts and environment.
DEV_COMMAND=(meteor run)
if [ "$cat" = "Dev server nobuild" ]; then
    DEV_COMMAND=(node "$WEKAN_DIR/scripts/dev-source/start.cjs")
fi

Nice work, @xet7, and thanks for exploring this. Avoiding unnecessary copying and generated files is definitely worth pursuing if it makes working on WeKan faster and lighter.

It would help to explain a bit more what “no-build” actually means here: what work is avoided, what still needs compilation or preparation, and what happens at startup or after a source change. From what I understand, it avoids the conventional application bundle, but source transformation and Meteor package preparation still happen differently, mostly in memory. That distinction would help everyone understand the tradeoffs.

My main question is whether we can bring those benefits into the existing Meteor pipeline rather than maintain another execution path alongside it.

Rspack is about more than producing a bundle. It gives us a shared foundation for modern JS/TS, React Compiler, CSS tooling, assets, caching, HMR and production optimizations. A source-loaded approach can support these too, but someone still needs to integrate and maintain all that behavior. Offloading many of those responsibilities to a tool like Rspack makes a lot of sense, and is broadly how modern frameworks have evolved: the build step is one part of a larger development pipeline, not necessarily something that has to mean heavy or unnecessary work. I would prefer improving that shared tooling rather than duplicating those responsibilities.

That does not mean keeping every intermediate step we have today. We will keep improving the core integration as we get more real-world feedback and identify opportunities to simplify it, reduce unnecessary work or disk output, and make the overall pipeline lighter.

This is also why contributions from projects like WeKan would be so valuable. I would really encourage bringing reusable improvements directly as Meteor PRs. It does not need to be the whole no-build runtime at once: removing a copy step, reusing package preparation, reducing intermediate output, or improving the Rspack handoff could each be useful on their own.

It would also be useful to compare clean startup, cached startup, first usable page and edit-to-visible-result time, so we can see where the gains actually come from.

Maybe this deserves a separate forum thread too. This has grown beyond pnpm support into a broader discussion around source loading, caching, build output and simplifying Meteor’s development pipeline. It could be a good place to document the experiment, collect measurements and track possible core improvements.

For me, the goal is not to defend having a build step. It is to do only the work that is really needed while keeping Meteor maintainable and flexible.

1 Like