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 😅.