blog.tawa.me

東京出身・埼玉育ち・福岡在住のWebエンジニアが思い立った文章を書き溜める場所。エンジニアリングと海外とガジェットの話がきっと多め。

MENU

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

f:id:tawachan39:20181209172520j:plain

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

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

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

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

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

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

medium.com

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

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

  • Apache Cordova

Apache Cordova

  • React / React Native

React – A JavaScript library for building user interfaces

React Native · A framework for building native apps using React

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とは

github.com

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 で判定できるので、出し分けてあげるとこんな感じになる。

f:id:tawachan39:20180930134143p:plain

よかったこと

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

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

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

React Native examples

まとめ

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

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

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