For AI agents: the complete documentation index is available at https://rstest.rs/llms.txt, the full documentation bundle is available at https://rstest.rs/llms-full.txt, and this page is available as Markdown at https://rstest.rs/guide/advanced/side-effects.md.
close
  • English
  • Module side effects

    Rstest bundles tests with Rspack, which can skip unused modules during the build to reduce the dependencies that need to be built and executed. Optimizations such as lazyBarrel speed up test startup, provided the skipped modules contain no required initialization code.

    The sideEffects declaration tells build tools which modules can be skipped. This page explains its relationship to module side effects and lazyBarrel, and how to retain initialization that your tests need.

    What counts as a side effect

    A side effect here is a change to external state when a module loads, beyond providing exported values. For example:

    test/register-mocks.ts
    import { rs } from '@rstest/core';
    
    rs.mock('../src/api', () => ({
      fetchUser: () => ({ name: 'Alice' }),
    }));

    This module exports nothing, but evaluating it registers a mock. Other common side effects include modifying globals, installing polyfills, and registering event listeners.

    The following bare import runs the module's initialization code:

    test/user.test.ts
    import './register-mocks';

    How side-effect declarations affect module execution

    Setting sideEffects: false in package.json tells the bundler that files in the package can be skipped when their exports are unused.

    package.json
    {
      "name": "my-project",
      "sideEffects": false
    }

    When this declaration applies to the registration module and the relevant optimizations are enabled, even an explicit import './register-mocks' can be removed. Build tools trust the sideEffects declaration; registration code in a file does not guarantee that the file will be retained.

    See Rspack's tree shaking documentation.

    Faster test builds with barrel optimization

    Rstest sends test files and their dependencies through Rspack's build pipeline, so it benefits from Rspack's default lazyBarrel optimization without switching to production mode. Rstest does not automatically mark application code as side-effect-free: the optimization relies on declarations provided by the project or dependency package.

    A barrel file is an entry point that re-exports other modules. Tests often use only a small subset of its exports:

    src/utils/index.ts
    export { sum } from './sum';
    export { formatDate } from './format-date';
    test/sum.test.ts
    import { expect, test } from '@rstest/core';
    import { sum } from '../src/utils';
    
    test('sum', () => {
      expect(sum(1, 2)).toBe(3);
    });

    When src/utils/index.ts is declared side-effect-free and no other module in the build graph uses formatDate, Rspack can follow the sum re-export to build sum.ts and skip the format-date.ts branch.

    Build workWhen all re-export branches must be processedWith lazyBarrel
    Loader transforms, parsing, and dependency builds for sum.tsRequiredRequired
    Transforms, parsing, and builds for format-date.ts and its exclusive dependenciesRequiredCan be skipped

    The benefit goes beyond removing code from the final bundle: unrelated branches can avoid subsequent build processing altogether. For entry points that export many components or utilities, using only a few exports in tests can reduce cold-start build work. Watch rebuilds also process modules according to dependency needs; this is a separate optimization from caching previously built results.

    If another test or module uses formatDate, that branch still needs to be built. With export *, Rspack may need to build more modules to determine where an export comes from, limiting the benefit.

    sideEffects declares module behavior; lazyBarrel uses that declaration to optimize builds. It relies on explicit package or module-rule declarations to skip branches before building their dependencies.

    An incorrect sideEffects: false declaration can therefore drop required initialization. Declare side effects for those modules and any necessary intermediate importers.

    Rspack can also skip building side-effect-free bare imports such as import './register-mocks'. This is a separate related optimization, so initialization can be skipped even without a barrel file.

    See Rspack's barrel file optimization guide.

    Declare modules with side effects

    Only adjust these declarations when initialization modules have been incorrectly marked as side-effect-free. Omitting sideEffects is not equivalent to setting sideEffects: false. Using Rstest or putting registration code in a separate file does not by itself require additional side-effect configuration.

    Declare side effects for a package

    If your project declares sideEffects: false but some files need to run initialization, replace it with an array listing those files:

    package.json
    {
      "name": "my-project",
      "sideEffects": ["./src/polyfills.ts", "./test/support/**"]
    }

    Paths are relative to this package.json. Files outside the array are still treated as side-effect-free. When editing an existing array, retain any other files that still have side effects.

    With the array declaration above, if initialization passes through several imports, such as test → bootstrap → helper → register-mocks, make sure intermediate modules cannot be skipped either. Marking only the final registration module may not preserve the whole import chain. Keeping these files under test/support and declaring that directory is one maintainable approach.

    Declare side effects in Rstest config

    To override side-effect-free declarations only in the test build, use tools.rspack to set sideEffects: true for a specific directory:

    rstest.config.ts
    import { defineConfig } from '@rstest/core';
    
    export default defineConfig({
      tools: {
        rspack: {
          module: {
            rules: [
              {
                test: /[\\/]test[\\/]support[\\/]/,
                sideEffects: true,
              },
            ],
          },
        },
      },
    });

    The rule matches the imported module's path. sideEffects: true preserves its side effects; false allows it to be skipped. This setting does not load every file in the directory: files still need to be imported.

    Matching initialization directories precisely lets other modules continue to benefit from barrel optimization. See Rspack's module.rules for rule syntax.

    Third-party dependencies

    These optimizations apply to bundled modules. External dependencies loaded by Node.js at runtime are not pruned by Rspack under these rules.

    Settings such as output.bundleDependencies control whether third-party dependencies are bundled. Changing that scope changes which modules are affected by sideEffects declarations.