こんにちは、スタディプラスの須藤(id:kurotyann)です。 タイトルどおり、9/17にFlutterとFirebaseで新しいサービスをリリースしました。
サービス名は「ポルト(Porto)」です。 受験生に人気の参考書を月額980円でスマホで読める電子参考書サービスです。 iOSとAndroidで利用でき、無料で読める参考書もあります。受験生でない方も試しにインストールしてみてください。
apps.apple.com【公式】ポルト 参考書読み放題サービス【14日間無料体験のお申し込みはこちら】
さて、リリースされたばかりのポルトですが、今回のブログでは以下の3点を書きます。
- 「(1) 技術スタック」
- 「(2) 開発期間」
- 「(3) FlutterとFirebaseで開発を考えている人へ」
なお、技術の詳細や知見は、今後のFlutterやFirebase関連のMeetupと、12月のアドベントカレンダーで共有する予定です。
今回のブログの目的は、FlutterとFirebaseというホットな技術の採用事例の共有です。
(1) 技術スタック
ポルトには、3つのプロダクトがあります。
- iOSとAndroidのモバイルアプリケーション
- データ(参考書 etc)をFirebaseにインポート・エクスポートするスクリプト
- ランディングページ(LP)とクレジットカードの登録フロー(クレカ登録)をもつWebアプリケーション
ポルトは月額980円のサブスクリプションサービスです。スマホアプリでサブスクリプションの登録はできず、Webサイトで登録します。つまり、NetflixやSpotifyと同じくスマホアプリには課金登録がないサービスです。
そして、1. と 2. は同じリポジトリでコードを管理したので、GitHubのリポジトリは全部で2つです。
iOSとAndroid、データのインポート・エクスポート
まずは、スマホアプリの技術スタックです。 GitHubのCodeタブがわかりやすいので、そのスクショを使って説明します。
Dartの割合は、ほぼ100%です
JavaScript 7.2%は、データのインポート・エクスポートのコードです。Firebase Admin SDKのNode.jsで書いています。TypeScriptで書けてないのは私の力不足なので、今後の課題です。そして、Ruby 1.1%はfastlaneのコードです。
つまり、データのインポート・エクスポートを別リポジトリで管理していれば、Dartはほぼ100%になります。SwiftとKotilnを書いたのは、弊社のStudyplus SDKを利用するために、Flutter Plugin Packageを書いたときだけです。
iOSとAndroidを開発するときはAndroid Studioを使い、データのインポート・エクスポートを開発するときは、IntelliJ IDEAを使っています。
当初はIntelliJ IDEAだけで開発しようと試みましたが、IntelliJ IDEAのFlutterプラグインが不安定なため断念しました。
ただ、iOSとAndroidの開発とデータのインポート・エクスポートを同時に開発することは、稀だったので開発効率には、ほとんど影響はなかったと思います。
バックエンドはFirebaseで固めた
見ての通り、Firebaseを使いまくっています。FlutterとFirebaseの相性はとても良く、公式プラグインはだいたい存在します。
公式プラグインの安定性は、十分に利用できる安定性です。まったくデグレなく安定してるのかと言われるとそうではなく、発展途上な部分やバグはあります。しかし、利用した方が圧倒的に便利で安全だと言ってよい性能です。
公式プラグインで利用しなかったのは、Firebase Crashlytics です。ポルトでは、iOSのみビルドがうまく通らず、クラッシュの解析はSentryに任せてしまいました。ただ、Dartの割合が大きいためSentryだけで、なんとか解析は進められないかと考えています。これも今後の課題の一つです。
Webサイト(LPとクレカ登録)
次は、Webサイト側の技術スタックです。
Nuxt.jsとFirebase Hostingを使いました
Nuxt.jsの nuxt generate
で静的なウェブアプリケーションを生成して、成果物をFirebase Hostingへデプロイしています。iOSとAndroidのユーザーでログインする必要があるのと、StripeのAPIを呼ぶために、こちらでもバックエンドはFirebaseです。
クレジットカードの登録はStripeのBillingです。Stripeとの連携はFirebase functionsを使って実現しています。APIの呼び出しは onRequest
ではなく、SDK経由の onCall
です。一方、StripeのWebhookと連携する場合は、onRequest
です。
StripeとFirebase functionsの実装は試行錯誤があったので、今後どこかで発表したり記事にまとめたりして、ほかの開発者の意見を聞きたいところです。
CI/CDを同じ技術スタックで統一した
スマホ側と同じく、Web側もCircleCIとfastlaneでCI/CDをまとめました。弊社がCircleCIで一本化していることと、私がfastlaneに慣れていることが理由として大きいです。
fastlaneはiOS、Android、Webの細かいCI/CDフローを全て担ってくれたので、個人的にこの構成に満足しています。
(2) 開発期間
開発期間も、GitHubのInsightsタブがわかりやすいのでスクショで説明します。 モバイルとWebの両方を縦に並べてみました。
開発期間は2月~9月(モバイル)と、6月~9月(Web)
Flutter 1.0.0の公表は、2018年12月4日のことでした。このとき、私はポルトの要件定義とプロトタイプを開発していました。当時のプロトタイプは、iOSのみでSwiftとFirebaseという構成でした。
当初は、iOSを先にリリースして、Androidは後からリリースする計画でしたが、同時にリリースしたいという要望が出てきました。このとき私には、Androidの開発経験がありませんでした。さらに弊社のAndroidエンジニアをStudyplusの開発から、新規事業のポルトへコンバートするのは、人数と計画から考えて難しい状況でした。
そこに、Flutterを個人で触っていたAndroidエンジニアの若宮(id:D_R_1009) が「Flutterなら開発できるかもしれない」と、アドバイスをくれたのがきっかけで、2月からFlutterでの開発をスタートしました。
フルタイムでポルト(Flutter)に関わったのは6月から
2月から9月の約8ヶ月間ですが、フルタイムで開発をスタートできたのは、6月からです。5月に大石(id:k_oishi)が入社したことで、iOSの開発をバトンタッチして新規事業へフルコミットすることができました。それまでは、Studyplus iOSの開発と採用活動を同時に行っていました。
開発スピードが求められる新規事業でありながら時間がかかっているのは、このような社内の人員状況が原因です。また弊社の新規事業部は、私と竹内の他に営業とコンテンツ制作を担当する2名の社員がおり、合計4名の社員でポルトを開発しました。
FlutterとFirebaeを採用してスピーディな開発を検討している方は、弊社のこのような状況を考慮した上で検討してもらうと良いと思います。
Webサイトはデザイナーと共に開発
デザイナーの竹内が5月に入社して、Nuxt.jsでのWeb開発を6月からスタートしました。Nxut.jsで開発することは、エンジニアの私ではなくデザイナーの竹内が希望しました。
まずは、ランディングページ(LP)の作成と全体のレイアウト構成を竹内が行い、7月ごろから私がFirebaseの連携と、クレジットカード登録フローを開発しました。
竹内は名古屋からのリモート勤務であり、東京のオフィスに来るのは月に1度だけです。コミュニケーションはSlackとZoomを使っています。
スピードが求められる新規事業でリモート開発は難しいのではと不安もありましたが、結果的に開発は間に合いました。
(3) FlutterとFirebaseで開発を考えている人へ
最後に、ここまでの説明をもとに「弊社と同じようにFlutterとFirebaseで開発を考えている人」へいくつか共有したいことを書きます。
- Flutterを使えば、ほぼDartを書くだけでiOSとAndroidのネイティブアプリが開発可能です
- Flutter用のFirebase公式プラグインは十分に利用できる性能だと思います
- Flutterの利用者が国内外で増えているのをissueの数や、検索でヒットする良記事の数で感じます。なので困ったことがあっても、なんとかなりますし、なりました
最後に
サービスのリリースは、ゴールではなくスタートです。
多くのユーザーの要望に応えられるサービスへ成長できるよう、これからも開発を続けていきます。