Skip to content

[Bug]: MSW Storybook Addon Fails to Initialize with Lazy Compilation in Rsbuild Storybook #409

@tmeindle

Description

@tmeindle

Version

## Environment

- **Storybook**: 10.1.10
- **storybook-react-rsbuild**: 3.2.0
- **msw**: 2.12.6
- **msw-storybook-addon**: 2.0.6
- **@storybook/addon-docs**: 10.1.10
- **@storybook/react**: 10.1.10
- **React**: 19.2.3
- **OS**: Windows

Details

Description

When using the MSW Storybook addon with Rsbuild's lazy compilation feature enabled (default?), the addon fails to initialize correctly, causing stories that use MSW handlers to get stuck in an infinite loading state. This issue does not occur when lazy compilation is disabled.

Steps to Reproduce

  1. Configure Storybook with Rsbuild and MSW addon:

.storybook/main.ts:

import type { StorybookConfig } from 'storybook-react-rsbuild';
import { dirname, join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const config: StorybookConfig = {
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  addons: ['@storybook/addon-docs', 'storybook-addon-rslib'],
  staticDirs: [resolve(__dirname, '../public')],
  framework: {
    name: 'storybook-react-rsbuild',
    options: {
      builder: {
        lazyCompilation: true,  // This is enabled by default
      },
    },
  },
};

export default config;

.storybook/preview.ts:

import type { Preview } from 'storybook-react-rsbuild';
import { initialize, mswLoader } from 'msw-storybook-addon';

initialize({
  onUnhandledRequest: 'bypass',
});

const preview: Preview = {
  parameters: {
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/i,
      },
    },
  },
  loaders: [mswLoader],
};

export default preview;
  1. Create a story that uses MSW handlers:

src/UserProfile/UserProfile.stories.tsx:

import type { Meta, StoryObj } from '@storybook/react';
import { http, HttpResponse } from 'msw';
import { UserProfile } from './UserProfile.component';

const meta = {
  title: 'Components/UserProfile',
  component: UserProfile,
  parameters: {
    layout: 'centered',
  },
} satisfies Meta<typeof UserProfile>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {
  args: {
    userId: 1,
  },
  parameters: {
    msw: {
      handlers: [
        http.get('/api/users/1', () => {
          return HttpResponse.json({
            id: 1,
            name: 'John Doe',
            email: '[email protected]',
            avatar: 'https://i.pravatar.cc/150?img=1',
            role: 'Developer',
          });
        }),
      ],
    },
  },
};
  1. Ensure mockServiceWorker.js is in the public directory
  2. Run Storybook: pnpm storybook (or npm run storybook)
  3. Navigate to a story that uses MSW handlers (e.g., "Components/UserProfile")

Expected Behavior

The story should load normally with MSW handlers intercepting and mocking API requests. The component should render with the mocked data.

Actual Behavior

The story gets stuck in an infinite loading state and never renders. The MSW service worker appears not to initialize or activate properly when lazy compilation is enabled. The browser tab shows a perpetual loading spinner. No errors are reported in the console.

Workaround

Disabling lazy compilation resolves the issue:

.storybook/main.ts:

import type { StorybookConfig } from 'storybook-react-rsbuild';
import { dirname, join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { mergeRsbuildConfig } from '@rsbuild/core';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const config: StorybookConfig = {
  stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
  addons: ['@storybook/addon-docs', 'storybook-addon-rslib'],
  staticDirs: [resolve(__dirname, '../public')],
  framework: {
    name: 'storybook-react-rsbuild',
    options: {
      builder: {
        lazyCompilation: false,  // Disable lazy compilation
      },
    },
  },
  rsbuildFinal: async (config) => {
    return mergeRsbuildConfig(config, {
      dev: {
        lazyCompilation: false,
      },
    });
  },
};

export default config;

With lazy compilation disabled, all MSW-dependent stories load and render correctly.

Additional Context

  • This appears to be a timing or initialization issue where lazy compilation interferes with the MSW service worker registration or the mswLoader execution.
  • The service worker file (mockServiceWorker.js) is in the public directory and configured via staticDirs.
  • The issue may be related to how Rsbuild's lazy compilation defers module loading, potentially causing the MSW initialization to happen before required dependencies are available, or vice versa.
  • Stories without MSW handlers work fine with lazy compilation enabled.
  • The issue is consistent and reproducible across multiple stories that use MSW.

Impact

This bug prevents using lazy compilation (which significantly improves dev server startup time) in projects that rely on MSW for API mocking in Storybook. This is a significant limitation for larger projects where lazy compilation provides substantial performance benefits.

Reproduce link

n/a attached

Reproduce Steps

see above

repro.zip

Metadata

Metadata

Assignees

No one assigned

    Labels

    storybookissue from storybook

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions