包详细信息

@storybook/addon-react-native-web

storybookjs728.8kMIT0.0.29

Configure React storybook for react-native-web

storybook-addons, react-native, react-native-web

自述文件

React Native Web addon for Storybook

This addon configures @storybook/react to display React Native (RN) projects using React Native for Web (RNW)

See the FAQ for common questions.

You can read more about this package in this blog post.

To contribute see the contributing guide here

Heres a screen shot of how you could use this alongside storybook/react-native, the image is taken from the following starter code

image with storybook on mobile and web

Getting Started

Assuming you've got an existing RN project, run the following from the project root:

npx sb init --type react
yarn add react-dom react-native-web babel-plugin-react-native-web @storybook/addon-react-native-web @react-native/babel-preset --dev

Then edit your .storybook/main.js:

module.exports = {
  addons: [/*existing addons,*/ '@storybook/addon-react-native-web'],
};

From here, you should be able to write stories incorporating your RN components according to the Storybook for React instructions.

Common issues

Please see the FAQ for common issues like the "loader not found" error.

Config options

Most packages should work without extra changes however in some cases extra steps are needed. One common example is "reanimated" which requires some babel config and extra transpilation.

Options Type Description
modulesToTranspile Array<string> node_modules that need transpiling
modulesToAlias {[key: string]: string} node_modules that need aliasing
babelPlugins `Array<string \ [string, Record<string, string>]>` Babel plugins you want to apply
projectRoot string Path to the root of your project, if in a mono repo you might need to set this.
babelPresets `Array<string \ [string, Record<string, string>]>` Babel presets you want to apply
babelPresetReactOptions Record<string, any> Options to pass options to @babel/preset-react
babelPresetReactNativeOptions Record<string, any> Options to pass options to @react-native/babel-preset

Untranspiled react native libraries

Many react-native packages are shipped untranspiled and this doesn't work for the web platform. If you receive errors like "proper loader not found" after adding a package try adding it to the modulesToTranspile option for this addon.

You can do that like this:

module.exports = {
  addons: [
    /*existing addons,*/
    {
      name: '@storybook/addon-react-native-web',
      options: {
        modulesToTranspile: ['react-native-package-name'],
      },
    },
  ],
};

Aliasing react native web libraries

Some react-native packages recommend module aliasing as a means of importing and using the web variant of an existing package. If you need to add additional key:value pairs to webpack's config.resolve.alias, use the modulesToAlias option for this addon. You don't need to add react-native-web to this list as it is already included by default.

You can do that like this:

module.exports = {
  addons: [
    /*existing addons,*/
    {
      name: '@storybook/addon-react-native-web',
      options: {
        modulesToAlias: {
          'react-native-package-name': 'react-native-web-package-name',
        },
      },
    },
  ],
};

Replace react-native-package-name with the name of a real package.

Adding babel plugins

It's common to provide a babel plugin for certain packages in the react native eco system and you can pass a list of these to the addon.

module.exports = {
  addons: [
    /*existing addons,*/
    {
      name: '@storybook/addon-react-native-web',
      options: {
        babelPlugins: ['babel-plugin-name'],
      },
    },
  ],
};

Configuring popular libraries

Many libraries work without extra config, heres some examples of config required for some packages.

Note: react-native-vector-icons requires some extra steps due to fonts required and there will be a future addon with that config included.

Package Required config
react-native-svg No extra config needed
react-native-gesture-handler No extra config needed
react-native-reanimated
<summary> Click to here to see the config </summary> js module.exports = { addons: [ /*existing addons,*/ { name: '@storybook/addon-react-native-web', options: { modulesToTranspile: ['react-native-reanimated'], babelPlugins: [ '@babel/plugin-proposal-export-namespace-from', 'react-native-reanimated/plugin', ], }, }, ], };
native-base
<summary> Click to here to see the config </summary> Due to the vector icons dependency add the following js module.exports = { addons: [ /*existing addons,*/ { name: '@storybook/addon-react-native-web', options: { modulesToTranspile: ['react-native-vector-icons'], }, }, ], };
react-native-paper
<summary> Click to here to see the config </summary> Due to the vector icons dependency add the following js module.exports = { addons: [ /*existing addons,*/ { name: '@storybook/addon-react-native-web', options: { modulesToTranspile: ['react-native-vector-icons'], }, }, ], };
nativewind
<summary> Click to here to see the config </summary> Nativewind requires some additional babel config to work correctly. You can see an example of this config below. Tip: Use the web version of storybook to receive compilation and runtime errors that may not bubble up from the mobile simulators. js // .ondevice/main.ts // AND/OR .storybook/main.ts module.exports = { addons: [ /*existing addons,*/ { name: '@storybook/addon-react-native-web', options: { modulesToTranspile: [ 'react-native-reanimated', 'nativewind', 'react-native-css-interop', ], babelPresetReactOptions: { jsxImportSource: 'nativewind' }, // If you have a bable.config.js file: this can also be placed there, and removed from here babelPresets: ['nativewind/babel'], babelPlugins: [ // If you have a bable.config.js file: this can also be placed there, and removed from here 'react-native-reanimated/plugin', // If you have a bable.config.js file: this can also be placed there, and removed from here [ '@babel/plugin-transform-react-jsx', { runtime: 'automatic', importSource: 'nativewind', }, ], ], }, }, ], }; js // .ondevice/preview.tsx // add the following import '../styles/global.css' js // metro.config.js const path = require("path"); const { getDefaultConfig } = require("expo/metro-config"); const { withNativeWind } = require("nativewind/metro"); const withStorybook = require("@storybook/react-native/metro/withStorybook"); const defaultConfig = getDefaultConfig(__dirname); // 👇 important: nativeWindConfig is defined and passed to withStorybook! // replace this: module.exports = withNativeWind(config, { input: "./global.css" }); // with the below (and update your input): const nativeWindConfig = withNativeWind(defaultConfig, { input: "./styles/global.css" }); module.exports = withStorybook(nativeWindConfig, { // this line helps you switch between app and storybook using variable in package.json script, // and changes to your app's main entry point. enabled: process.env.EXPO_PUBLIC_STORYBOOK_ENABLED === "true", configPath: path.resolve(__dirname, "./.ondevice"), onDisabledRemoveStorybook: true, }); js // babel.config.js module.exports = function (api) { api.cache(true); return { presets: [ ["babel-preset-expo", { jsxImportSource: "nativewind" }], "nativewind/babel", ], plugins: [ ["babel-plugin-react-docgen-typescript", { exclude: "node_modules" }], 'react-native-reanimated/plugin', [ '@babel/plugin-transform-react-jsx', { runtime: 'automatic', importSource: 'nativewind', }, ], ], }; };

Adding support for static assets and svgs

Install @svgr/webpack and url-loader

module.exports = {
  /*existing config*/
  // to provide a public export for assets
  staticDirs: ['<path_to_assets>'],
  webpackFinal: async (config) => {
    const fileLoaderRule = config.module.rules.find(
      (rule) => rule.test && rule.test.test('.svg'),
    );

    if (fileLoaderRule) {
      fileLoaderRule.exclude = /\.svg$/;
    }

    config.module.rules.push({
      test: /\.svg$/,
      use: ['@svgr/webpack', 'url-loader'],
    });

    return config;
  },
};

Node polyfills for webpack 5

install node-polyfill-webpack-plugin

const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');

module.exports = {
  /*existing config*/
  core: {
    builder: 'webpack5',
  },
  webpackFinal: async (config) => {
    config.plugins.push(new NodePolyfillPlugin());

    return config;
  },
};

Known limitations

  • Libraries that don't support react-native-web will not work
  • Components will display on the web so may not be the same as a component on a mobile device since dom versions of those components may be used (like <div> and span)
    • when using primitives such as View/Text or other cross platform components then the difference should be minimal.

更新日志

v0.0.29 (Fri Mar 21 2025)

🐛 Bug Fix

  • Update Tailwind / Nativewind information in readme #96 (@rwitchell)

Authors: 1


v0.0.28 (Thu Mar 20 2025)

🐛 Bug Fix

Authors: 1


v0.0.27 (Fri Feb 07 2025)

🐛 Bug Fix

  • fix(webpack): fix derivation of DEV from NODE_ENV #99 (@lbland94)

⚠️ Pushed to main

Authors: 2


v0.0.27 (Fri Feb 07 2025)

🐛 Bug Fix

  • fix(webpack): fix derivation of DEV from NODE_ENV #99 (@lbland94)

⚠️ Pushed to main

  • fix: include mjs in babel loader test (@dannyhw)

Authors: 2


v0.0.27 (Fri Feb 07 2025)

🐛 Bug Fix

  • fix(webpack): fix derivation of DEV from NODE_ENV #99 (@lbland94)

⚠️ Pushed to main

  • fix: include mjs in babel loader test (@dannyhw)

Authors: 2


v0.0.27 (Fri Feb 07 2025)

🐛 Bug Fix

  • fix(webpack): fix derivation of DEV from NODE_ENV #99 (@lbland94)

⚠️ Pushed to main

  • fix: include mjs in babel loader test (@dannyhw)

Authors: 2


v0.0.26 (Fri Sep 27 2024)

🐛 Bug Fix

Authors: 1


v0.0.25 (Sun Sep 22 2024)

🐛 Bug Fix

Authors: 1


v0.0.24 (Thu Jun 06 2024)

🐛 Bug Fix

Authors: 3


v0.0.23 (Wed Feb 07 2024)

🐛 Bug Fix

Authors: 3


v0.0.22 (Sun Jan 07 2024)

🐛 Bug Fix

⚠️ Pushed to main

Authors: 2


v0.0.21 (Sat Jul 15 2023)

🐛 Bug Fix

Authors: 3


v0.0.20 (Fri Mar 31 2023)

🐛 Bug Fix

Authors: 4


v0.0.19 (Fri Oct 28 2022)

🐛 Bug Fix

Authors: 2


v0.0.18 (Wed Jan 12 2022)

🐛 Bug Fix

Authors: 2


v0.0.17 (Sat Jan 08 2022)

🐛 Bug Fix

  • feat: add example for gradient #31 (danny@Daniels-MBP.lan @dannyhw)

Authors: 2

  • Daniel Williams (danny@Daniels-MBP.lan)
  • Danny (@dannyhw)

v0.0.16 (Wed Dec 15 2021)

🐛 Bug Fix

Authors: 1


v0.0.15 (Wed Dec 15 2021)

🐛 Bug Fix

  • fix: add the suggested process.env plugin to the config #27 (@dannyhw)

📝 Documentation

Authors: 1


v0.0.14 (Fri Dec 03 2021)

🐛 Bug Fix

Authors: 1


v0.0.13 (Wed Dec 01 2021)

🐛 Bug Fix

Authors: 1


v0.0.12 (Thu Nov 25 2021)

🐛 Bug Fix

  • docs: don't suggest @next version in readme #21 (@dannyhw)
  • fix: use target for running action #20 (@dannyhw)

Authors: 1


v0.0.11 (Thu Nov 25 2021)

🐛 Bug Fix

Authors: 2


v0.0.10 (Tue Nov 23 2021)

🐛 Bug Fix

Authors: 1


v0.0.9 (Tue Nov 23 2021)

🐛 Bug Fix

  • fix crash if modulesToTranspile undefined #15 (@adblanc)

Authors: 1


v0.0.8 (Tue Nov 23 2021)

🐛 Bug Fix

  • fix: use automatic runtime and fix for mono repos #13 (@dannyhw)

Authors: 1


v0.0.7 (Mon Nov 15 2021)

🐛 Bug Fix

  • fix: ran sb upgrade and fixed peer deps #11 (@dannyhw)

Authors: 1


v0.0.6 (Mon Nov 15 2021)

🐛 Bug Fix

⚠️ Pushed to main

Authors: 1


v0.0.5 (Thu Nov 11 2021)

🐛 Bug Fix

Authors: 1


v0.0.4 (Wed Nov 10 2021)

⚠️ Pushed to main

Authors: 1


v0.0.3 (Wed Nov 10 2021)

🐛 Bug Fix

Authors: 1


v0.0.2 (Wed Nov 03 2021)

🐛 Bug Fix

  • fix: babelv7 enabled and babel config now included in preset #2 (@dannyhw)

Authors: 1


v0.0.1 (Wed Oct 13 2021)

🐛 Bug Fix

⚠️ Pushed to main

Authors: 2