Rslib

This addon will load a reuseable Rsbuild config from Rslib config file for storybook-builder-rsbuild, which will make Storybook use an coherent configuration with Rslib. It also provides a way to development mf (Module Federation) format output.

WARNING

storybook-addon-rslib is still under development and subject to change at any time.

Getting started

Installation

npm
yarn
pnpm
bun
npm install storybook-addon-rslib -D

Setup .storybook/main.ts

export default {
  addons: ['storybook-addon-rslib'],
}

or with config

export default {
  addons: [
    {
      name: 'storybook-addon-rslib',
      options: {
        // Check options section.
      },
    },
  ],
}

Module Federation

First, you need to set up a Rslib project with mf format output.

To make Storybook load remote modules from the Module Federation host app, you can follow the steps below:

Set up

  1. Install an additional Module Federation Storybook addon, it will work with storybook-addon-rslib.

    npm
    yarn
    pnpm
    bun
    npm install @module-federation/storybook-addon -D
    • storybook-addon-rslib will auto start devServer to manage mf assets.
    • @module-federation/storybook-addon will make Storybook simulates Module Federation host app to load remote modules.
  2. Add dev server config for "mf" format in rslib.config.ts.

    rslib.config.ts
    1import { pluginModuleFederation } from '@module-federation/rsbuild-plugin'
    2import { pluginReact } from '@rsbuild/plugin-react'
    3import { defineConfig } from '@rslib/core'
    4
    5export default defineConfig({
    6  lib: [
    7    // ...
    8    {
    9      format: 'mf',
    10      output: {
    11        distPath: {
    12          root: './dist/mf',
    13        },
    14        // for production
    15        assetPrefix: 'http://localhost:3001/mf',
    16      },
    17      // for storybook to dev
    18      dev: {
    19        assetPrefix: 'http://localhost:3001/mf',
    20      },
    21      // for storybook to dev
    22      server: {
    23        port: 3001,
    24      },
    25      plugins: [
    26        pluginModuleFederation({
    27          name: 'rslib_provider',
    28          exposes: {
    29            '.': './src/index.tsx',
    30          },
    31          shared: {
    32            react: {
    33              singleton: true,
    34            },
    35            'react-dom': {
    36              singleton: true,
    37            },
    38          },
    39        }),
    40      ],
    41    },
    42  ],
    43  plugins: [pluginReact()],
    44})
  3. Add Module Federation types and stories into tsconfig.json.

    tsconfig.json
    {
      "compilerOptions": {
        // ...
        "paths": {
          "*": ["./@mf-types/*"]
        }
      },
      "include": ["src/**/*", ".storybook/**/*", "stories/**/*"]
    }
  4. Adding storybook-addon-rslib and @module-federation/storybook-addon to Storybook config.

    .storybook/main.ts
    1import { dirname, join } from 'node:path'
    2import type { StorybookConfig } from 'storybook-react-rsbuild'
    3
    4function getAbsolutePath(value: string): any {
    5  return dirname(require.resolve(join(value, 'package.json')))
    6}
    7
    8const config: StorybookConfig = {
    9  // ...
    10  addons: [
    11    {
    12      name: getAbsolutePath('storybook-addon-rslib'),
    13      options: {
    14        rslib: {
    15          include: ['**/stories/**'],
    16        },
    17      },
    18    },
    19    {
    20      name: '@module-federation/storybook-addon/preset',
    21      options: {
    22        // add remotes here for storybook to load remote modules
    23        remotes: {
    24          'rslib-module':
    25            'rslib-module@http://localhost:3001/mf/mf-manifest.json',
    26        },
    27      },
    28    },
    29  ],
    30  framework: {
    31    name: getAbsolutePath('storybook-react-rsbuild'),
    32    options: {},
    33  },
    34}
    35
    36export default config
  5. Load remote module from the configured remote name.

    stories/index.stories.tsx
    1import { Counter } from 'rslib-module'
    2
    3export default {
    4  title: 'Example/MFCounter',
    5  component: Counter,
    6}
    7
    8export const Primary = {}
  6. There you go, start Storybook with npx storybook.

Further Reading

Options

export interface AddonOptions {
  rslib?: {
    /**
     * `cwd` passed to loadConfig of Rslib
     * @default undefined
     */
    cwd?: string
    /**
     *  `path` passed to loadConfig of Rslib
     * @default undefined
     */
    configPath?: string
    /**
     * The lib config index in `lib` field to use, will be merged with the other fields in the config.
     * Set to a number to use the lib config at that index.
     * Set to `false` to disable using the lib config.
     * @experimental subject to change at any time
     * @default 0
     */
    libIndex?: number | false
  }
}