---
outline:
  level: [2, 3]
---

# Rspack Bundler Integration

Rspack integration updates Meteor apps to modern bundling standards, offering faster builds, quicker reloads, smaller bundles, and a smoother development experience with built-in features and configurations.

In this setup, Rspack bundles your app code, while Meteor Bundler produces the final output, maintaining support for Meteor features like Atmosphere packages.

## Quick start

:::info
Starting with Meteor 3.4
:::

Add this Atmosphere package to your app:

``` bash
meteor add rspack@1.0.0-rc340.1
```

On first run, the package installs the required Rspack setup at the project level. It compiles your app code with Rspack to get the full benefit of this integration.

## Requirements

### Define the app’s entry points

Your app must define entry points for the Rspack integration to work. Entry points tell Rspack which files start execution on the client and server.

In Meteor, set this in `package.json`:

```json
{
  "meteor": {
    "mainModule": {
      "client": "client/main.js",
      "server": "server/main.js"
    }
  }
}
```

[Check out the Meteor migration guide](#entry-points) on describing entry points in your app.

### Remove nested imports

Your app code cannot use Meteor's specific nested imports (not to be confused with dynamic imports, which are supported). These are ES import statements placed inside conditions or functions.

``` javascript
if (condition) {
	import { a as b } from "./c"; // This is a nested import
	console.log(b);
}
```

[Refer to the Meteor migration guide](#nested-imports) to ensure your app code has no nested imports.

### Reserve a new build context

A Meteor-Rspack project reserves the folders `_build`, `{public,private}/build-assets`, and `{public,private}/build-chunks` to store intermediate and production bundles.

- `_build/*`. Contains the Rspack entry point, the intermediate Rspack app, and the overridden Meteor entry point that imports the Rspack app. It creates contexts for different environments, such as main or test modules, development and production, client and server. You can explore the contents to understand more.
- `build-assets/*`. Placed inside `public` (client) and `private` (server) folders. Stores assets built by Rspack that are packed into the final Meteor app.
- `build-chunks/*`. Placed inside `public` (client) folder. Stores chunks built by Rspack from code splitting (dynamic imports), CSS generation, and other chunk processing, to be packed into the final Meteor app.

The folders are prepared and cleared automatically and should not be modified directly, as they are autogenerated. They are added to `.gitignore` when using Git, and it’s recommended to exclude them from IDE analysis.

You don’t need to migrate your project for this, just ensure these folders are reserved for Meteor-Rspack. If you already use them for something else, move that content elsewhere.

If you want to customize the folder names, set these options in `package.json`:

``` json
{
  "meteor": {
    "buildContext": "build",
    "assetsContext": "assets",
    "chunksContext": "chunks"
  }
}
```

:::warning
Attempts were made to reuse the existing `.meteor/local` cache context instead of creating new build contexts, but this was not possible.

Use `.meteor/local` or folders that suggest internals or hidden content (e.g., starting with a dot). These affect debug visibility, file watching, final compilation, and inclusion in the Cordova bundle.
:::

### Replace build plugins

Meteor build plugins extend the Meteor bundler by letting you handle new file types and process them for the final app bundle. They’ve commonly handled HTML templating, style files for Less or SCSS, CoffeeScript, and more, since the system allows third-party customization.

However, Meteor’s build system solves the same problems as other bundlers, including Rspack. Build plugins are largely deprecated in favor of Rspack alternatives. Some plugins may still be useful if they don’t act directly on app files and do something Meteor-specific that can be preserved.

Among the compatible plugins:
- [`zodern:types`](https://packosphere.com/zodern/types). Still compatible, automatically providing Meteor types for core and community packages.

For others, please refer to the migration topics.
- [CSS, Less, and SCSS](#css-less-and-scss) (when using [`less`](https://packosphere.com/meteor/less), [`fourseven:scss`](https://packosphere.com/fourseven/scss))
- [Coffeescript](#coffeescript) (when using [`coffeescript`](https://packosphere.com/meteor/coffeescript))
- [Svelte](#svelte) (when using [`zodern:melte`](https://packosphere.com/zodern/melte))

You can still use these plugins to handle files inside Meteor atmosphere packages. You only need consider Rspack alternative when it’s required for your app code, which will usually be the case. An exception applies to HTML and CSS files: you can still use Meteor plugins touching these files if they are in the entry folder (e.g. `client/*.[html|css]` in most apps), or when using `modules` config as explained in the [Entry Points migration guide](#entry-points).

Please report your plugin usage as [GitHub issues](https://github.com/meteor/meteor/issues?q=sort%3Aupdated-desc+is%3Aissue+is%3Aopen) or [forum posts](https://forums.meteor.com/), so we can suggest an Rspack alternative or assess compatibility.

### Further migration

Refer to the [Migration Topics](#migration-topics) section for more details on other specific requirements your app might have.

## Custom `rspack.config.js`

Meteor-Rspack projects can be customized using the `rspack.config.js` file, which is automatically available when installing the `rspack` package. You can also use `rspack.config.mjs` or `rspack.config.cjs` if you prefer strict ESM or CommonJS formats.

This file defines dynamic configurations, so you return the config from a resolved function.

```javascript
const { defineConfig } = require('@meteorjs/rspack');
const { rspack } = require('@rspack/core');
const HtmlRspackPlugin = require('html-rspack-plugin');
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');

/**
 * Example: Using different plugins for client and server builds
 *
 * - For client: Load Lodash automatically with ProvidePlugin
 * - For server: Add Node.js polyfills with NodePolyfillPlugin
 * - For both: Add progress plugin
 */
module.exports = defineConfig(Meteor => {
  return {
    plugins: [
      Meteor.isClient && new rspack.ProvidePlugin({ _: 'lodash' }),
      Meteor.isServer && new NodePolyfillPlugin(),
      new rspack.ProgressPlugin()
    ].filter(Boolean),
  };
});
```

You can use flags to control the final configuration based on the environment. The available flags are passed in the `Meteor` parameter.

| Flag                | Type     | Description                                                                                                                       |
|---------------------| -------- |-----------------------------------------------------------------------------------------------------------------------------------|
| `isDevelopment`     | boolean  | True when running in development mode                                                                                             |
| `isProduction`      | boolean  | True when running in production mode                                                                                              |
| `isClient`          | boolean  | True when building or running client code                                                                                         |
| `isServer`          | boolean  | True when building or running server code                                                                                         |
| `isTest`            | boolean  | True when running in test mode                                                                                                    |
| `isDebug`           | boolean  | True when debug mode is enabled                                                                                                   |
| `isRun`             | boolean  | True when running the project with `meteor run`                                                                                   |
| `isBuild`           | boolean  | True when building the project with `meteor build`                                                                                |
| `swcConfigOptions`  | object   | Project-level SWC config available for reusing                                                                                    |
| `HtmlRspackPlugin`  | function | Custom HtmlRspackPlugin function for extending the config                                                                         |
| `compileWithMeteor` | function | Forces given npm deps ([Condition](https://rspack.rs/config/module#condition)[]) to be compiled by Meteor                         |
| `compileWithRspack` | function | Forces given npm deps ([Condition](https://rspack.rs/config/module#condition)[]) to be compiled by Rspack                         |
| `setCache`          | function | Enables or disables cache. Accepts true (persistent, default), false, or 'memory'                                                 |
| `splitVendorChunk`  | function | Splits vendor libraries so they are automatically served from a separate chunk                                                    |
| `extendSwcConfig`   | function | Extends the [SWC loader configuration](https://rspack.rs/guide/features/builtin-swc-loader#options) to apply only to the app code |
| `extendConfig`      | function | Extends the config by applying merged object configs                                                                                 |

Some configurations in the Rspack config are reserved for the Meteor-Rspack setup to work, such as Rspack options inside the `entry` and `output` objects. These will trigger warnings if modified. All other settings can be overridden, giving you the flexibility to make any setup compatible with the modern bundler.

If you want to see the final Rspack config applying your overrides, you can enable verbose mode in the modern build stack.

```json
"meteor": {
  "modern": {
    "verbose": true
  }
}
```

## Migration Topics

### Entry Points

Meteor entry points allow a modular, modern, bundler-compliant structure for your Meteor app. Modern bundlers define entry points where the evaluation and bootstrap of your app begin. In Meteor, you can set these for both the client and server, and optionally for tests.

``` json
{
  "meteor": {
    "mainModule": {
      "client": "client/main.js",
      "server": "server/main.js"
    },
    "testModule": "tests.js"
  }
}
```

Learn more in [“Modular application structure” in Meteor](https://docs.meteor.com/packages/modules.html#modular-application-structure).

Ensure your app defines these entry files with the correct paths where each module is expected to load. Organize your app so the loading order of modules is clear.

Defining entry points improves performance even with the Meteor bundler, as Meteor stops scanning and eagerly loading unnecessary files. For Meteor-Rspack integration, this is required, since it does not support automatic code discovery for efficiency.

In Meteor-Rspack integration, all app code is ignored by Meteor and handled by Rspack. By default, Meteor still processes eagerly CSS and HTML files in the entry folder (e.g. `client/*.[html|css]` in most apps).

If you need Meteor to handle CSS or HTML files outside the main entry folder, add them to the `modules` field. This field accepts an array of strings, each pointing to a file or folder.

``` json
{
  "meteor": {
    "modules": ["styles/main.css"]
  }
}
```

With this, Meteor will process these files, merge stylesheets, generate the final HTML, and support files a Meteor plugin may use, except for JS or script code now handled by Rspack. You can also process CSS and HTML files directly with Rspack using loaders from imports in your app code, as mentioned in ["CSS, Less and SCSS"](#css-less-and-scss) or ["HtmlRspackPlugin"](#htmlrspackplugin). If you prefer Meteor's loading approach, you can still rely on it.

Keep in mind: compiling styles with the Meteor compilers triggers Meteor HMR, which is slower than Rspack HMR. Migrating to compile styles with Rspack as part of the app code ensures the fastest HMR for style changes in development.

### Nested Imports

Nested imports are a feature of Meteor’s bundler, not supported in 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](https://github.com/benjamn/reify/tree/main) and works with Babel transpilation. SWC doesn't support them since they were never standardized.

:::warning
Don't confuse nested imports with standardized dynamic imports using `import()` in module blocks, these are supported.  
:::

Example with a nested import:

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

For background, see: [Why nested import](https://github.com/benjamn/reify/blob/main/WHY_NEST_IMPORTS.md).

To use Rspack, migrate your nested imports to a standard form. To identify and fix nested imports in your project, [use verbose mode in Meteor 3.3’s modern transpiler](./meteor-bundler-optimizations.md#optimize-swc-and-handle-fallbacks). Enable it with:

```json  
"meteor": {
  "modern": {
    "verbose": true
  }
}
```

When you run your app, `[Transpiler]` logs will show each file. Focus on `(app)` files that fail with messages like:

`Error: 'import' and 'export' cannot be used outside of module code`

![](https://forums.meteor.com/uploads/default/original/3X/e/1/e1a2c285284f82ab736bcada647d88bd4fa8d3ec.png)

**Fix nested imports by moving them to the top of the file, or by replacing them with require or dynamic import.**

You can skip migrating `(package)` code with nested imports. Meteor packages are still handled by the Meteor bundler in Rspack integration, but your app code is fully delegated to Rspack and must use standard syntax.

Nested imports isn’t standard, most modern projects use other deferred loading methods. Let Rspack handle files to speed builds and enable modern features. The choice is up to the devs. Some Meteor devs use nested imports for valid reasons. You can opt out of Rspack and still get build speed gains from Meteor bundler optimizations.

:::info
With Meteor–Rspack integration, you can still use nested imports if they are defined in Meteor Atmosphere packages. These will be accepted without any breaking changes.
:::

### Import Aliasses

An import alias is a shortcut that maps a custom name to a specific file path or directory, making imports shorter and easier to manage.

With Meteor-Rspack integration you can define aliases using the `resolve.alias` configuration in your `rspack.config.js`. For example:

``` javascript
export default defineConfig(Meteor => {  
  return {  
    resolve: {  
      alias: {  
        '@ui': '/imports/ui',  
        '@api': '/imports/api',  
      },  
    };
}
```

Learn more in the [Rspack alias docs](https://rspack.rs/config/resolve#resolvealias).

If you use TypeScript, also update your `tsconfig.json` to support IDE autocompletion and ESLint resolution:

```json
{  
	"compilerOptions": {
		"baseUrl": ".",
		"paths": { 
		  "@ui/*": ["imports/ui/*"],  
		  "@api/*": ["imports/api/*"]
		}
	}
}
```

You can also [configure aliases at the transpiler level](meteor-bundler-optimizations.md#import-aliases). For SWC, enable it through the `.swcrc` file (note that SWC aliases have some limitations when resolving files or `node_modules`). If you use Babel, you can rely on the [module-resolver plugin](https://www.npmjs.com/package/babel-plugin-module-resolver).

### React

Meteor-Rspack supports React projects out of the box. Just install the `rspack` package and run your app. Meteor will detect it and automatically add the needed Rspack dependencies, including `react-refresh` for a full development experience.

Learn more in the [official Rspack and React integration guide](https://rspack.rs/guide/tech/react).

> Use `meteor create --react` to start with a preconfigured Rspack React app.

### React Compiler

Meteor-Rspack supports React Compiler. To enable it, install the required dependencies and add the new configuration to Meteor’s `rspack.config.js` file.

Learn more in the [official Rspack and React Compiler integration guide](https://rspack.rs/guide/tech/react#react-compiler).

### Vue

Meteor-Rspack supports Vue projects out of the box. To enable it, install the required dependencies and add the new configuration to Meteor’s `rspack.config.js` file.

Learn more in the [official Rspack and Vue integration guide](https://rspack.rs/guide/tech/vue).

> Use `meteor create --vue` to start with a preconfigured Rspack Vue app.

:::warning
Previous official support in the Meteor bundler was through [jorgenvatle:vite](https://github.com/JorgenVatle/meteor-vite).

With Meteor-Rspack integration, you no longer need vite-related packages, so you should remove them from your project.
:::

### Solid

Meteor-Rspack supports Solid projects out of the box. To enable it, install the required dependencies and add the new configuration to Meteor’s `rspack.config.js` file.

Learn more in the [official Rspack and Solid integration guide](https://rspack.rs/guide/tech/solid).

> Use `meteor create --solid` to start with a preconfigured Rspack Solid app.

:::warning
Previous official support in the Meteor bundler was through [jorgenvatle:vite](https://github.com/JorgenVatle/meteor-vite).

With Meteor-Rspack integration, you no longer need vite-related packages, so you should remove them from your project.
:::

### Coffeescript

Meteor-Rspack supports CoffeeScript projects out of the box. To enable it, install the needed dependencies and add the configuration to Meteor’s rspack.config.js.

[See the official Webpack and CoffeeScript integration guide](https://webpack.js.org/loaders/coffee-loader/#getting-started). Since Rspack is based on Webpack, the same setup applies.

If you want to use SWC with CoffeeScript, combine `swc-loader` with `coffee-loader`.

```bash
npm install --save-dev coffeescript swc-loader coffee-loader
```

In your `rspack.config.js` you would add something like:

``` javascript
export default defineConfig(Meteor => {
  return {
    module: {
      rules: [
        {
          test: /\.coffee$/i,
          use: [
            {
              loader: 'swc-loader',
              // perserve SWC config in the Meteor project level
              options: Meteor.swcConfigOptions,
            },
            {
              loader: 'coffee-loader',
            },
          ],
        },
      ],
    },
    resolve: {
      extensions: ['.coffee'],
    },
  };
});
```

> Use `meteor create --coffeescript` to start with a preconfigured Rspack Coffeescript app.

### Svelte

Meteor-Rspack supports Svelte projects out of the box. To enable it, install the required dependencies and add the new configuration to Meteor’s `rspack.config.js` file.

Learn more in the [official Rspack and Svelte integration guide](https://rspack.rs/guide/tech/svelte).

> Use `meteor create --svelte` to start with a preconfigured Rspack Svelte app.

:::warning
Official Svelte support in the Meteor bundler was via [zodern:melte](https://github.com/zodern/melte).

With the Meteor–Rspack integration, `zodern:melte` no longer works. Use the official Rspack Svelte integration instead. If you relied on melte-specific features like `$` or `$m`, you may need to update parts of your code. Create your own abstractions or migrate them to standard npm package.
:::

### CSS

Meteor-Rspack comes with built-in CSS support. You can import any CSS file into your code, and it will be processed and included in your HTML skeleton automatically. In addition, any CSS file placed in the same folder as your Meteor entry point will be processed and added as global styles without the need for explicit imports.

### Less

Less support is available in Meteor-Rspack. You need to replace the existing [Meteor `less` package](https://github.com/meteor/meteor/tree/master/packages/non-core/less) or similar with the Rspack configuration.

#### Install

``` bash
npm i -D less less-loader
```

#### Config

``` js
module.exports = defineConfig(Meteor => ({
  module: {
    rules: [
      {
        test: /\.less$/,
        use: [
          {
            loader: 'less-loader',
          },
        ],
        type: 'css/auto',
      },
    ],
  },
}));
```

For details, check [the official Rspack and Less guide](https://rspack.rs/guide/tech/css#less).

### SCSS

SCSS support is available in Meteor-Rspack. You need to replace the existing Meteor [`fourseven:scss`package](https://github.com/Meteor-Community-Packages/meteor-scss) or similar with the Rspack configuration.

#### Install

``` bash
npm i -D sass-embedded sass-loader
```

#### Config

``` js
module.exports = defineConfig(Meteor => ({
  module: {
    rules: [
      {
        test: /\.scss$/i,
        use: [
          {
            loader: 'sass-loader',
            options: {
              api: 'modern-compiler',
              implementation: require.resolve('sass-embedded'),
            },
          },
        ],
        type: 'css/auto',
      },
    ],
  },
}));
```

For more details, check [the official Rspack and SCSS guide](https://rspack.rs/guide/tech/css#sass).

### Tailwind & PostCSS

Meteor-Rspack supports Tailwind projects out of the box. For details, check [the official Rspack and Tailwind guide](https://tailwindcss.com/docs/installation/framework-guides/rspack/react).

> Use `meteor create --tailwind` to start with a preconfigured Rspack Tailwind app.

### Babel

Meteor-Rspack supports Babel projects as an alternative to default SWC.

> Use `meteor create --babel` to start with a preconfigured Rspack Babel app.

Using Babel will increase build times. Prefer SWC. If you need Babel for specific files, limit Babel to those files, or use a hybrid with SWC and Babel. For example, [enabling React Compiler is available only via Babel using module rules](https://rspack.rs/guide/tech/react#react-compiler).

### Angular

Meteor-Rspack supports Angular projects. It’s experimental, but it already works in development, production, and with Meteor testing. We still need to refine it and add the Angular test suite and other details.

> Use `meteor create --angular` to start with a preconfigured Rspack Angular app.

### HtmlRspackPlugin

Meteor-Rspack includes its own HtmlRspackPlugin, enabled by default to attach chunks and assets to the HTML skeleton. Meteor then uses this HTML to generate the final index file.

If you want to customize HtmlRspackPlugin, add it to your `rspack.config.js` file:

```javascript
export default defineConfig(Meteor => {
  return {
    plugins: [
      Meteor.HtmlRspackPlugin({
        meta: {
          // Will generate: <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
          viewport: 'width=device-width, initial-scale=1, shrink-to-fit=no',
          // Will generate: <meta name="theme-color" content="#4285f4">
          'theme-color': '#4285f4',
          // Will generate:  <meta http-equiv="Content-Security-Policy" content="default-src https:">
          'Content-Security-Policy': {
            'http-equiv': 'Content-Security-Policy',
            content: 'default-src https:',
          },
        },
      }),
    ],
  };
});
```

This example adds meta tags to the HTML. For more options, see the [official Rspack and HTML integration guide](https://rspack.rs/plugins/rspack/html-rspack-plugin).

:::warning
You can still use HTML files near your Meteor client entry point to define customizations (for example, `./client/main.html` will generate correctly and apply the contents you add).
:::

### Delegating Dependencies to Rspack

**Meteor.compileWithRspack(deps: [Condition](https://rspack.rs/config/module#condition)[], options?: [SwcLoaderOptions](https://v0.rspack.dev/guide/features/builtin-swc-loader#options))**

This helper forces **Rspack (via SWC and custom loaders)** to parse and transpile specific npm dependencies during the build.

Use this when a dependency:

* Uses modern syntax (ESM, TypeScript, etc.)
* Lives inside a monorepo and isn’t precompiled,
* Needs to be reprocessed according to your SWC config

```js
const { defineConfig } = require('@meteorjs/rspack');

module.exports = defineConfig(Meteor => ({
  // Force-compile modern or local packages via SWC
  ...Meteor.compileWithRspack(['grubba-rpc']),
  // Force-compile zod with ES5 target
  ...Meteor.compileWithRspack(['zod'], { jsc: { target: 'es5' } }),
}));
```

### Delegating Dependencies to Meteor

**Meteor.compileWithMeteor(deps: [Condition](https://rspack.rs/config/module#condition)[])**

This helper marks specific npm dependencies as externals, meaning they are skipped by Rspack and instead handled by Meteor/Node at runtime.

Use this when a dependency:

* Contains native or binary code (e.g. sharp)
* Belongs to a Meteor Atmosphere package that maintains internal state
* Comes precompiled or is large enough to run better outside the bundle

```js
const { defineConfig } = require('@meteorjs/rspack');

module.exports = defineConfig(Meteor => ({
  // Exclude native modules from the bundle (use Meteor runtime)
  ...(Meteor.isServer ? Meteor.compileWithMeteor(['sharp']) : {}),
}));
```

---

A reported use case for this is with the `thread-stream` dependency, a transitive dependency of Mongo packages. If you get this error:

``` shell
Error: Cannot find module '/_build/main-dev/lib/worker.js'
```

It means the worker can’t be found. Let the Node/Meteor ecosystem handle this dependency so it can automatically pick the right worker.

``` js
module.exports = defineConfig((Meteor) => {
  return {
     // ..
    ...Meteor.compileWithMeteor([
      // ..
      "thread-stream"
    ]),
  };
});
```

More info in [this forum post](https://forums.meteor.com/t/new-3-4-beta-12-release-faster-builds-smaller-bundles-and-modern-setups-with-the-rspack-integration/64124/94).

### Cache

Meteor cache remains active and continues to handle Atmosphere packages and intermediate builds. There’s an additional cache layer managed by Rspack to speed up rebuilds for your app code.

This Rspack cache is enabled by default in persistent mode. If you [encounter issues](https://github.com/web-infra-dev/rspack/issues/11804) or prefer to disable it, you can do so in your `rspack.config.js` using the helper:

```json
const { defineConfig } = require('@meteorjs/rspack');
const { rspack } = require('@rspack/core');
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');

module.exports = defineConfig(Meteor => ({
  // Disable cache, or use 'memory' to switch to in-memory cache
  ...Meteor.setCache(false),
}));


```

This helper provide a shortcut to apply the needed Rspack configuration and safely override defaults, so you don’t have to handle it manually.

### Split Vendor Chunk

When using dynamic imports (`import()`), you might unintentionally include libraries like React, Mantine, or date utilities in multiple async chunks. To avoid this, it's best to define a stable `vendor` chunk for shared dependencies.

We provide a helper to easily configure this in your `rspack.config.js`:

```js
const { defineConfig } = require('@meteorjs/rspack');

module.exports = defineConfig(Meteor => ({
  // Split vendor chunk
  ...Meteor.splitVendorChunk(),
}));
```

This is a quick configuration for split chunks all within `node_modules` as a `vendor` chunk, if you need more control you can use the [official Rspack split chunks integration guide](https://rspack.rs/guide/optimization/code-splitting#splitchunksplugin).

### Extending SWC config

Rspack uses the SWC configuration to transpile your app code. By default, it inherits any settings from the `.swcrc` file, which also [impacts how Meteor transpiles core and package code](meteor-bundler-optimizations.md#custom-swcrc).

If you want a configuration to apply only to your app code, you can extend the SWC setup using the `Meteor.extendSwcConfig` helper:

```js
const { defineConfig } = require('@meteorjs/rspack');

module.exports = defineConfig(Meteor => ({
  // Extend SWC config
  ...Meteor.extendSwcConfig({
    jsc: {
      parser: {
        syntax: 'typescript',
      },
    },
  }),
}));
```

### Interop for Default Imports

Meteor originally handled default imports from CommonJS modules automatically. This allowed you to write:
```js
import all from 'some-commonjs-lib';
```
even when the library used module.exports = ... under the hood.

With Rspack and SWC, that behavior no longer happens by default, you now need to use:

```js
import * as all from 'some-commonjs-lib';
```
unless you re-enable interop support.

If you prefer to restore Meteor’s earlier behavior, you can configure SWC like this in your `.swcrc`:

``` json
{
  "jsx": { ... },
  "module": {
    "type": "commonjs",
    "noInterop": false,
    "importInterop": "node"
  }
}
```

* `"type": "commonjs"` tells SWC to emit CommonJS output (require, module.exports, etc.).
* `"noInterop": false` injects interop helpers so default imports from CommonJS modules work properly.
* `"importInterop": "node"` aligns behavior with how Node handles ESM and CJS interop.

This configuration ensures compatibility for mixed module imports, allowing default imports from CommonJS packages to behave as the old Meteor-style import behavior.

However, enabling this globally means SWC will convert all `import`/`export` statements into `require` calls. Rspack then loses access to ES module boundaries, preventing optimizations like tree-shaking and static analysis.

In short, this option trades runtime compatibility for build-time optimization.

We recommend migrating away from this pattern and using standard named or namespace imports (`import { ... }` or `import * as`...) for long-term compatibility and better build performance.

### Cache

Meteor cache remains active and continues to handle Atmosphere packages and intermediate builds. There’s an additional cache layer managed by Rspack to speed up rebuilds for your app code.

This Rspack cache is enabled by default in persistent mode. If you [encounter issues](https://github.com/web-infra-dev/rspack/issues/11804) or prefer to disable it, you can do so in your `rspack.config.js` using the helper:

```json
const { defineConfig } = require('@meteorjs/rspack');
const { rspack } = require('@rspack/core');
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');

module.exports = defineConfig(Meteor => ({
  // Disable cache, or use 'memory' to switch to in-memory cache
  ...Meteor.setCache(false),
}));


```

This helper provide a shortcut to apply the needed Rspack configuration and safely override defaults, so you don’t have to handle it manually.

### Service Worker

Rspack lets you use standard plugins to manage Service Workers, such as Workbox, so you don’t need to maintain your own setup. You can follow the Webpack guide for integrating Workbox with [`workbox-webpack-plugin`](https://developer.chrome.com/docs/workbox/modules/workbox-webpack-plugin) (it should be compatible), or try the Rspack-specific version [`@aaroon/workbox-rspack-plugin`](https://github.com/Clarkkkk/workbox-rspack-plugin).

Whether you use a managed tool or a custom setup, ensure that only the Rspack dev server endpoints are treated as network-only for proper development. Otherwise, you may end up with infinite reload loops that only clear after removing the Service Worker. Skip caching of `__rspack__` endpoints.

If you use a custom implementation in your `sw.js`, intercept fetch requests to ignore Rspack contexts like this:

```js
self.addEventListener('fetch', (event) => {
  const { request } = event;
  const url = new URL(request.url);

  const sameOrigin = url.origin === self.location.origin;
  // Skip Rspack  devServer
  if (sameOrigin && url.pathname.includes('/__rspack__/')) {
    // Never cache ignores and hot updates; hit the network every time
    event.respondWith(fetch(event.request, { cache: 'no-store' }));
    return;
  }

  // ...
});
```

When using Workbox, the equivalent with `GenerateSW` might look like this:

```js
new GenerateSW({
  // ...
  runtimeCaching: [
    {
      urlPattern: ({ url }) => url.pathname.includes('/__rspack__/'),
      handler: 'NetworkOnly',
    },
    // ...
  ],
  // ...
})
```

### Dev Server

You can customize the Rspack dev server much like you would when using meteor run. Any [devServer option listed in the official Rspack guide](https://rspack.rs/config/dev-server) can be applied in your app’s [`rspack.config.js`](./rspack-bundler-integration.md#custom-rspackconfigjs).

The only exception is the port configuration. To set a specific port for the Rspack dev server, use the `RSPACK_DEVSERVER_PORT` environment variable:

```bash
# Assign a specific port for the Rspack dev server
RSPACK_DEVSERVER_PORT=3232 meteor run
```

The reason is that the Rspack dev server is handled by the Meteor so it can make both dev server works together, and the info of the port needs to be properly shared via the env.

### Disable Plugins

Meteor allows disabling Rspack plugins that are added by default or through presets. This is useful when troubleshooting build issues or replacing a plugin with a custom implementation.

Plugins are matched by name (constructor name) and can be specified as a string, RegExp, a predicate function, or an array of all.

``` js
const { defineConfig } = require('@meteorjs/rspack');

module.exports = defineConfig(Meteor => ({
    // Disable one or more Rspack plugins
    ...Meteor.disablePlugins([
        'DefinePlugin',
        /Html/i,
        p => p?.constructor?.name === 'CustomConsoleLogPlugin',
    ]),
}));
```

## Benefits

Meteor–Rspack integration sends your app code to Rspack to use modern bundler features. Meteor then uses Rspack’s output to handle Meteor-specific tasks (like Atmosphere package compilation) and create the final bundle.

This implementation preserves Rspack HMR for faster reloads.

With `Rspack` compiling your app you get:

- Standard code splitting via HTTP
- Tree shaking to significantly reduce bundle size
- Support for ESM packages, including npm packages with export fields
- Bundler plugins for build hooks, alternative compilers, file resolvers, image optimizations, PWAs with service workers, and more
- Advanced analysis tools to track code impact and guide later optimizations
- More features coming soon

With `Meteor` you get:

- Core API with reactive and non-reactive endpoints (DDP, Express)
- Built-in Mongo/Minimongo API for isomorphic business logic
- Third-party packages for faster development
- Multiplatform development support
- All other Meteor strengths

## Limitations

### No Blaze HMR support

Blaze templates build correctly with Rspack, but Meteor’s Hot Module Replacement (HMR) for Blaze is not available. Normally, Blaze HMR updates the UI instantly without reloading the whole page, keeping the current state (like form inputs or scroll position).

With Rspack, Blaze changes will instead trigger a full live reload. This reload is still very fast thanks to Rspack’s reduced rebuild time (about 97% reduction), but the page state will reset after each change. The limitation exists because Blaze’s HMR relies on Meteor’s internal mechanism, which is not yet compatible with Rspack.

This limitation only applies to Blaze. Any other modern project will work with HMR as soon as Rspack natively supports it, which is likely if it’s a modern library.

## Troubleshotting

If you run into issues, try `meteor reset` or delete the `.meteor/local` and `_build` folders in the project root.

For help or to report issues, post on [GitHub](https://github.com/meteor/meteor/issues) or the [Meteor forums](https://forums.meteor.com). We’re focused on making Meteor faster and your feedback helps.

You can compare performance before and after enabling `modern` by running [`meteor profile`](../../cli/index.md#meteorprofile). Share your results to show progress to others.
