@module-federation/storybook-addon
v6.0.6
Published
Storybook addon to consume remote module federated apps/components
Readme
Storybook addon for Module Federation
This addon enables to consume remote Module Federated apps/components
Install
# with NPM
npm install @module-federation/storybook-addon
# with Yarn
yarn add @module-federation/storybook-addonConfiguration
In file ./storybook/main.js:
const moduleFederationConfig = {
// Module Federation config
};
const storybookConfig = {
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
addons: [
// other addons,
{
name: '@module-federation/storybook-addon',
options: {
moduleFederationConfig,
},
},
],
framework: '@storybook/react',
core: {
builder: '@storybook/builder-webpack5', // is required webpack 5 builder
},
};
module.exports = storybookConfig;Rsbuild App or Rslib Module
import { dirname, join } from 'node:path';
import type { StorybookConfig } from 'storybook-react-rsbuild';
function getAbsolutePath(value: string): any {
return dirname(require.resolve(join(value, 'package.json')));
}
const config: StorybookConfig = {
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
framework: {
name: getAbsolutePath('storybook-react-rsbuild'),
options: {},
},
addons: [
{
name: '@module-federation/storybook-addon/preset',
options: {
// add remote here and then you can load remote in your story
remotes: {
'rslib-module':
'rslib-module@http://localhost:3000/mf/mf-manifest.json',
},
},
},
],
};
export default config;
For the NX projects:
Replace Nx module federation wiring in webpack.config.js with a plain webpack config that uses withModuleFederation.
Example:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { withModuleFederation } = require('@module-federation/storybook-addon');
const baseConfig = require('./module-federation.config');
module.exports = withModuleFederation(baseConfig, { dts: false })({
mode: 'development',
context: __dirname,
entry: {
main: path.resolve(__dirname, 'src/main.ts'),
},
plugins: [new HtmlWebpackPlugin({ template: path.resolve(__dirname, 'src/index.html') })],
});In file ./storybook/main.js:
const nxModuleFederationConfig = {
// Module Federation config
};
const storybookConfig = {
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
addons: [
// other addons,
{
name: '@module-federation/storybook-addon',
options: {
nxModuleFederationConfig,
},
},
],
framework: '@storybook/react',
core: {
builder: '@storybook/builder-webpack5', // is required webpack 5 builder
},
};
module.exports = storybookConfig;Usage
import React, { Suspense } from 'react';
const LazyButton = React.lazy(() => import('remote/Button'));
const Button = (props) => (
<Suspense fallback={<p>Please wait...</p>}>
<LazyButton {...props} />
</Suspense>
);
export default {
title: 'ModuleFederation/Button',
component: Button,
argTypes: {
variant: {
control: 'select',
options: ['primary', 'secondary'],
},
},
};
const Template = (args) => <Button {...args} />;
export const Primary = Template.bind({ variant: 'primary' });
Primary.args = {
variant: 'primary',
children: 'Button',
};
export const Secondary = Template.bind({});
Secondary.args = {
variant: 'secondary',
children: 'Button',
};