react-nativeでreact-styleguidistを使う
2019-02-12

react-nativeでreact-styleguidistを使う

react-nativeのプロジェクトでreact-styleguidistを使う方法です。

コードのサンプルは本家の方にPR送ったのでこちらの見てください。

本家の方でコードが変わっている場合もあります。ご注意ください。

使っているライブラリなどのバージョンは次の通りです。

  • expo: 32.0.0
  • react-styleguidist: 8.0.6
  • react: 16.5.0
  • react-dom: 16.7.0
  • react-native-web: 0.10.0
  • @babel/core: 7.2.2

Expoを使ってますが、react-nativeのプロジェクトでも大まかな手順はほとんど同じだと思います。

動作の仕組み

react-styleguidistにはreact-nativeで動作させるための仕組みがないので、react-native-webを使ってreact-nativeのUIコンポーネントをWebで表示できるように変換して表示します。

簡単な図に表すと次のような仕組みになっています。

通常はreact-nativeはMetro bundlerを通して実行可能な形式になりますが、react-native-webで動かす場合は、Babelを使ってトランスパイルを行ってから、react-styleguidistで処理します。

react-styleguidistの導入

react-styleguidistとその依存モジュールをインストール

react-styleguidistとその依存モジュールをインストールします。

npm install --save-dev @babel/core @babel/plugin-proposal-class-properties @babel/plugin-proposal-object-rest-spread @babel/polyfill @babel/preset-env babel-loader babel-plugin-react-native-web file-loader metro-react-native-babel-preset react-dom react-native-web react-styleguidist webpack

注意点としては、react-native v0.57からbabel-preset-react-nativemetro-react-native-babel-presetに置き換わっていて、Babelも7系を使うようになっています。古いサンプルなどは依存関係のバージョンに注意してください。

react-artが依存関係に見つからないというエラーが出る場合は、npmインストールしてください。

styleguide.config.jsを設定する

styleguide.config.jsを追加します。

// styleguide.config.js
const webpack = require('webpack');

module.exports = {
  require: ['@babel/polyfill'],
  components: 'src/**/[A-Z]*.js',
  webpackConfig: {
    resolve: {
      // auto resolves any react-native import as react-native-web
      alias: { 'react-native': 'react-native-web' },
      extensions: ['.web.js', '.js'],
    },
    module: {
      rules: [
        {
          test: /\.js$/,
          loader: 'babel-loader',
          exclude: [/node_modules/],
          options: {
            plugins: [
              '@babel/proposal-class-properties',
              '@babel/proposal-object-rest-spread',
              'react-native-web',
            ],
            presets: [
              '@babel/preset-env', 
              'module:metro-react-native-babel-preset',
            ],
            babelrc: false,
          },
        },
        {
          test: /\.(jpe?g|png|gif)$/i,
          use: [
            {
              loader: 'file-loader',
              options: {
                hash: 'sha512',
                digest: 'hex',
                name: '[hash].[ext]',
              },
            },
          ],
        },
        {
          test: /\.ttf$/,
          loader: 'file-loader',
        },
      ],
    },
    // Most react native projects will need some extra plugin configuration.
    plugins: [
      // Add __DEV__ flag to browser example.
      new webpack.DefinePlugin({
        __DEV__: process.env,
      }),
    ],
  },
};


注意点としては、webpackのresolve.aliasオプションで、react-nativeの参照先をreact-native-webに置き換えている部分です。これで内部で宣言されているreact-native部分をreact-native-webに豪快に置き換えています。

実際のファイルはこちらです。

これでnpm run styleguideをすると、次のような画面が表示されます。

まとめ

最近、react-nativeを仕事で使うことが多いのでreact-styleguidistが動かせるかどうか調べてみました。

react-nativeの参照先をreact-native-webに置き換えているため、実際の再現度など細かな部分で差異がありそうです。

自分の場合は、採用を検討した結果、react-native-web部分に不安があるので見送りました。