HeavyCookie

Configurer Storybook avec TypeScript et React-Native-Web

Storybook se marie bien avec TypeScript, mais j'ai un peu lutté pour y faire fonctionner React-Native-Web.

On commence par configurer un projet node, y ajouter Storybook pour React :

$ yarn init
$ npx -p @storybook/cli sb init --type react # https://storybook.js.org/docs/guides/guide-react/

On y ajoute le support de TypeScript un peu modifiée aux côté de React-Native-Web :

$ yarn add -D typescript
$ yarn add -D awesome-typescript-loader
$ yarn add -D @types/storybook__react
$ yarn add react-native-web
$ yarn add -D @types/react-native

On modifie la configuration de webpack en aliasant react-native à react-native-web :

// .storybook/webpack.config.js
 
module.exports = ({ config }) => {
  config.module.rules.push({
    test: /\.(ts|tsx)$/,
    use: [
      {
        loader: require.resolve('awesome-typescript-loader'),
      },
    ],
  });
  config.resolve.extensions.push('.ts', '.tsx');
  config.resolve.alias['react-native$'] = 'react-native-web'
  return config;
};

Ainsi qu'une configuration TypeScript à laquelle on enlève la lib dom pour éviter qu'elle n'entre en conflit avec le typage de react-native

{
  "compilerOptions": {
    "outDir": "build/lib",
    "module": "commonjs",
    "target": "es5",
    "lib": ["es5", "es6", "es7", "es2017"], // On a enlevé "dom" ici
    "sourceMap": true,
    "allowJs": false,
    "jsx": "react",
    "moduleResolution": "node",
    "rootDirs": ["src", "stories"],
    "baseUrl": "src",
    "forceConsistentCasingInFileNames": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "suppressImplicitAnyIndexErrors": true,
    "noUnusedLocals": true,
    "declaration": true,
    "allowSyntheticDefaultImports": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "build", "scripts"]
}

Un yarn storybook et c'est parti !

Pour utiliser react-native-web, il suffit alors d'importer simplement react-native à la place et webpack s'occupe de tout.

A noter que ce n'est pas une solution idéale, je n'ai pas encore trouvé le moyen de faire fonctionner styled-components ou emotion. C'est la principale raison pour laquelle je n'utiliserai pas React-Native-Web 😅.