とある勉強会で話した内容を、整理してまとめてみる。
ウェブとアプリを両方いい感じに作れるクロスプラットフォーム開発を実現することができれば、 PMFをスピーディに探れるエンジニアリング組織ができると思い技術検証をしてみた。
- ウェブとアプリの両方を作るのは結構時間がかかる
- クロスプラットフォームを実現する技術
- React / React Nativeで試したこと
- React / React Nativeを同じリポジトリに置いてデータ周りを共通化する
- React NativeにReact Native for Webを導入する
- まとめ
ウェブとアプリの両方を作るのは結構時間がかかる
ウェブを作るためにSPA開発をし、スマホアプリを作るためにSwiftやらKotlinで開発するのが、それぞれの質を上げるにはまだ一番方法な気がする。
しかし、まだサービスの在り方が固まってないときにJavaScript / Swift / Kotilinをそれぞれ書くにはだいぶ時間がかかってしまうし無駄が多い。
そこで質は多少下がったとしても、開発速度を上げてPMF(Product Market Fit)を早く得られる状況をエンジニアリングの立場から作れるかを模索した。
クロスプラットフォームを実現する技術
クロスプラットフォーム開発を実現する技術は幾つかある。
- 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で試したこと
React / React Nativeを同じリポジトリに置いてデータ周りを共通化する
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
で判定できるので、出し分けてあげるとこんな感じになる。
よかったこと
純粋なReact Nativeのプロジェクトに後から入れることができるので、 まずはReact Nativeでアプリを作るのに専念できるのはかなりありがたい。
最初から、ウェブのこともアプリのことも考えて環境構築や開発するのは結構厳しい。
しかも、React Nativeコンポーネントの変換具合も結構いい感じそう。
まとめ
クロスプラットフォーム開発をする方法は世の中に幾つもあるが、Reactが一番良さそうだと思って検証した。
Reactを使ったやり方を模索してみた結果、React Native for Webを使うのが安定感とスピード感があって良さそうだと感じた。
これから本格的に実装をしていく予定なので、また所感があればまとめる。