今年のはじめにこんな記事がバズった。
批判的なコメントが多かったせいか、記事自体はもう消されてしまっている。
自分も数年前に Titanium を使ったことがあり、そんときは「Nativeで頑張ったほうが良さそう」と思って使うのをやめてしまった。ただ、その頃から状況も変わっているだろうし、この人の言っていることを無下に批判する気にはなれなかった。
そんなわけで、実際に自分の手で動かしてみることにした。以下はその時の作業メモ(自分用なので読みやすさは考慮してません)
動作環境
- react-native: 0.41.1
- Xcode 8.3
- Android Studio 2.2.3
作ったソースコード
https://github.com/koogawa/ReactNativeSample
インストール
Introduction · React Native に従って、Node、Watchman、React Native CLI をインストール。
brew install node brew install watchman npm install -g react-native-cli
サンプルプロジェクトの作成
iOS
react-native init AwesomeProject cd AwesomeProject
これだけで最低限の機能を備えたiOSアプリを生成してくれる。(言語はObjective-C)
react-native run-ios
を実行すれば iOS Simulator を起動してくれる。もしくは出力された xcodeproj を Xcode で開いて自分でビルドすることもできる。
ビルド自体は本当に簡単にできた。
cmd+d でデバッグメニューが出てくる。
出力されたコードを見てみる
デバッグメニューを出すのをどうやって実現しているのか気になったのでソースを追ってみると
RCTKeyCommands *commands = [RCTKeyCommands sharedInstance]; // Toggle debug menu [commands registerKeyCommandWithInput:@"d" modifierFlags:UIKeyModifierCommand action:^(__unused UIKeyCommand *command) { [weakSelf toggle]; }];
こんな感じでやっていた。cmdキーを検知できるの知らなかった。
AppDelegate も読んでみる。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSURL *jsCodeLocation; jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil]; RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation moduleName:@"ReactNativeSample" initialProperties:nil launchOptions:launchOptions]; rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; UIViewController *rootViewController = [UIViewController new]; rootViewController.view = rootView; self.window.rootViewController = rootViewController; [self.window makeKeyAndVisible]; return YES; }
index.ios.js から RCTRootView
を生成して self.window.rootViewController にセットしてる感じなのね。
ためしに index.ios.js に変更を加えて再度ビルドしてみたけど、AppDelegate に差分は出なかった。某クラスプラットフォームのように、単純に機械的なコードを吐き出してるわけでは無さそうだ。この辺はとてもシンプル。
Android
SDK Manager を起動して、必要なパッケージをインストール。
- Google APIs
- Intel x86 Atom System Image
- Intel x86 Atom_64 System Image
- Google APIs Intel x86 Atom_64 System Image
このとき Android SDK Build-Tools 23.0.1
にチェックが入ってないとダメ。
環境変数 ANDROID_HOME
にもパスをセットする必要がある。
export ANDROID_HOME=${HOME}/Library/Android/sdk export PATH=${PATH}:${ANDROID_HOME}/tools export PATH=${PATH}:${ANDROID_HOME}/platform-tools
最初、ここのパスを間違えて結構ハマった。
次に Android Studio から AVD Manager を起動して、エミュレータを起動しておくのがポイント。
AVD Managerは
android avd
のコマンドでも起動できる。
react-native run-android
でアプリを実行。
こんな感じで Android アプリもビルドできた。
タブバーを表示してみる
TabBarIOSの公式ドキュメント通り実装してみるが、何故かエラーが出る。。🤔
調べてみてわかったのだが、
var React = require('react'); var ReactNative = require('react-native');
みたいな書き方はすでに古くなっているらしい😩
Does React Native use require or import? - Stack Overflow
import React, { Component } from 'react'; import { AppRegistry, TabBarIOS, StyleSheet, Text, View } from 'react-native';
のような書き方に修正することで、なんとかビルドが通った。
見てるドキュメントが間違ってるのかもしれないけど、公式ドキュメントが最新になってないのはちょっと焦った😞
TabBarIOS
という名前なので、Androidの場合はどうするんだろう?という疑問が湧いたが、やはり同じことを考える人がすでにいた。
How to make Tab bar for Android like TabBarIOS in react native? - Stack Overflow
こうやってiOS用のコードとAndroid用のコードを別々に管理していくことになりそう。
所感
- ホントに簡単にアプリを作り始められる
- 公式ドキュメント通りやっても動かないことが多々ある
- 正しい情報を探すことになり、ここに多くの時間を割くことになりそう
- ビルドしてみないとエラーかどうかわからないのがつらい
- コードの補完機能がないのが地味につらい
- パフォーマンスとかはもうちょっと使ってみないとわからない
- iOS/Android のバージョンが上がったときに追従してくれるか不安
iOSアプリはXcode で、AndroidアプリはAndroid Studioで作りたいと思った。何を言っているのかわからねーと思うが(略
— Og🌗エンジニア🏝宮崎 (@koogawa) 2017年2月4日