npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@storybook/addon-react-native-web

v0.0.26

Published

Configure React storybook for react-native-web

Downloads

366,318

Readme

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.

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',
        ],
      },
    },
  ],
};
module.exports = {
  addons: [
    /*existing addons,*/
    {
      name: '@storybook/addon-react-native-web',
      options: {
        modulesToTranspile: ['react-native-vector-icons'],
      },
    },
  ],
};
module.exports = {
  addons: [
    /*existing addons,*/
    {
      name: '@storybook/addon-react-native-web',
      options: {
        modulesToTranspile: ['react-native-vector-icons'],
      },
    },
  ],
};
module.exports = {
  addons: [
    /*existing addons,*/
    {
      name: '@storybook/addon-react-native-web',
      options: {
        modulesToTranspile: [
          'react-native-reanimated',
          'nativewind',
          'react-native-css-interop',
        ],
        babelPresets: ['nativewind/babel'],
        babelPresetReactOptions: { jsxImportSource: 'nativewind' },
        babelPlugins: [
          '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.