とある API を作っいて、動作確認にしょぼいクライアントアプリを作りたくなった。

  • 目標1: まずは Web で試して後から Native アプリ化したい。
  • 目標2: TypeScript で書きたい。

Twitter Lite で開発されたという react-native-web を使ってみる。react-native-web とは、react-native に入れ替えると ReactNative アプリが HTML アプリになるという物。同一のコードを携帯でも HTML でも動かそうと思うとまだちょっと手間がかかるようだ。

react-native-web アプリの一番簡単な作り方

react-dom の代わりに react-native-web を使うだけなら非常に簡単。create-react-app がすでに対応している。

まず、create-react-app で普通の React アプリを作る。ちなみに、npx はローカルにインストールされた node コマンドを実行するだけの物だと思っていたら、ローカルにインストールされてない時は勝手にインストールして使い終わったらアンインストールしてくれるという便利機能があった。

npx create-react-app react-native-web-simple

react-native-web をインストール

cd react-native-web-simple
yarn add react-native-web

src/index.js を書き換える

import { AppRegistry } from 'react-native';
import App from './App';

AppRegistry.registerComponent('App', () => App);

AppRegistry.runApplication('App', {
  rootTag: document.getElementById('root')
});

src/App.js を書き換える

import React, { Component } from 'react';
import logo from './logo.svg';
import { Image, StyleSheet, Text, View } from 'react-native';

const Link = (props) => <Text {...props} accessibilityRole="link" style={StyleSheet.compose(styles.link, props.style)} />

class App extends Component {
  render() {
    return (
      <View style={styles.app}>
        <View style={styles.header}>
          <Image accessibilityLabel="React logo" source={logo} resizeMode="contain" style={styles.logo} />
          <Text style={styles.title}>React Native for Web</Text>
        </View>
        <Text style={styles.text}>
          This is an example of an app built
          with <Link href="https://github.com/facebook/create-react-app">Create React App</Link> and{' '}
          <Link href="https://github.com/necolas/react-native-web">React Native for Web</Link>
        </Text>
        <Text style={styles.text}>
          To get started, remix this starter kit by editing <Link href="https://glitch.com/edit/#!/react-native?path=src/App.js" style={styles.code}>src/App.js</Link>.
        </Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  app: {
    marginHorizontal: 'auto',
    maxWidth: 500
  },
  logo: {
    height: 80
  },
  header: {
    padding: 20
  },
  title: {
    fontWeight: 'bold',
    fontSize: '1.5rem',
    marginVertical: '1em',
    textAlign: 'center'
  },
  text: {
    lineHeight: '1.5em',
    fontSize: '1.125rem',
    marginVertical: '1em',
    textAlign: 'center'
  },
  link: {
    color: '#1B95E0'
  },
  code: {
    fontFamily: 'monospace, monospace'
  }
});

export default App;

上記コードは https://glitch.com/edit/#!/react-native から拝借しました。不思議な事に react-native-web をインストールすると react-native を import 出来るようになる。これは webpack の alias という機能を使っていて、あらかじめ create-react-app の生成する webpack に alias の設定が入っているからだった。https://github.com/facebook/create-react-app/pull/407

Native でも Web でも動くアプリを作る。

https://github.com/necolas/react-native-web/blob/master/website/guides/getting-started.md#web-packaging-for-existing-react-native-apps の通りに作業するだけですが、私は初見でかなり戸惑ったので丁寧に書きます。手順としては以下になります。

  • 普通に ReactNative のプロジェクトを作る。
  • JavaScript を合体させるために webpack + babel の設定を書く。
    • babel-plugin-react-native-web でソースコードで react-native を import すると react-native-web を import した事になる。
  • ブラウザで表示するために index.html や index.web.js を書く。
  • 微調整。

普通に react-native のプロジェクトを作る

brew install node watchman yarn
npm install -g react-native-cli
react-native init ReactNativeTest
cd ReactNativeTest
react-native run-ios

react-native-Web 化に必要なモジュールをインストール

yarn add react-dom react-native-web
yarn add --dev babel-plugin-react-native-web babel-loader url-loader webpack webpack-dev-server webpack-cli

web/webpack.config.js の作成

通常の ReactNative では、Metro というツールでソースコードを合体させますが、react-native-web では webpack + babel を使います。

https://github.com/necolas/react-native-web/blob/master/website/guides/getting-started.md#web-packaging-for-existing-react-native-apps に書いてある通りの内容で web/webpack.config.js を作成します。

index.html の作成

ウェブブラウザがアクセスする HTML を適当に書きます。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>React Native Web</title>
  </head>
  <body>
    <div id="react-app"></div>
  </body>
  <script type="text/javascript" src="bundle.web.js"></script>
</html>

index.web.js の作成

アプリを記述する App.js を HTML 上に設置する部分です。

index.web.js の作成

import App from './src/App';
import { AppRegistry } from 'react-native';

// register the app
AppRegistry.registerComponent('App', () => App);

AppRegistry.runApplication('App', {
  initialProps: {},
  rootTag: document.getElementById('react-app')
});

App.js の移動

react-native init で作ると最上位に App.js が作られますが、webpack に合わせて src に移します。

mkdir src
mv App.js src/App.js

実行

./node_modules/.bin/webpack-dev-server -d --config ./web/webpack.config.js --inline --hot --colors

ブラウザで http://localhost:8080/ を開く。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.