ナカザンドットネット

それって私の感想ですよね

「たった1日で基本が身に付く! Androidアプリ開発超入門」という本が出版されます

来る9月21日(金)に「たった1日で基本が身に付く! Androidアプリ開発超入門」という本が技術評論社さんから出ることになりました。電子書籍版もあります。

たった1日で基本が身に付く!  Androidアプリ開発超入門

たった1日で基本が身に付く! Androidアプリ開発超入門

人生初の商業向け単著です! しんどかった。世の中の単著erの皆さんすごい。

いろいろ思い出があるので、出版にあたってのあれこれを書いてみようと思います。

どんな本なの?

プログラミング未経験者やAndroid未経験者の方が、本の内容で手を動かしながら(いわゆる「写経」をしながら)Java言語やAndroid Studioの使い方を学んでいく本です。

初学者向けの本にするにあたって、次の3点を工夫しています。

  • Android Studioを日本語化して、できるだけ解説に英語が出てこないようにする
  • Java言語についての解説は最低限にする
  • レイアウトはGUIエディターのみで行う

余計な前提知識を求めると、躓いてしまう方もいそうだったので、できるだけ前提知識を求めずに、学びたいことをストレートに学べるようにした形になります。

Android Studioの日本語化

Android Studioを日本語化したおかげで、解説の中で出てくる文言の多くを日本語にすることができました。

見慣れないアルファベットの単語が入り混じった文章はコンテキストスイッチが多くなりそうなので、良い取り組みだったと思います。だからといってカタカナが大量に出てくるようになったのが良かったのかというと怪しいですし、ScrollViewのようなクラス名はそのまま表記しているので、どのくらい読みやすさに寄与したのかは、読者の感想を待ちたいところです。

Javaを説明しすぎない

本書はプログラミング未経験者を対象にしているため、Java言語についての解説も行いました。写経していく中で登場する、変数やメソッドといった最低限の要素だけを解説しています。

思い切った点として、クラスについての解説をほとんどしていません。クラスの書き方を解説し始めると際限なく話題が膨らんでいくためです。

自作のクラスを活用せずにAndroidアプリを作っていくと、自然とFat Activityになります。それ自体は後々に問題を引き起こす可能性はあります。ただ、それが問題になるくらいにコードをたくさん書けるようになった人なら、本書ではなくもっと別の本がフィットするようになっているはずです。

この「たった1日で」シリーズの良さは薄さや手軽さです。「Android Javaの正しさ」を語り過ぎないようにしたつもりなので、読者がサクサク読み進められたらいいなと思います。

レイアウトエディターはデザインモードのみ

レイアウト作成の解説は、レイアウトエディターのデザインモードのみで行いました。レイアウトの解説にXMLは登場しません。ここは筆者のこだわりです。

XMLを書きながらプレビューを見るスタイルも筆者は好きですが、初学者時代を思い出して見ると、JavaとXMLを行ったり来たりするのは地味に心が折れそうになるポイントだった記憶があります。

現代のAndroid Studioには、ConstraintLayoutを用いた、そこそこ実用的といえるWYSIWYGなレイアウトエディターがあります。これならば心理的な障壁が幾分か低くなるのではないかと考え、全編で採用しました。ドラッグ&ドロップで制約を付けていく作業については、限られた紙面の中で、できるだけ丁寧に解説したつもりです。アプリ開発の醍醐味のひとつ、レイアウト作成を楽しく体験してもらえればと思います。

余談として……本書はAndroid Studio 3.1.4向けに書いたので、Android Studio 3.2で導入されたナビゲーションエディターを用いた画面遷移の定義は盛り込めませんでした(そもそも画面遷移を取り扱う紙面の余裕もなかったのですが:-p)。2019年に似たような本が出てくるときには、是非ナビゲーションエディターの解説も含まれていてほしいなあと思います。

執筆の経緯

技術評論社さんで刊行しているたった1日で基本が身に付く!シリーズのAndroid Studio版を作ろう、という企画が先にあり、1月に知人を通じて声がかかりました。まさに降って湧いたようなチャンスだったので、最低限の調整だけを行って、ほぼ二つ返事でOKしました。

それまでに書いたことがあった中で最も長い本は、88Pの技術書典4本でした。

blog.nkzn.info

200ページ超の執筆は初めてだったので、かなり不安もありました。とはいえ、ここまで大きいチャンスは滅多に来ません。多少自信がない程度で逃すわけにもいかなかったのでした。

当初の予定では5月くらいまでに書き上げて、7月刊行くらいのスケジュールを引いていた気がしますが、筆者の遅筆が原因でずるずると延びて、8月入稿となりました。関係者の皆さんにはご迷惑をおかけしました。

執筆の体制

執筆の体制については、ざっくりと次のような感じです。

  • 編集プロダクションとのやり取り
    • GitHubとSlackでIssue管理と連絡を行う
  • 執筆環境(メンタル)
    • 集中できるようにネットカフェに入り浸る
  • 執筆環境(システム)
    • VivlioStyleでMarkdown+CSS組版で書いた
    • Macで書きたいがためだけにVPNを張ってリモートデスクトップを設定した
    • 初稿の差分管理はGitで行う
    • 以降の校正作業はPDFベースでコメントを付ける

日本語の文章の差分管理にもGitを使うのが有用なのは、プログラマーの間では認知されてきていることですね。

個人的に面白い取り組みだった、CSS組版とリモートデスクトップについて掘り下げます。

CSS組版

今回の本は編集プロダクションのリブロワークスさんと一緒に作ったのですが、リブロワークスさんではVivlioStyleというCSS組版のツールにMarkdownを組み合わせた執筆環境を用意してくれています。

f:id:Nkzn:20180906232000p:plain

libroworks.co.jp

Atomにプラグインを入れておけば、実際の本と同じような見た目でプレビューしながら、執筆を行うことができます。

ReVIEWにもリアルタイムプレビューを行うツールはあったので、執筆体験としては既知の(素晴らしい)ものでしたが、こちらのほうがより実物に近い形で実現されていたので、楽しく執筆できました。

リモートデスクトップ

今回の本はWindows向けなので、Android Studioの動作確認やスクリーンショットの撮影はWindows上で行う必要がありました。一方で、私は普段Macを使っており、指が最もスムーズに動くのはMacです。Emacsキーバインドに指が汚染されているし、XKeymacsは好みじゃないので仕方ないですね。

Android Studioの操作がWindowsに準じたものになるのは問題なかったのですが、Atomで日本語を入力していくときにWindowsのお作法に縛られるのは嫌でしたし、Windows上に快適な環境を作り上げる労力を払うのも嫌でした。

仕方がないので、MacからWindowsマシンにリモートデスクトップでアクセスし、Android Studioを触ることにしました。Windows側で撮影したスクリーンショットは自動でDropboxのフォルダに入るようにして、ほぼリアルタイムでMac側に共有されるようにしました。

また、前述のとおり、ネットカフェでの作業が多かったため、自宅の外からでもWindowsマシンに繋がるよう、VPNを設定しました。これで快適な執筆環境の完成です。

f:id:Nkzn:20180906233450p:plain

この環境ができるまで、なかなか文章を書き始められなかったので、担当さんをやきもきさせてしまって非常に申し訳なかったです……

グランドスラム達成

ここは本の内容と関係ないです。

今回の出版のおかげで、これまで本の形で執筆してきたものリストが次のようになりました。

タイトル 出版年月 出版 形態
はじめる! Corona SDK 2011年7月 達人出版会(商業) 電子書籍(単著)
TechBoosterの同人誌 随時 TechBooster(同人) 紙・電子書籍(共著)
Effective Android 2013年8月 達人出版会(商業) 電子書籍(共著)
Effective Android 2014年1月 インプレス(商業) 紙(共著)
Cheap Dive into React Native 2018年4月 越後屋(同人) 紙・電子書籍(単著)
たった1日で基本が身に付く!
Androidアプリ開発超入門
2018年9月 技術評論社(商業) 紙・電子書籍(単著)

この表を読み換えてみると、なんと、(商業|同人)、(電子|紙)、(単著|共著)の組み合わせを全パターン網羅しているのです。

  • 商業・電子・単著(Corona SDK)
  • 商業・電子・共著(Effective Android)
  • 商業・紙・単著(たった1日で)
  • 商業・紙・共著(Effective Android)
  • 同人・電子・単著(Cheap Dive)
  • 同人・電子・共著(てくぶ)
  • 同人・紙・単著(Cheap Dive)
  • 同人・紙・共著(てくぶ)

グランドスラム達成は言い過ぎかも*1ですが、ちょっとした達成感があります。

この7年間、いろいろ書いてきたんだなあ、としみじみしてしまいますね。本を書く楽しさを教えてくれた皆さんには感謝するばかりです。

今後も、機会を見つけて本を書いていきたいと思いますので、よろしくお願いします。

まとめ

妻や編集さんに助けてもらいながら、何とか本を書き上げることができました。この規模になってくると、とてもじゃないですが自分の力だけでやりましたとは言えません。本づくりって色んな人の力で成り立ってるんだなーと思いました。

筆者がAndroidをやり始めたときにも、多くの書籍に助けられました。私の本が、現代の初学者の助けになれば、望外の喜びです。この本で入門した読者が5年後くらいにDroidKaigiで登壇してたりしたら泣くので、そういう方がいれば5年後にお声がけください。

書店にPOPとか持ち込んだら置いてもらえるのかな……

*1:紙媒体の雑誌連載とかはしたことないですしね

React Nativeの光と闇について喋ってきました #上越TechMeetup

f:id:Nkzn:20180723164831j:plain

7月21日(土)に新潟県上越市で行われた、上越TechMeetup#2に参加してきました。

jtm.connpass.com

町家を改装したイベントスペース「高田小町」で、総勢15名での、和やかな雰囲気での開催となりました。

なんでいったの

主催の五十川さんがRNの話を聞きたいということでお呼ばれしました。上越は地元なので、地元で行われるIT勉強会にお呼ばれなんて、テンションがダダ上がりになる事案です。

個人的なところとして、2010年ごろに上越である程度の規模のIT勉強会を開催することを諦めて新潟市で開催していたという事情がありまして、自分が諦めたことを実現した勉強会を是非応援したいという気持ちもありました。

なにしたの

React Nativeの光と闇というタイトルで講演してきました。スライドは次のとおりです。

www.slideshare.net

細かい内容は後述します。

他の方の発表

印象に残ったお話だけ。

writer.appの話

f:id:Nkzn:20180723163347p:plain

https://writer-app.com/

自動文字起こしのWebアプリです。実用上のニーズから生まれているので、使いやすさはピカイチとのこと。

FirebaseやGCPをモリモリ使っているのは楽しそうだなあと思いました。

EventEmitterの話

@さんから。ブラウザの文脈にEventEmitterを持ち込むと、Reactで小さいアプリを作るときにpropsのたらい回しとかしないで済むことがあって良いよ、というお話でした。

序盤は「えー、いうてEventEmitter氏、大規模に乱用するとプロジェクトが崩壊するじゃないですかー」と思いながら聞いていました。途中で当人から「まあ、規模が大きくなってくるとReduxとかのほうが管理しやすくなるんですけどね」という話があったので、安心して聞いていられました。

SOC2の話

クラスメソッドの植木さんから。↓の裏話について。

classmethod.jp

ISMSなんかも「面倒くさそうだなあ」と思いながら傍から見ていたのですが、これは輪をかけて面倒くさいやつのようです。

「おおお、そこまで監査するんだ偉い」みたいな気持ちで聞いていましたが、自分たちではあんまりやりたくないですね・・・。

React Nativeの光と闇

ざっくりとした内容としてはこんな感じです。

光パート

  • Reactはレイアウトツリーの差分更新が得意なライブラリだよ
  • React NativeはReactの得意分野をネイティブビューの更新に持ち込んだやつだよ
  • AndroidとiOSの同時開発ができるのは嬉しいね
  • react-native initで作ったプロジェクトはXcode/Android Studio経由でビルドすることが多いよ
  • デモ:ハロワとちょっとしたLive Reload
  • React NativeはC++処理系の上で動くJavaScriptCoreの上で、バベったJSを動かしてるよ
  • JSとC++の間の通信方式はWebKitが担保してるので素性がいいね
  • C++とObj-C/Javaの間の通信もそれぞれのOSで普通のやり方があるので素性がいいね
  • デモ:create-react-native-app(Expo)でQRコードリーダーを作る
    • デバッグ時に突如コンソールに現れるQRコード
    • カメラパーミッションの請求も、カメラプレビューの配置も、読み込んだQRコードのデータ受け取りも、Expoならサクサクやれちゃう
    • JANやIMEIのバーコードも読めちゃう
    • ねっ、簡単でしょ?
  • Expoクライアントアプリが色々隠蔽してくれてます
  • 活用事例

闇パート

  • 万人にオススメできるわけではない
  • 無理を通した帳尻合わせを、腕力で何とかしている部分がある
  • 腕力の例
    • エラーメッセージを読む力
      • JSC, Android, iOSのエラーメッセージが混在するので、メンバーの誰かはそれを読めないとしんどい
    • ビルドする力
      • リリースビルドするときは、JS文化圏、Android文化圏、iOS文化圏のそれぞれのお作法を押さえておく必要がある
      • なお、Expoは知らないままビルドしても何とかなる部分が多い
      • Expoは楽なんだけど、本来のやり方を知らないままでいくとトラブったときに身動きが取れなくなるので、やはり本来のお作法を知っている人間はいたほうがよい
    • ストアにリリースする力
      • Google Play ConsoleとかAppStore Connectを使うのは同じ
      • 何にせよAppleの審査員とは闘う
    • バージョンアップする力
      • RN自体のバージョンアップが結構しんどい
      • アップグレードコマンドも失敗することがある
      • マジiOSお前
      • 困ったらreact-native initから環境構築をやり直したほうが早いというのが現状

光と闇のはざまで

  • 技術選択は組織と事業に見合ったものを選ぶべき
  • 普段使っている、責務が小さいライブラリなら、組織や事業との相性を深く考えなくてもリスク少なめで採用できたりする(失敗しづらい)
  • RNはメリットもデメリットも大きいので、よく考えないと採用しづらい
  • Airbnbは結果的に去ってしまったけれど、どんな組織と事業にマッチしそうなものなのかを僕らに考えさせてくれた
  • メリットは最大限享受して、デメリットを可能な限り回避したり打倒したりできる、そんな組織や事業で採用したいですね
  • もしあなたが目指す組織・事業の途上でRNが役立てられそうなところがあったら、使ってみてください

感想

「光と闇」なんて大風呂敷を広げてしまったせいで、自分の中での意見のバランス調整が大変でした。闇パートを先に仕上げたのですが、気持ちがネガティブになってしまい、なかなか光パートを書き始められないという事故があったり。

僕はRNの話をするときに一番怖いのは、オーディエンスが「React Nativeは銀の弾丸である」と思って、誤ったワクワクを持って帰ることです。そのため、普段から闇の話を多めにすることにしていますが、おかげで「お前はRNが嫌いなのか?」と言われることもあります。そうじゃないのです。闇って言っちゃってますが、実際には解決すべき課題たちなのです。課題を解決するためのコストがメリットに対してめちゃくちゃ軽いならば、限られた条件において銀の弾丸っぽいものになることはあると思います。結局は組織と事業にマッチするかどうかです。

とはいえ心配ばかりしていてもReact Nativeの良いところが世の中に伝わらないんだよなあ、とも思っていたので、今回は思い切って光の話もしてみました。Webの人がブラウザ上ではどうやっても獲得できないQRコード読み込みを、超サクッとやってみせるというデモをしただけですが、刺さる人には刺さったんじゃないでしょうか。

また、ノージャンルのIT勉強会だったので、オーディエンスにどの程度の知識を要求したらいいのかという点でもかなり迷いました。ざっくりとReactという概念を先に説明することで、なんとかJSに普段触れ合っていない人向けにも理解度を上げられたのではないかと思います。

今までRNの話は東京でコンテキストの近い人たち向けに喋ることが多かったわけですが、今回の資料作りで新潟向けの難易度調整みたいなところが分かってきた気がするので、今後はもうちょっと県内でも喋ってみたいです。

懇親会

写真を取り忘れましたが、ビアバッシュでした。おしゃべりしてたらほとんど食べてない(いつものこと)。

うちこういう仕事すること多いんだけど、RNマッチすると思う?みたいな話をちらほらもらいました。

総括

f:id:Nkzn:20180723164930j:plain

主に現地の上越や、新潟県内からの参加者が多い感じでしたが、長野や石川からの参加者もおり、上越地方ならではの顔ぶれという感じの特色あるイベントになっていたと思います。

10年前にこのイベントがあれば私は新潟市に移住しなかったかもしれないもしもの話をしても詮無いことなのですが、是非育ってほしいイベントです。

今後とも発表を中心に、応援していけたらと思います。

Android Studioを立ち上げるのが億劫になってコマンドラインだけで済ませたAndroid出身React Nativeエンジニアの指の動き

AndroidエミュレータでRN製アプリのデバッグをしようと思ったのですが、なんとなくAndroid Studioを立ち上げてエミュレータを起動してRunボタンを押すのが億劫になってしまい、指の赴くままにコマンドラインからアプリを起動してみました。

何も考えないで指を動かしただけなので、もっと良い方法があるかとは思います。読んでもよく分からなかった人は真似せずAndroid Studioを起動してください。

エミュレータを立ち上げる

エミュレータの作成はAndroid Studioを通したほうが楽ですが、作成済みのエミュレータはコマンドラインからでも起動できます。

$ $ANDROID_HOME/tools/emulator -list-avds # 作成済みのエミュレータ一覧を出す
Nexus_5X_API_26
Pixel_API_24
Pixel_C_API_25
$ $ANDROID_HOME/tools/emulator @Pixel_C_API_25 # エミュレータを指定して起動する
emulator: emulator window was out of view and was recentered

emulator: ### WARNING: /etc/localtime does not point to /usr/share/zoneinfo/, can't determine zoneinfo timezone name
emulator: ### WARNING: /etc/localtime does not point to /usr/share/zoneinfo/, can't determine zoneinfo timezone name

本来は $ANDROID_HOME/tools にはPATHを通してあるので、ただ emulator と打つだけでも起動できますが、説明のために冗長にしてあります。

これでエミュレータの起動を待ちます。

bundlerをスタートしておく

最終的には react-native run-android を使うので、そのときに一緒にbundlerを立ち上げてもらえるのですが、諸々の事情でyarn startに単純なstart以外にも処理を仕込んである場合などがあると思います。うちの場合はキャッシュに悩まされてつらかったことがあったので --reset-cache を必ず付けるようにしてたりします。

そんな事情から、 run-android とは別にbundlerを実行しています。ターミナルのタブをひとつ占有させてあげる感じですね。

$ yarn start
yarn run v1.5.1
$ node node_modules/react-native/local-cli/cli.js start --reset-cache
Scanning folders for symlinks in /path/to/rnapp/node_modules (51ms)
 ┌────────────────────────────────────────────────────────────────────────────┐
 │  Running Metro Bundler on port 8081.                                       │
 │                                                                            │
 │  Keep Metro Bundler running while developing on any JS projects. Feel      │
 │  free to close this tab and run your own Metro Bundler  instance if you    │
 │  prefer.                                                                   │
 │                                                                            │
 │  https://github.com/facebook/react-native                                  │
 │                                                                            │
 └────────────────────────────────────────────────────────────────────────────┘
Looking for JS files in
   /path/to/rnapp


Metro Bundler ready.

Loading dependency graph, done.

エミュレータのデバイス名を確認してrun-androidする

エミュレータとbundlerの準備ができたら、あとはアプリを起動するだけです。

react-native run-android にdeviceIdオプションを付けると、インストール先の実機やエミュレータを指定できるので、先程起動したエミュレータのdeviceIdを調べるところから始めます。

$ $ANDROID_HOME/platform-tools/adb devices # エミュレータや実機のdeviceIdを調べる
List of devices attached
emulator-5554   device # これがエミュレータのdeviceId
$ npx react-native-cli run-android --deviceId emulator-5554 # Androidでアプリを起動する
npx: 41個のパッケージを4.999秒でインストールしました。
Scanning folders for symlinks in /Users/y.nakagawa/dev/an-lite-app/packages/app/node_modules (46ms)
JS server already running.
Building the app...

adbでdeviceIdを調べると、大抵はemulartor-5554が出てきます。面倒であれば調べずに決め打ちでemulator-5554を指定してもいいのかもしれません(というかよくやります)。

コマンドが react-native run-android ではなく npx react-native-cli run-android は特に意識の高い話ではなくかなりズボラな話で、何だか面倒になってreact-native-cliをグローバルにもdevDependenciesにもインストールしなくなった*1ので、このときだけ使えればいいやというモチベーションで使っています。この方法の問題として、yarn startとrun-androidで使っているcliの実装が違っているけどいいの?という話はあって、いつか痛い目を見そうな気はしています。

まとめ

Android SDKのemulatorやadbといったコマンドの動きが指に染み付いている人間はこういう変な起動の仕方をすることがありますが、こんなことを新しく覚えるために学習コストを払うくらいなら素直にAndroid Studioを立ち上げたほうが賢明だと思うので、どうしてもやってみたい方以外は真似するのはオススメしません。

*1:たまにしか使わないし・・・

React NativeをWebに持ってくることの意味

React Native for Webは、React NativeをWebに持ち込む試みです。

しばしば、こういった試みに対して「わけがわからない」「本末転倒である」といった意見を見かけますが、筆者は妥当な試みであるという印象を持っています。ちょっと頭の中にあるものを出してみようと思います。

ブラウザはGUIアプリケーションプラットフォームではない

まず前提となっている思想として、 WebブラウザはGUIアプリケーションプラットフォームではない 、というものがあります。ブラウザは元々ドキュメントビューアであり、Webページで情報を閲覧するためのソフトウェアであり、アプリケーションのランタイムではなかった、という立場です。

HTMLもCSSもJS(vanilla jsね)も、綺麗でセマンティックでインタラクティブなWebサイトを作るための進化を遂げましたが、元々がドキュメントビューアなので、アプリを動かすためのフレームワークとしては無理が残ります。

巨大な配列データのリストを省メモリで表示できる仕組み、ユーザーの言語や地域の設定に合わせて自動で表示言語を切り替える機能など、AndroidやiOSであれば当然持っている機能はブラウザには搭載されていません。ダウンロード処理や非同期処理を伴うならばぜひ使いたいプログレスバーも、インジケータ(ぐるぐる)も、標準では搭載されていません。

ブラウザで同じようなことをしたいと思ったら、人気っぽいJavaScriptライブラリやCSSフレームワークを選定し、導入する必要があります。これは「ドキュメントビューアを頑張ってGUIアプリケーションっぽく動かすための作業」です。頑張りの大半をライブラリ製作者が担ってくれているために実感しづらいですが、筆者はそう思っています。

これはブラウザがGUIアプリケーションプラットフォームとして劣っているという話をしたいのではなく、そもそもドキュメントビューアなので、GUIアプリケーションが作りづらいのは自然なことである、という話です。divもspanもul/liも、それらを装飾するCSSも、GUIのレイアウトを組むことに特化した作りをしているわけではないのです。

Flexboxについて

ちょっと主張がブレるように思われるかもしれませんが、Flexboxはアプリ開発に向いているなあ、と思っています。Webサイトを作っていく上でも役立つので、別にアプリ開発のために作られた機能というわけでもないと思うのですが、AndroidのLinearLayoutやiOSのStackViewなど、類似の機能がアプリ開発の現場では欠かせない状況になっているので、これが登場したときには本当に嬉しかった・・・

React DOMはGUIアプリケーションフレームワークではない

ブラウザそのものがGUIアプリケーションプラットフォームでないのであれば、何らかのフレームワークを噛ませることで、ある程度GUIアプリケーションを作りやすくなりそうですよね。筆者はしばらくの間、「React DOMを使ったらブラウザをGUIアプリケーションプラットフォームであるかのように扱える」と思っていました。

さて、現実を見てみましょう。

Reactは、DOMをいくらかの単位で切り分け、コンポーネントとして扱わせてくれます。Reactは、データの更新に対するDOMの更新を最低限に抑えてくれます。Reactのおかげで、複雑なインタラクションを最低限のコストで管理できるようになりました。

これで、どんな複雑なWebサイトでも構築できます!

…………………………

……………………

…………

……やっぱりGUIアプリケーションのフレームワークという感じではないぞ……?

「ドキュメントビューアを頑張ってGUIアプリケーションっぽく動かす」ためのコストを下げてくれる存在であることは間違いないのですが、レイアウトを組むために必要な頑張りの方向性は、楽になっただけで(これはこれでもちろん重要なんですが)、あまり変わっていません。

React NativeはGUIアプリケーションプラットフォームの抽象である

AndroidやiOSはGUIアプリケーションプラットフォームです。React Nativeは両者の上でGUIアプリケーションを構築させるためのツールを用意するにあたり、AndroidやiOSにあったものを共通化する形で「GUIアプリケーションを作るなら大抵こういうのが必要でしょ」というコンポーネント群やモジュール群を用意しました。

特にコンポーネント群には嬉しいものが多いです。基本となるViewText以外にも、ぐるぐるを出してくれるActivityIndicatorや、巨大な配列データを省メモリでリスト表示できるFlatList、挟めばスクロールさせてくれるScrollView、進捗を表示するProgressBar/ProgressView、引っ張って更新のRefreshControlなど、 「無きゃ無いでどこかから調達してくるなり自作なりするけど、あるなら嬉しい」 が揃っています。もちろん足りないものもあるので自作することもありますが、GUIアプリケーションを構築していくにあたっての最低限のベースとしては充実していると思います。

この抽象はAndroid/iOSをベースに生み出されたので、AndroidとiOSでしか有効でないものと思われがちですが、実際にはプラットフォームを限定しない抽象化を行っているため、react-native-windowsreact-native-macosといった、他のプラットフォームの抽象化にも成功しています。

React Nativeは「あらゆるGUIアプリケーションプラットフォームを抽象化するフレームワークである」と言えるのではないかとすら、筆者は感じています。

React Native for Webがブラウザに持ち込んだもの

Webブラウザ上でGUIアプリケーションを構築しようとした場合にも、React Nativeの「GUIアプリケーションを作るなら大抵こういうのが必要でしょ」というコンポーネントのラインナップは、やはり有効です。

React Native for Webは、ネイティブアプリをブラウザ上で再現しようとしたものではありません。React Nativeが提唱したGUIの抽象化を、Webアプリケーションの世界でも使えるようにした、ブラウザ向けのReactコンポーネント&便利モジュール集ライブラリです。

React Native本家のテクノロジスタックとは異なり、次の図のような構成になっています。

f:id:Nkzn:20180529203426p:plain

たまたまReact Nativeと似たようなラインナップのコンポーネントが、たまたま似たような名前のpropsを持っていて、たまたまReact Nativeと似たようなスタイルを持っている、ただそれだけです。スタイルやpropsに関する思想をReact Nativeに寄せてあるだけで、ライブラリとしてはmaterial-uiOnsen UIに近いとすらいえるでしょう。

コンポーネントが便利

というわけで、ただのブラウザ向けReactコンポーネントとしてみた場合に、どんなコンポーネントがあるかというと、

  • ぐるぐるを出してくれるActivityIndicator
  • 挟めばスクロールさせてくれるScrollView
  • 進捗を表示するProgressBar
  • 引っ張って更新のRefreshControl

こういうのが普通に使えるわけです。便利ですね。

スタイル周りも良い感じ

GUIアプリケーション、特にモバイルでの動作を意識したスタイルが最初から効いています。

例えばScrollViewには次のような特性があります。

  • 細かい設定をしなくてもScrollViewの中には慣性が効く
  • 細かい設定をしなくてもScrollViewの中身がオーバースクロールする

例えばこういうの↓を書いただけで、画像が縦にズラッと並んで、慣性スクロールも聴いて、一番下まで行ったらちょっとオーバースクロールもさせてくれるわけです。

<View>
  <ScrollView style={{flex:1}}>
    <Image />
    <Image />
    <Image />
    ...
  </ScrollView>
  <Text>画面下部に固定のテキスト</Text>
</View>

このへんはMobile Safariに苦しめられたことがあったので、地味に嬉しいです。

また、React NativeではレイアウトにFlexboxを採用しているのを踏襲して、次のような特性も持っています。

  • 常に display: flex が効いてる
  • flexDirection のデフォルト値が column (縦並び)

毎回 display: flex を書かなくていいのは完全に楽ですし、モバイル向けのアプリではアイテムを上から下に並べることが多いことから、flexDirectionを指定する機会が減るのも助かります。

TouchableOpacityでタップ表現もラクラク

TouchableOpacityは「タップイベントに応じて囲んだ内側のViewの透明度を変えるフィードバックを表現する」ためのコンポーネントです。

<TouchableOpacity onPress={() => { /* タッチイベント */}}>
  <View /> // 自作のボタンっぽいもの
</TouchableOpacity>

上記のようなコンポーネントを作った場合、内側のViewには一切タッチイベントに関する設定を行わなくても、簡単なフィードバックを実装することができます。

f:id:Nkzn:20180529200955g:plain

他にもいろいろあるけど

GUIアプリケーションを作る際に便利なあれこれが詰まっています。

React Native本家とコードの共通化、みたいな文脈もないわけではないですが、それよりも、単純にWebアプリ開発を便利にしてくれるツールだと思ったほうが気楽に試せると思います。

触ってみたくなった方向けに、create-react-app上にReact Native for Web環境を置いたボイラープレートを用意しておいたので、触ってみてください。

github.com

プロダクション事例が強すぎる

実は、PWAの事例として有名なTwitter Liteは、React Native for Webの事例でもあります。

Twitter LiteはReact Nativeによるネイティブアプリ版が存在するわけでもなく、純然たるWebアプリです。

こういった活用ができる程度には、React Native for WebはWebアプリ開発の文脈で有用なものであると筆者は考えます。

作者のnecolasも語ってた

https://twitter.com/necolas/status/983769332411805697

↑から始まる一連のツイートで、React Nativeそのものやfor Webの可能性について語っています。アツいです。

まとめ

React Native for Webは、React Nativeによって抽象化された「モバイルアプリ開発の当たり前」をブラウザの世界に持ち込んでくれる存在です。

単純にWebアプリ開発の負担を軽減してくれるところもありますし、ネイティブアプリ開発の出身者が初めてWebアプリ開発に携わったときに経験しやすい「えっ、こんなことも自分で工夫しないといけないの」を、いくらか軽減してくれる効果も期待できます。

ScrollViewなどを単独で使うこともできるので、皆さんのWebアプリの一部に取り込んでみてはいかがでしょうか。

余談:React系のアプリケーションフレームワーク

Reactベースでありながらまったく別のコードベースで開発が進められているフレームワークたちを挙げてみます。

  • React Native
    • Android, iOS向けのGUIアプリケーションフレームワーク
    • ネイティブ実装部分を差し替えただけのサードパーティ実装もある
      • react-native-windows(Windows)
      • react-native-macos(macOS)
      • react-native-dom(ブラウザ)
    • この辺の話は先日の記事が詳しい
  • React Native for Web + React DOM
    • ブラウザ向けのGUIアプリケーションフレームワーク
    • React Nativeのコンポーネントを模倣している
  • React 360
    • VRアプリのためのGUIアプリケーションフレームワーク
    • React Nativeのコンポーネントを模倣している
  • Ink
    • ターミナルのためのCLIアプリケーションフレームワーク
    • 独自の生態系を構築している

はい、Inkをオチに使いたかっただけです。

<Color green>
  {this.state.i} tests passed
</Color>

f:id:Nkzn:20180529205525g:plain

完全に独自の生態系ですよ・・・この発想はなかった・・・

マッハ新書できそうだったけどやらずにちゃんと書いたという話

最近、マッハ新書ってあるじゃないですか。

nlab.itmedia.co.jp

golden-lucky.hatenablog.com

実践してる人たちのツイートをリアルタイムで眺めながら、「はー、そういうのもあるのか」くらいに思っていたのですが、期せずして自分の手元にもマッハ新書を出版できる=12時間以内で最低限の思想を表明できるチャンスが巡ってきました。

しかし、結局マッハ新書的な形で出すのではなく、多少の時間をかけてそこそこボリュームのある記事を書くことを選びました。

このあたりの心の動きは来週くらいには忘れてしまっていそうなので、エッセイとして残しておきたいと思います。

続きを読む

Web最新技術がてんこ盛りのreact-native-domから目が離せない

パリで発表されていたReact向けプロダクトがあまりにも未来に生きていて興奮したので、紹介させてください。

目次

  • 目次
  • この記事のゴール
  • 想定読者
  • はじめに
  • 今回ベースとするソースコード
  • React Nativeは何をするツールか
  • Reactは何をするツールか
  • React DOMとReact Nativeの違い
    • Reactアプリケーションを描画するものたち
    • React DOMの役割
    • React Nativeの役割
      • 1. ネイティブ処理系の上でJavaScript処理系を動かす
      • 2. Reactを動かす
      • 3. Reactから渡された差分をネイティブViewに適用する
  • React Native DOMはどこがReact Nativeなのか
  • React Native DOMのやばいところ6連発
    • ReactからはReact Nativeに見えてるのがやばい
    • Objective-C実装をJavaScriptに書き直しててやばい
    • Web Workerまで使って2スレッド制を再現してるのがやばい
    • Yogaをwasm向けにポーティングしてるのがやばい
    • React DOMを使ってないのがやばい
    • 実はWebComponentsを描画してるのがやばい
  • React Native DOMはやばい
  • Donation Welcome!

この記事のゴール

この記事では、React Nativeの内部実装に関する予備知識がほとんどない人が、React Nativeが元々どういうものなのかをふんわりと理解した上で、React Native DOMがどのように変態かつ未来に生きているのかを分かったつもりになってもらうことを目的とします。

想定読者

  • ReactがわかるJavaScriptエンジニア
  • JavaScriptのマルチスレッド処理の実例に興味がある方
  • WebAssemblyの実例に興味がある方
  • React Nativeのソースコードを読んでみたいけど、JavaScriptならともかくJavaやObjective-Cを読むのはちょっと・・・と尻込みしていた方

はじめに

5月17, 18日に、パリでReact Europeが開催されました。

f:id:Nkzn:20180522084612p:plain

https://www.react-europe.org/

Reactに関する様々な知見が公開されたようですし、スケジュールを見た限りではReact Nativeに関するセッションも多めなように思われました。

中でも私の目を引いたセッションは、Vincent Riemerさん([twitter:@vincentriemer])の "Bridging React Native Back to its Roots" でした。動画↓とスライドがそれぞれ公開されています。

www.youtube.com

このセッションは「React Native DOMというプロダクトを作ってみたので、モチベーションと設計方針の紹介、それからデモをするね」というタイプのやつでした。

github.com

字面からなんとなく想像できるかと思いますが、React Native DOMは「React Nativeコードをブラウザ上で動かすためのライブラリ」です。

このへんのユースケースに興味があって調べたことがある方は「えっ、それReact Native for Webと何が違うの?」と思われたことでしょう。はい、私もそう思いました。

ちょうど、Cheap Dive into React Nativeを書いたおかげでReact Nativeのソースを読むのにも自信がついてきたところなので、「まあどうせYet Another React Native for Webでしょ」と思いながらReact Native DOMのソースを読み始めたのです。

そしたらまんまと度肝を抜かれたので、「こりゃみんなにどれだけすごいか伝えにゃいかん」と、こんな記事を書き始めた次第です。

長文で前提条件から細かく書いているので、ひとまず概要を知りたい方はQiitaの記事へどうぞ。

react-native-dom の何がすごいのか - Qiita

また、React Nativeのことはもうわかってるよ、という方は「React Native DOMはどこがReact Nativeなのか」の見出しを検索して、そこからお読みください。

続きを読む

FluxにはModelがないのではないかと思った覚書

Fluxを使い始めると「おっ、MV*に比べて頭が悪くても状態が壊れないぞ?」という感想になる人が多いと思うんだけど、その理由がふたつあるような気がしてきた。

ModelやViewModelについてはコンテキストが違う人から「それ違くない?」と言われそうな書き方になるかもだけど、思いつきを書きなぐってるだけなので勘弁してください。

1. 単方向データフローが分かりやすく、コードの複雑さの低下に寄与している

これは全くポジティブな要因。

2. FluxはMV*のModel相当の要素が図に含まれていないので考えることが減った

MV*は「Modelって書いてあるからには何かをModelと呼んでデータを突っ込まなきゃいけない」という意識が生まれやすかった(その責務分割が適切だったかは別として)と思う。

でも、FluxにはStoreとかいうViewModel*1みたいなものしかない*2と私は思っていて、MV*でModelと呼ばれていたものを定義させようとする意図は感じられません。

結果的に、Modelについて書いてないので考えるきっかけがなくなって、必要な脳内メモリの量が減った結果、「頭が悪くても〜」という感想になるのではと思いました。

文脈

文脈としてはこの辺の話から来ています。

まとめ

MV*はModel内の設計について定義していませんでしたが、FluxはModelの存在自体を私たちに押し付けてこない子なのでは、と思い始めました。Model相当のものがなくていいわけがないのですが、単方向データフローが強力すぎて、Model相当の部分があやふやでも、みんな何とかなっちゃってるんじゃないかな・・・*3

Model相当の部分を設計したFlux、業務で色々と試してみているので、どこかのタイミングで布教していきたいです。

補足をいただきました

この記事の本質を言語化し直してくれました。

nekogata.hatenablog.com

うん、StoreとVMの話は余計だったなという気持ちはあります。

おまけ

DroidKaigi 2018でベノワさんが紹介していたModel-View-Intentは限定的ながらModel相当の部分(Repositoryとか)にも言及している単方向データフローで、Fluxの単方向データフローしか見たことがなかった私にとってはかなり学びがあったので、興味があれば見てみてください。

speakerdeck.com

www.youtube.com

*1:VMを持ち出すと文脈がぼやけてしまいますが、Presentation Domain SeperationにおけるPresentationの中にいるということだけ伝わればOKです。

*2:StoreがViewModelに見えているのは僕の主観です。Modelだと主張したい方の思想を否定するものではありませんので、異論反論はご自身の主張を自分のブログか何かで展開してください。それはそれで僕も読みたい。

*3:Fat Controller相当のものがAction CreatorやReducerの中に増殖して見通しが死ぬほど悪くなったコードをたまに見かけるし書いたこともあります。