create-react-app + antd-mobile + TypeScript環境へのStorybook導入

前提

  • create-react-app
  • TypeScript
  • antd-mobile(antdもほぼ同じ方法で対応可能)

Storybookの導入

$ npm i -g @storybook/cli
$ getstorybook

追加されたstoriesフォルダは /src 以下に移動する

TypeScriptの型定義を追加

$ yarn add -D @types/storybook__react @types/storybook__addon-actions

configの追加、変更

.storybook/webpack.config.js を追加する

const genDefaultConfig = require('@storybook/react/dist/server/config/defaults/webpack.config.js')
const tsImportPluginFactory = require('ts-import-plugin')

module.exports = (baseConfig, env) => {
  const config = genDefaultConfig(baseConfig, env)

  config.module.rules.push({
    test: /\.tsx?$/,
    exclude: /node_modules/,
    include: [/src/],
    loader: 'ts-loader',
    options: {
      getCustomTransformers: () => ({
        before: [
          tsImportPluginFactory({
            libraryName: 'antd-mobile',
            libraryDirectory: 'lib',
            style: 'css',
          }),
        ],
      }),
    },
  })
  config.resolve.extensions.push('.ts', '.tsx')

  return config
}

.storybook/config.jsを書き換え

import { configure } from '@storybook/react'

const req = require.context('../src/stories', true, /.stories.tsx$/)
function loadStories() {
  req.keys().forEach(filename => req(filename))
}

configure(loadStories, module)

storiesを.tsxに置き換え

src/stories/index.stories.tsx

import { action } from '@storybook/addon-actions'
import { storiesOf } from '@storybook/react'
import { Button } from 'antd-mobile'
import * as React from 'react'

storiesOf('Button', module)
  .add('with text', () => (
    <Button onClick={action('clicked')}>Hello Button</Button>
  ))
  .add('with some emoji', () => (
    <Button type="primary" onClick={action('clicked')}>
      <span role="img" aria-label="so cool">
        😀 😎 👍 💯
      </span>
    </Button>
  ))

動作確認

$ yarn storybook

モバイル端末のプレビューを追加する

storybook/addons/viewport at master · storybooks/storybook

addons/viewportを使う

$ yarn add -D @storybook/addon-viewport

.storybook/addons.js

import '@storybook/addon-actions/register'
import '@storybook/addon-links/register'
import '@storybook/addon-viewport/register' // 追加

これでモバイル端末サイズでの確認が簡単にできるようになる

f:id:nishaya:20180915191713p:plain

antd-mobileのthemeを変更している場合

.storybook/webpack.config.js が少し複雑になる

const genDefaultConfig = require('@storybook/react/dist/server/config/defaults/webpack.config.js')
const tsImportPluginFactory = require('ts-import-plugin')
const modifyVars = require('../antdTheme')
const path = require('path')

module.exports = (baseConfig, env) => {
  const config = genDefaultConfig(baseConfig, env)

  config.module.rules.push({
    test: /\.tsx?$/,
    exclude: /node_modules/,
    include: [/src/],
    loader: 'ts-loader',
    options: {
      getCustomTransformers: () => ({
        before: [
          tsImportPluginFactory({
            libraryName: 'antd-mobile',
            libraryDirectory: 'lib',
            style: true,
          }),
        ],
      }),
    },
  })
  config.resolve.extensions.push('.ts', '.tsx')

  config.module.rules.push({
    test: /\.less$/,
    use: [
      {
        loader: 'style-loader',
      },
      { loader: 'css-loader' },
      {
        loader: 'less-loader',
        options: { modifyVars },
      },
    ],
    include: path.resolve(__dirname, '../src/', '../node_modules/'),
  })

  return config
}