飽き性の頭の中

Reactでウェブとアプリを最速で開発する方法を模索した話

Reactでウェブとアプリを最速で開発する方法を模索した話

tawachan
tawachan

とある勉強会で話した内容を、整理してまとめてみる。

ウェブとアプリを両方いい感じに作れるクロスプラットフォーム開発を実現できれば、PMF をスピーディに探れるエンジニアリング組織ができると思い技術検証をしてみた。

ウェブとアプリの両方を作るのは結構時間がかかる

ウェブを作るために SPA 開発をし、スマホアプリを作るために Swift やら Kotlin で開発するのが、それぞれの質を上げるにはまだ一番方法な気がする。

しかし、まだサービスの在り方が固まってないときに JavaScript / Swift / Kotilin をそれぞれ書くにはだいぶ時間がかかってしまうし無駄が多い。

そこで質は多少下がったとしても、開発速度を上げて PMF(Product Market Fit)を早く得られる状況をエンジニアリングの立場から作れるかを模索した。

クロスプラットフォームを実現する技術

クロスプラットフォーム開発を実現する技術はいくつかある。

  • Apache Cordova
  • React / React Native

Apache Cordova も事前に検討したが、React のほうが望ましそうな所感を得たのでこちらをさらに検証した。

React / React Native で試したこと

  1. React / React Native を同じリポジトリに置いてデータ周りを共通化する
  2. React Native に React Native for Web を導入する

React / React Native を同じリポジトリに置いてデータ周りを共通化する

どういうこと?

これはクロスプラットフォーム開発というよりは、React でウェブを開発、React Native でアプリを開発する順当な構成。

しかし、両者で共通で使うはずのデータ周りの処理を共通化させればある程度効率化できるのではないかという試み。

【ディレクトリ構成】

   .
├── common
│   ├── reducers
│   └── actions
├── native
│   ├── ios
│   ├── android
│   ├── src
│   ├── package.json
│   ├── tsconfig.json
│   ├── tslint.json
│   └── yarn.lock
└── web
    ├── package.json
    ├── public
    ├── src
    ├── tsconfig.json
    ├── tslint.json
    ├── webpack.config.js
    └── yarn.lock

よかったこと

こうした構成にしたことで、React / React Native でできることはすべてできるはず。

ウェブ向けのコードをアプリ用にビルドするわけでも、その逆でもないのでツラミが少なめ。

さらに、データ周りの処理が別フォルダに切り出されているので意識的に切り分けていけそうなところがよさそう。

微妙だったこと

しかし、React / React Native それぞれの package.json があるので管理するものが多い。

Typescript の場合は似たような tsconfig.json と tslint.json が必要なので結構煩雑になる。

共通化したとはいえ、そこまでスピード感を持って開発できるのかは懐疑的。

React Native に React Native for Web を導入する

React Native for Web とは

React Native for Web とは React Native のプロジェクトに後から入れることができるモジュール。

React Native のコンポーネントを Web で使える形にトランスパイルしてくれるので、React Native のコードがあればウェブ用のビルドもできるようになる。

React Native をそのままが使えるので View も共通化できるので、別々に実装するよりだいぶ効率化できそう。

React Dom と React Native が共存できる

React Dom も混ぜることができる。React Dom 入りの View をアプリ用にビルドするともちろん落ちるのだが、ウェブ向けにはビルドできる。

   import React from "react";
import { View, Text, StyleSheet } from "react-native";

export default class WebApp extends React.Component {
  render() {
    return (
      <View>
        <Text style={{ fontSize: 20, color: "blue" }}>ネイティブ</Text>
        <div style={{ fontSize: 20, color: "red" }}>ウェブ</div>
      </View>
    );
  }
}

これだとあまり実用性はないが、ウェブ向けとアプリ向けのどちらのビルドかによって出し分けることで活用できるように感じた。

   export default class App extends React.Component {
  render() {
    if (Platform.OS == "web") {
      return (
        <View style={styles.container}>
          <div style={{ fontSize: 20, color: "red" }}>ウェブ</div>
        </View>
      );
    } else {
      return (
        <View style={styles.container}>
          <Text style={{ fontSize: 20, color: "blue" }}>ネイティブ</Text>
        </View>
      );
    }
  }
}

Platform.OS で判定できるので、出し分けてあげるとこんな感じになる。

../../../assets/20180930134143.png

よかったこと

純粋な React Native のプロジェクトに後から入れることができるので、まずは React Native でアプリを作るのに専念できるのはかなりありがたい。

最初から、ウェブのこともアプリのことも考えて環境構築や開発するのは結構厳しい。

しかも、React Native コンポーネントの変換具合も結構いい感じそう。

まとめ

クロスプラットフォーム開発をする方法は世の中に幾つもあるが、React が一番良さそうだと思って検証した。

React を使ったやり方を模索してみた結果、React Native for Web を使うのが安定感とスピード感があって良さそうだと感じた。

これから本格的に実装をしていく予定なので、また所感があればまとめる。

関連記事