Exporting React Native Storybook Components as Static Storybook Web App
At first, I need to give credit and say "Thank you" : I wrote this article with the help of this post on the Stackoverflow by this user . I was looking for the solution of this problem for longer time, but did not find something usable.
Storybook has evolved to be the holy-grail for frontend development. Currently, it supports all big players of the frontend scene like Angular, Vue, React & React Native and many other frameworks with not so big developer base.
As many of you already know, Storybook setup differs platform by platform- see official instructions here.
In this article, I will focus on React Native and React (a bit) and explain how we can build a static web version of Storybook from React Native project.
In general, if we need to use Storybook either for React or React Native, we just use the Storybook "init" command with different parameters:
After the execution of the "init" command, the following scripts are added to the project's package.json:
As you can see, the package.json for React Native setup is missing the "build-storybook" command used to build a static version of your Storybook.
Did you know that there is the port/mirror of React Native called React Native for Web? It allows you to render React Native Components (yes, components backed by native code) inside the web browser. See the React Native Web project below.
Important Note: Currently, it supports React Native >= 0.60. I have tested it with 0.61.5 and 0.62.0.
The native modules are not supported but everything else except modals and alerts is. The "alert" implementation should not be any problem inside the browser environment but for modal, you will probably need to use some third-party library or wait until it will be implemented (check the status here).
So how this magic works?
Recent versions of the Storybook introduced the new file to be used for configuration or to put it simply, for story loading: main.js (located in the .storybook folder in your project) - see how it looks below :
Moreover, the main.js file could be used for custom webpack config. This is exactly what we are going to do - we tell the webpack inside Storybook to replace all imports from:
- react-native to react-native-web.
- @storybook/react-native to @storybook/react. Yes, we will use Storybook for React instead of Storybook for React Native.
The Short Example
The following example is better than describing everything:
1. Our React Native Components Stays Untouched
We will not modify any of them - they could look like the following example:
or we can import "component" from designer tools (Figma, Sketch, etc) in the SVG format:
that could look similar to this (screenshotted example, just for simplicity):
2. Initializing Storybook for React Native
Now we need to initialize Storybook according to the official docs - by executing Storybook init command with type param of react_native. Check it below:
npx -p @storybook/cli sb init --type react_native
3. Creating storybook-website folder
Next, we will create the storybook-website folder in the root folder of our project.
Inside this folder, we create main.js file with custom webpack config:
Remember, we also need to install
- react-native-web@ 0.12.2
4. Supporting SVGs
Quick note: I find to have few problems with SVGs inside Storybook - I solved it with following:
The SVGs inside React Native 0.61.5 and Storybook
During my recent work with Storybook, I found small problems with SVG and react-native-svg package. So I thought I will…
Moreover, I also needed to install svg-react-loader library. Then, I needed to put following piece of code into storybook-website’ main.js file:
5. Modifying package.json to support build-storybook command
By doing the following step, we will be able to use the “build-storybook” command that was missing from the React Native Storybook setup. We need to add it manually into the package.json file but remember - node_modules will not be aware of our changes. See the example below, when I tried to run build-storybook command manually:
The command to build storybook is as follows (just put it in your package.json file):
Now, we have just added the "build-storybook" command to build a static storybook web app with the following parameters:
- config-dir specifies the folder, where is our main.js configuration file for static Storybook build located (storybook-website folder in our case).
- output-dir is moreless straightforward.
6. Storybook Init for React (NOT React Native)
Then we are going to include deeper support for "build-storybook". Although we manually added the build-storybook command inside the project package.json file in the previous step, we still need to use it within Storybook's node_modules context. The best and the quickest option will be to init Storybook again, but for the browser version of React. See the command below:
npx -p @storybook/cli sb init --type react -f
After confirmation (that we want to force re-init of our project), we try to run the" build-storybook" command again. But now, it will not result in an error.
However, this process (Storybook init process ) may add a few new files to our project - see the picture below.
We can safely delete the root /stories folder (containing files 0-Welcome.stories.js,etc.) that are unnecessary for us.
The final folder structure
Finally, the folder structure should look similar to this:
We can see 3 folders:
- .storybook (containing main.js file for React Native Storybook)
- storybook (where your stories are)
- storybook-website (containing main.js file for static Storybook web app. Just to force webpack to use replace imports from React Native to React Native for Web).
After the executing build-storybook command we can find our static Storybook inside dist-storybook-website folder. The final static Storybook showcase in the style of #write-once-run-everywhere could be seen below (remember, SVG shadows must be added manually inside React Native):
Platform-specific code resolution is not supported so far - you can solve it by handling platform related components by yourself / maybe with additional webpack configuration ?? Just let me know in the comments. I mean the following button-platform-specific implementation:
And as you can see, shadows are a bit tricky too.
To see React Native Stories in static Storybook build (without physical mobile device presence), we need to execute just 4 steps:
- force webpack to use imports from React Native for Web instead React Native
- for React Native project, use Storybook for React and not for React-Native
- manually modify package.json to add build-storybook with custom main.js config
- fix Storybook for React to support SVG (I did so by adding svg-react-loader into webpack config)