> For AI agents: the complete documentation index is available at https://rspack.rs/llms.txt, the full documentation bundle is available at https://rspack.rs/llms-full.txt.

# Barrel file optimization

Rspack's barrel file optimization, also known as lazy barrel, improves build performance by skipping the building of unused re-export modules in side-effect-free barrel files.

## What is a barrel file

A barrel file is a module that re-exports functionality from other modules, commonly used to create a cleaner public API for a package or directory:

```js title="components/index.js (barrel file)"
export { Button } from './Button';
export { Card } from './Card';
export { Modal } from './Modal';
export { Tabs } from './Tabs';
// ... dozens more components
```

This allows consumers to import from a single entry point:

```js
import { Button, Card } from './components';
```

However, barrel files can cause performance issues because bundlers traditionally need to build all re-exported modules, even if only a few are actually used.

## How lazy barrel works

When lazy barrel optimization is enabled (which it is by default), Rspack will skip building unused re-export modules in side-effect-free barrel files until they're actually needed.

### Example

```js title="src/index.js"
import { Button } from './components';

console.log(Button);
```

```js title="src/components/index.js (barrel file)"
export { Button } from './Button';
export { Card } from './Card';
export { Modal } from './Modal';
// ... many more exports
```

With lazy barrel optimization:

- ✅ Only `Button.js` is built
- ✅ `Card.js`, `Modal.js`, and other unused modules are not built
- ✅ Faster build times, especially in large projects

Without lazy barrel optimization:

- ❌ All modules (`Button.js`, `Card.js`, `Modal.js`, etc.) would be built
- ❌ Slower build times, even though most modules are unused

## Requirements

For lazy barrel optimization to work, barrel files must be side-effect-free. A module is considered side-effect-free when it meets one of the following conditions:

1. Package-level declaration: The `package.json` file declares `"sideEffects": false`

   ```json title="package.json"
   {
     "name": "my-components",
     "sideEffects": false
   }
   ```

   See [Side effects analysis](https://rspack.rs/guide/optimization/tree-shaking.md#side-effects-analysis) for more details.

2. Module-level declaration: Modules explicitly marked as side-effect-free through [`rules[].sideEffects`](https://rspack.rs/config/module-rules.md#rulessideeffects)

   ```js title="rspack.config.mjs"
   export default {
     module: {
       rules: [
         {
           test: /\.js$/,
           sideEffects: false,
         },
       ],
     },
   };
   ```

## Supported export patterns

Lazy barrel optimization works with the following export patterns:

### Named re-exports

```js
export { Component } from './Component';
export { utils } from './utils';
```

### Namespace re-exports

```js
export * as Components from './components';
```

### Named exports from local declarations

```js
export const API_URL = 'https://api.example.com';
export function helper() {
  /* ... */
}
```

### Default exports

```js
export default function App() {
  /* ... */
}
// The name is "default" for lazy barrel purposes
```

## Star re-exports (`export *`)

Star re-exports (`export * from "./module"`) are not fully optimized by lazy barrel and remain a performance concern.

```js title="components/index.js (barrel file with star re-exports)"
export * from './Button';
export * from './Card';
export * from './Modal';
export const API_VERSION = '1.0';
```

### When lazy barrel can still optimize

Lazy barrel will skip building star re-exports only when:

1. The barrel file is side-effect-free, and
2. The imported specifier is found in the barrel's named exports

Example scenario where optimization works:

```js title="src/index.js"
import { API_VERSION } from './components';
console.log(API_VERSION);
```

In this case:

- ✅ `API_VERSION` is a named export in the barrel file itself
- ✅ Rspack can optimize this—no modules are built (`Button.js`, `Card.js`, `Modal.js` are all skipped)

Example scenario where optimization fails:

```js title="src/index.js"
import { Button } from './components';
console.log(Button);
```

In this case:

- ❌ `Button` is not a named export in the barrel file—it's from `export * from './Button'`
- ❌ Rspack must build `./Button.js` and potentially all other star re-exports to find which module exports `Button`

## FAQ

### 1. Does lazy barrel support CommonJS?

Currently, lazy barrel only supports ES modules (ESM). CommonJS support would require improvements to Rspack's CommonJS tree shaking, particularly the static analysis capabilities. Support for CommonJS may be added in a future release.

### 2. Can Rspack automatically detect side-effect-free modules?

Rspack can analyze whether a module has side effects (this capability is already used by [`optimization.sideEffects`](https://rspack.rs/config/optimization.md#optimizationsideeffects) for tree shaking). However, this analysis requires checking the module's dependencies recursively—a module is only truly side-effect-free when all its dependencies are also side-effect-free.

During the make phase, dependencies must be built before their side effects can be analyzed. Lazy barrel is specifically designed to avoid building those dependencies. Therefore, it relies on explicit markers like `"sideEffects": false` in `package.json` or `rules[].sideEffects`, which don't require dependency checking since they declare the entire package or matched modules as side-effect-free.

## Related optimization: skipping side-effect-only import builds

This optimization is not a part of lazy barrel, but it was inspired by lazy barrel, so it is documented here separately.

For the following ESM import that is only used to trigger side effects:

```js title="src/index.js"
import './module';
```

If `./module` has already been marked as side-effect-free through `"sideEffects": false` in `package.json`, or [`rules[].sideEffects`](https://rspack.rs/config/module-rules.md#rulessideeffects), Rspack will directly skip building this module during the make phase.

This kind of `import './module'` would be removed later by side-effects optimization anyway, so continuing to run loader, parser, and build would not affect the final output and would only add overhead to the make phase. Therefore, Rspack determines its side effects early during the make phase, and if it is side-effect-free, directly skips building it.

## Further reading

- [RFC: Lazy make for reexports in side effects free barrel file](https://github.com/web-infra-dev/rspack/discussions/11273)
- [Tree shaking](https://rspack.rs/guide/optimization/tree-shaking.md)
- [Side effects analysis](https://rspack.rs/guide/optimization/tree-shaking.md#side-effects-analysis)
