ninjinkun's diary

ninjinkunの日記

iOSアプリ開発者がWebアプリ(PWA)をリリースするまでの流れ

先日リリースした個人アプリBlogFeedbackを開発した動機と、開発の時系列、開発してみての感想(ネイティブ開発者から見たPWAとか)を書いていきます。リリースエントリにも書きましたが、このアプリはiOSネイティブアプリからWebアプリへの移植です。

TL;DR

  • BlogFeedbackのケースではWebでもネイティブアプリとほぼ同等の体験を作ることができた
  • ネイティブ歴が長くHTML/CSSに明るくなかったので、まずReact Native for WebでUIを組んでいって、自力でHTML/CSSが書けるようになってから脱React Native for Webした
  • React / TypeScript / create-react-app / styled-components / storybook おすすめ
  • ブログを書いている人はBlogFeedbackを使ってみて欲しい!

Web版を開発した理由

プロダクト的な理由

  • 元アプリiOSネイティブアプリだったので、AndroidやPCでも見れるようにしたかった
  • ローカルにしかデータを持っていなかったので、Webにデータを集めて複数デバイスから参照できるようにしたいと思っていた
  • コードが2012年時代のObjCで書かれており、さすがに古すぎたのでフルスクラッチしたかった

個人的な理由

  • Twitter Liteを一年以上使っていて、Web(PWA)でも今はここまでできるという感触を掴んでいた
  • ネイティブアプリはなくならないものの、今後はPWAとの棲み分けが進むだろうと予測している
  • 仕事がネイティブアプリからWebアプリ開発の方にシフトしたので、HTML/CSS/JSをきちんと勉強し直したかった
    • ネイティブの仕事が長かったので、Webフロントエンドの知識が2010年のjQueryまでで止まっていた
    • 勉強のために今回はMaterial-UIとかUIフレームワークは使わず、ゴリゴリHTML/CSS/JSを書いてUIを作っている。UIデザインも自分
  • ネイティブ開発時代からReduxなどSPA方面から来たパラダイムに注目していたので、本流をちゃんと知っておこうという動機もあった

開発タイムライン

割とゆるゆる停滞しながら開発していたので、それなりに時間がかかっている。

2018年3月

  • このアプリのコアは各SNSのシェア数を集計するクローラである
  • なのでとりあえずnode.jsで動くクローラを書いてみた
    • ES2015にキャッチアップ
  • できたので飽きて放置

2018年5月

  • ネイティブアプリ開発者のここぽんさんがPWAに挑戦した事例が出て、俺もやるかーとなる

  • UIでも作ってみるかと思ってReactを入れる
    • 職場がVue.jsなので、少し迷ったがReactを採用
    • ReduxをJSでもちゃんと書いてみたかったので、だったら本家のReactかなというイージーな動機
  • webpackのconfigが大変そうなイメージがあったので、create-react-appを知って飛びつく
  • Firebaseを導入
    • 認証の設定
    • Cloud Firestoreにデータを貯め始める

2018年6月

  • React Native for Webを導入
    • Reactを少し書いてみて、HTMLもCSSもよくわからんとなった
    • React NativeはFlexboxでUIが組めるので、ネイティブアプリの感覚に近いということは知っていた
    • React Native for Webならネイティブ出身者人も優しいんじゃない?と思って入れた
      • ちょうど同じ頃 id:Nkzn さんの記事が出て盛り上がっていた

  • Typescriptに移行
    • SwiftやJavaで型がある開発に慣れているので、ReactのPropsやStateをさわり始めると型が無いのがきつくなってきた
    • このときにcreate-react-appのforkのreact-scripts-tsでプロジェクトを作り直した
  • この後一時停滞、この頃でもUIは全然できてないw

2018年9月

  • Atomic Designの本を読んだので、試してみたくなってモチベーションが再開

  • とりあえずディレクトリをAtomic Design風に分割
  • styled-componentsを導入
    • これまではほとんどスタイルが当たっていなかった
    • Atomic Design本の内容を実践しようと思ったら、CSSをそれなりに書く必要があったので、名前を聞いたことがあったので導入
    • 結果的にはすごく自分にしっくりきている
      • クラス名からの解放、コンポーネントを直接装飾するというのは自分にはとても直感的
      • これが使えるという理由だけでVueよりReactを推したくなる
  • ここでようやくReduxを導入
    • 書くのがだるいのはわかっていたので、必要になるまで入れない方針だった
    • コンポーネントが分かれて、共有状態が必要になってきたので導入
  • 画面が分かれ始めたのでreact-routerも導入

2018年10月

  • 脱React Native for Web
    • Atomic Design本を読んでCSSを書いていたら、少しCSSが書けるようになってきた
    • RN for Webのコンポーネントが出力するCSSを参考にして、Flexbox縛りのReactコンポーネントを作ってみたら結構それだけでレイアウトできることがわかった
    • 結果的にRNコンポーネントと素のReactコンポーネントが混ざって気持ち悪くなってきた
    • 最終的にRNのCSSからパクれるところはパクって、RN依存を解消した
    • WebでネイティブっぽいUIを実装する例としてとても参考になったので、ネイティブ出身者はRN for Web入れて組んでみてから最後は抜く、というのは結構ありかもしれない
  • UIを粛々と作る
    • 仕事がどんどん忙しくなってきていたが、なぜか週末にやっているこの個人プロジェクトも捗り始めた。テスト前メソッド?
  • create-creact-app本家がv2.1でTypeScript対応したのでreact-scripts-tsから乗り換え

2018年11月

  • ここでようやくGitHubのプライベートリポジトリに上げた
    • それまで個人マシンのローカルで開発していた
    • 会社で遊んでしまうのを防ぐため…
  • redux-saga導入
    • redux-thunkでがんばっていたが、シェア数のクローリングが複雑だったのでそこだけ導入
    • 学習コストは高いが、複雑な非同期処理を管理するにはとても理にかなっていると感じる
      • 非同期処理と処理の間でキャンセルとかできるのが地味によい
    • 自分は非同期処理が複雑になるまでは導入せず、必要になったら局所的に導入するのがいいんじゃないかと思う
      • 全部sagaにするのはRxと同じ危険な臭いを感じる
  • 利用規約の整備
    • ログインがあるので、規約とプライバシーポリシーは要りそうと思って調べ始めた
    • 定番である利用規約の本を読んで勉強。付録のひな形を作って規約を初めて自分で作った
    • id:a-know さんのエントリも大変参考になった
    • 結果的に自社や他社サービスの規約の読み方もわかるようになって、とても有意義だった

良いウェブサービスを支える「利用規約」の作り方

良いウェブサービスを支える「利用規約」の作り方

  • 本番環境の構築
    • firebaseのプロジェクトをもう一つ作るだけ
    • 現在は開発環境と本番環境の2プロジェクトで運用中(Firebaseの設定リポジトリにあります)
  • CircleCIの導入
    • Cloud FirestoreのルールをCIしたかった
      • 自分はソフトウェアのテストにはモチベーションが薄い方だが、こういう肝の部分はさすが欲しくなる
    • CircleCIデプロイも整備
      • masterへのmergeで開発環境へ自動デプロイ
      • 人間がCircleCIでapproveすると本番へもデプロイ
  • ホスティングはFirebase Hosting
    • Netlifyも良さそうだったが、既にFirebaseのセットアップをしてしまっていたのでそのままになっている
      • NetlifyはDynamic Renderingしてくれるオプションがあるらしいので、試してみたい気持ちもある
  • ドメインの購入
    • 今年できた.appドメインで行こうというのは前から決めていた
    • feedback.appが欲しかったが、当然取られていたので長いがblog-feedback.appにした
    • 自分は造語の名前を付けるのが苦手。たぶんPerl育ちだからだと思われる

2018年12月

  • 新規登録フローを整備
    • 知人に使ってもらったところ、いきなりブログのURLを入れさせるところで面食らっていたので、とりあえず一休の開発ブログとこのブログのURLを一発で入れられるボタンをつけて、お試しですぐ使えるようにした
  • 紹介動画を作成
  • OGP、Twitter Card設定
  • Google Analytics導入
  • リリース!
    • 全然話題にならず落ち込む
  • OSSとしてコードもGithubに公開
    • Friebaseのキーとか晒して良いものか少し悩んだけど、最終的にJSに埋め込まれて公開情報になるから同じだと判断
    • 実際漏れても問題無いようになっている
      • その代わりCloud Firestoreの設定はガチガチに固めておいた方が良さそう(任意のカラムにデータを突っこまれたりしたら困る)
      • Firebaseの管理者権限がないとデプロイはできないので安心
      • CircleCIからのデプロイはFirebaseの管理者tokenを発行して設定

  • Twitterの反応から想定していなかったケースを拾って実装
  • 追加で実装する予定だった機能を実装
    • はてなスター対応
    • Pocket対応
    • count.jsoon対応
      • これは前のネイティブアプリ時代から要望があったもの。ようやく対応できた

リリースした結果

  • 前回のネイティブアプリ時代は100円の有料アプリで約1000ダウンロードくらいだった
  • 今回はまだ登録ユーザー50人で泣ける
  • ぜひ使ってみてください!
    • 使われるほどFirebaseのお金はかかるんだけど、このユーザー数はちょっと寂しい
  • ネイティブアプリでは何だかんだ言ってAppStoreの存在が大きかったと感じる
    • 有料ソーシャルカテゴリというスカスカのカテゴリで10~20~位くらいに居座っていたので、そこから流入があった
    • 審査とかリリースプロセスとか色々だるかったけど、個人開発者への恩恵は結構あったんだなーと今更ながら実感
    • Webアプリだとランディングページ作らないといけないのか!というのも作り始めてから逆に気づいて新鮮だった

PWAのユーザー体験

  • ユーザー体験的にはほぼネイティブと同等のものができた(気がする)
    • BlogFeedbackはほぼ見るだけのアプリ、かつインタラクションもそこまで多くなかったのでそう感じるのかも
    • 同じようにツール系かつ使用頻度がそこまで高くないものはPWAに向いているのかもしれない
  • ニュースアプリとかのメディア系やEC系ならPWAはアリだと思う
    • 難があるのは他アプリからの写真共有とか、投稿周り
    • ユーザーに投稿させるサービスは当分ネイティブ優勢かも

ネイティブアプリ開発者(俺)にとってのPWA

  • ネイティブアプリ開発者がPWA開発できるのか?→全然可能
    • ネイティブアプリで設計力を鍛えている人は画面の構築方法さえわかればすぐに活躍できそう
    • TypeScriptは必須
  • しかし開発にかかるコスト自体はネイティブとそんなに変わらない印象
  • ネイティブ開発者が馴染みやすいのはVueよりReactだと思う
    • 前述のstyled-componentsの存在とTypeScriptとの親和性
    • マークアップをデザイナーや専門家に任せられるならVue、プログラマーがやるならReactという棲み分けになるのかな?
    • SSRしたいとかは今回の要件にはなかったので、検討範囲外
  • アニメーションの実装に課題感
    • CSSアニメーションでいけるところはCSS
      • 例えばボタンがキラキラ光るところはCSS
    • それ以外はセオリーがよく分からないままreact-motionというやつでやっている
    • チューニングしていないのでカクつく時も結構ある
      • iOSネイティブはすぐにサクサク動いて楽だったな…
  • ナビゲーションの設計はTwitter Liteを参考にした
    • この辺りは自由に設計できてしまうWebの方が大変
    • TwitterとかGoogleとかを参考にしながら作ることになる
    • Material DesignやBootstrapに乗ればこの辺は楽できそう
  • iOS Safari辛い
    • iOS SafariのAdd to home screenにはだいぶ問題がある
      • 他のサイトに飛ぶともうPWAに戻って来れなくなるので、BlogFeedbackはシングルサインオンが死んで全く使えない 😇
    • 原因は追えていないが、Service Workerのキャッシュが時々壊れるのでSafariではオフにした
    • みんな待ってるプッシュ通知
    • PWA試したいなら今はAndroid買う方が幸せになれる
  • (PWA関係ないけど)Firebase Cloud Firestoreは強烈なパラダイムシフトだと感じた

BlogFeedback使ってみて欲しい!

よろしくお願いします!🙏 🙏 🙏