1人で「Webアプリ＋ iOS & Android モバイルアプリ＋サーバー処理」を実装するための知見

<!------------------------------------------------------------------------->

# **1. はじめに - この記事について**

この記事は 「`Ionic(Cordova)`を利用したハイブリッドアプリ」と「mBaaSクラウドサービスの`Firebase`」を取り扱った記事となります。

Webアプリ&Mobileアプリ開発の検討をしている方を対象に記載しましたので参考になれば幸いです。

## 1.1 ざっくり記事の内容

* 「採用した技術」と「採用しなかった技術」の理由について
* Windows環境からの「iOSアプリのビルド」と「Appストアへのアップロード」について
* Appleの審査について

## 1.2 対象読者
この記事は以下の方を対象に記載しました。

* 何かしらの開発経験はあるけど、これからWeb＆モバイルのアプリ開発を新たに始める方
* 現状の開発環境を見直したい方
* アプリを作りたい！でも人が足りない！

<!------------------------------------------------------------------------->

# **2. どんなアプリか**
Web,iOS,Androidで動作して**自動的に各端末でデータを同期する**メモ帳アプリを作成しました。
同様のアプリとしてGoogle KeepやEvernoteなど優れたメモアプリは山ほどありますが、アプリ作成の練習も兼ねて今回はメモ帳アプリを題材にしました。

![利用イメージ.jpg](https://qiita-image-store.s3.amazonaws.com/0/67192/69b47d88-0854-c7b8-14cf-2cc375f54003.jpeg)
例えば、出先でスマホにメモした内容を自宅や社内のパソコンで確認・編集できます。

## 2.1 どうやって実現したか

1つのプロダクションで`SPAなWebアプリ`[^1]と`iOSアプリ`と`Androidアプリ`と`サーバー処理(API)`を作ることになった場合、人的リソースが有り余っているならJavaScriptでWebアプリ、SwiftでiOSアプリ、JavaやKotlinでAndroidアプリ、PHP/Ruby/Python/Node/Java/ASP.NETなどでサーバー処理(API)、とそれぞれオフィシャルな環境で作ることは可能かと思います。

しかし、これら4種(Webアプリ,iOSアプリ,Androidアプリ,サーバーAPI)を**1人でそれぞれ実装することは現実的ではない**ため私は以下のように、「(1) Ionicフレームワークを使用したハイブリッドアプリ構成」と、「(2) mBaaSサービスのFirebaseを利用した構成」としました。

要件的には`Webアプリ`と`iOSアプリ`と`Androidアプリ`と`サーバー処理`の4つが必要ですが、**1つのソースコードプロジェクトだけで実現したシンプルな構成となっています。**

### **(1) Ionicフレームワークを使用したハイブリッドアプリ**

![開発構成.png](https://qiita-image-store.s3.amazonaws.com/0/67192/33dbbe26-ee90-222a-53ad-b7b637bb5e90.png)

`HTML & TypeScript & SCSS`でプログラミングして、`Ionic CLI`にてトランスパイル&バンドルを行って**`Webアプリ`**を生成し、同じく`Ionic CLI`を使用して**`iOSアプリ`**と**`Androidアプリ`**を生成します。

### **(2) mBaaSサービスのFirebase**

クラウドには`Firebase`の`Firestore`を使用しています。

クラウド上にデータを置くことによりWebアプリとiOSアプリとAndroidアプリのすべての端末で共通のデータを参照しています。
なお、オフラインの場合はローカルにデータを保持してオンラインになった際に自動的に同期します。

![ユーザーとサーバーの関係図.png](https://qiita-image-store.s3.amazonaws.com/0/67192/c998009b-fbf6-c625-169e-ba1eb7527601.png)

サーバー側の処理はセキュリティ設定のルールファイルを書いたぐらいでAPIの処理は一切書かずに実現しています。

[^1]: SPAとは Single Page Application の略で、1つのページのみから構成することで、スマホアプリやデスクトップアプリのような操作性を提供するWebアプリです。


<!------------------------------------------------------------------------->

# **3. 採用した技術(ライブラリ)**
利用するライブラリは今後も長くメンテされそうで、かつWeb上に日本語の情報が多く**自分以外の人がアプリのメンテを行うことになっても問題ない技術**を基準に選定しています。

## 3.1 [**Ionic Framework**](https://ionicframework.com/) v3.20
iOS/Androidの画面デザインと挙動に対応したUI･UXコンポーネント環境と、WebアプリのビルドやiOS/Androidアプリへのビルドを実行するCLI環境です。

Ionicの内部では大まかに以下の技術が使われています。

* [**Angular**](https://angular.io/) v5.2：
Googleが開発・メンテしているSPA(シングルページアプリケーション)のフレームワークです。基本的に `TypeScript + HTML + SCSS`を使ってコーディングして、`JavaScript + HTML + CSS` にトランスパイル(変換)します。

* [**TypeScript**](http://www.typescriptlang.org/) v2.6：
Microsoftが開発・メンテしているプログラミング言語です。JavaScriptに対して静的型付けとクラスベースオブジェクト指向を加えた感じです。設計思想的にはC#に近い言語です。

* [**SCSS**](http://sass-lang.com/)：
CSSを構文的にイケてるように拡張した言語で、CSSを知っていればすぐに馴染めると思います。

## 3.2 [**Cordova**](https://cordova.apache.org/) v7.1
WebアプリからiOS/Androidに対応する実行ファイルを生成します。
Cordovaを利用することで1セットのソースコード (JavaScript/HTML/CSS) からiOS用、Android用のアプリを生成することができます。
Ionic-CLI経由でCordovaを使うことになるため、Cordovaのコマンドを知らなくてもさほど問題ありません。

 * [**cordova-android**](https://github.com/apache/cordova-android) v6.4：
Androidアプリのビルドエンジンです。

 * [**cordova-ios**](https://github.com/apache/cordova-ios) v4.5：
iOSアプリのビルドエンジンです。

 * [**cordova-plugin-googleplus**](https://github.com/EddyVerbruggen/cordova-plugin-googleplus) v5.2：
端末のネイティブなGoogleログイン機能を提供するプラグインです。

## 3.3 [**Firebase**](https://firebase.google.com/?hl=ja) v4.12
クラウド上のデータを参照・変更するために「Firebase」を使用しています。
FirebaseはGoogleが開発・運用しているmBaaSサービスです。
Firebaseには無料プランもあります。[Firebase利用料金へのリンク](https://firebase.google.com/pricing/?hl=ja)


<!------------------------------------------------------------------------->

# **4. 採用しなかった技術(ライブラリ)**

今回使用しませんでしたが、検討した類似技術(ライブラリ)を紹介します。
それぞれ比較する粒度が異なり分かりにくいかもしれませんがガシガシ記載していきます。
なお、**採用しなかった理由を太字で記載しています。**

## 4.1 **[Microsoft / Blazor](https://github.com/aspnet/Blazor)**
Microsoftによって開発・メンテされているC#でフロントエンドWebアプリを作れる実験的な.NETフレームワークです。

* `WebAssembly`というWeb標準技術を使っているためSilverlightやFlash等のようにブラウザにプラグインを追加しなくても動きます。
* ただしBlazor自体がまだまだ実験段階で、**ビルド後のアプリサイズが大きすぎて実用的なWebアプリとしてはツライ**ところがあります。
* AoTコンパイル等の圧縮技術が[実装予定](https://github.com/aspnet/Blazor/issues/26)みたいなので、実装されたらもうちょっと遊べそうです^^
* Blazorについては以下のjsakamotoさんの記事が参考になりました。

> @jsakamoto さんのQiita記事:
> [C# で Single Page Web Application が書ける Blazor が凄かった件](https://qiita.com/jsakamoto/items/20d4893f6c8cdb0356f6)

## 4.2 [**Microsoft / Xamarin**](https://www.microsoft.com/ja-jp/dev/campaign/vs-xamarin.aspx)
Microsoft社の子会社であるXamarin社によって開発・メンテされているiOS/Androidアプリを作成できる.NETフレームワーク環境です。

* C#を使ってiOS/Android/Windowsのアプリが作成できます。しかし**Webアプリが作れません。**
* 上記の`Blazor`と組み合わせて使えるようになったら楽しそうです。

## 4.3 [**Facebook / React Native**](https://facebook.github.io/react-native/)
Facebookが開発・メンテしているJavaScriptフレームワークです。

* Ionic(Cordova)でのWebViewによる描画と違い、ネイティブのUIコンポーネントを使うためパフォーマンスが高いです。
* ただ、**個人的にReactのViewに関する構文が性に合わなかった**ため触ったことがありません。世間では人気のあるフレームワークです。
* 以下の @tuttieee さんの記事によるとロジックを共通化して、ViewをWebとMobileで分けるやり方ができるようです。

> @tuttieee さんのQiita記事:
> [ReactとReact Nativeでコードを共通化し，web / android / iOS (+PC)クロスデバイス開発](https://qiita.com/tuttieee/items/7c66691fe6cc244053de)

## 4.4 [**Asial / OnsenUI**](https://ja.onsen.io/) v2.8
iOS/Androidの画面デザインと挙動に対応したUI･UXコンポーネントです。

* ネイティブなiOSとAndroidのデザインガイドに準拠したデザインと機能を持っています。
* ドキュメントがほぼ日本語に対応していて、AngularJS,Angular,React,Vue.jsに対応した柔軟なフレームワークです。
* はじめはIonicの代わりに`OnsenUI + Angular`の構成で開発していましたが、タブレット・PC向けの対応ができなくはないけど微妙なことと、**Ionicのほうが完成度が高くやりたいことが簡潔に書けてCLI対応(Ionic-CLI)やプラグイン対応(Ionic-Native)がそろっていて便利でしたので移行しました。**

## 4.5 [**vuejs.org / Vue.js**](https://jp.vuejs.org/index.html) v2.5
Vue.jsはGoogleの Evan You という方が開発した軽量なJavaScriptフレームワークです。

* TypeScriptでも書けて、さらにクラススタイルで書きたい場合には別途公式の`vue-class-component`ライブラリを使用することで可能です。
* Vue.js単体であればかなり軽量ですが、`Vue.js + TypeScript + vue-class-component + OnsenUI + などなど`を使うとアプリ起動時間が長くなってしまい、**Angular-AoTコンパイル構成の方が起動時間が短縮できたため利用をやめました。**(私の実機環境で初回起動が8.2秒から4.1秒に短縮されました)

## 4.6 [**riotjs.com / Riot.js**](http://riotjs.com/ja/) v3.8
Riot.jsは軽量なJavaScriptのViewライブラリです。

* 個人的に`TypeScript`と`UIライブラリ`は外せなかったため、頑張って`Riot.js + TypeScript + OnsenUI`構成を試して動作可能なところまで持っていけましたが、ネット上にこの構成の前例がなさすぎることとOnsenUIはRiot.jsに対応していないため無理くり対応したことで**別の人が触るのに厳しい環境となったため利用を諦めました。**

<!------------------------------------------------------------------------->

# **5. 開発環境について**

開発・デバッグ環境としてWindows + Androidを使用して、iOSアプリのビルド用にMacを使用しています。

![開発環境.png](https://qiita-image-store.s3.amazonaws.com/0/67192/0358e479-25e9-19c8-5ac8-f09dd2a585fc.png)

**「iOS向けのビルド」や「Appleストアへのアップロード」にはMacが必要**になります。クラウドでiOSアプリのビルドを提供しているサービスなどもありますが、Appleストアへの代理アップロードには対応していなかったり別途料金が必要だったりするので注意が必要です。

## 5.1 **Windows 10 64bit**
* メインの開発環境にWindows 10 64bit を使用
* エディタは `Visual Studio Code` v1.22 を使用
* 開発時はAndroid端末と接続して実機デバッグしています

環境構築は「[[Ionic3] 開発環境の構築からAndroid実機デバッグまでの手順まとめ](https://qiita.com/alclimb/items/a266871625f1227f425d)」にまとめました。

## 5.2 **macOS High Sierra 10.13** - Mac mini (Mid 2010)
* 「iOSアプリのビルド」と「Appleストアへのアップロード用」の環境
* 中古で`Mac mini (Mid 2010)`を &yen;29,880円 にて購入。CPUは`Core 2 Duo 2.4 GHz`と今の時代では貧弱ですが、最新のmacOS High Sierra環境にできて安いMacを探した結果これになりました
* 古い機種ですがメモリは8GBでHDDからSSDに換装しているので割とサクサク動作しています

初期状態のOSは `Mac OS X 10.6 Snow Leopard` だったはず。ここから最新の `macOS High Sierra 10.13` までアップデートするのには意外と罠が多く骨の折れる作業だったと記憶しています。
これに関して記事を書けば良かったのですが記録し忘れていました。

## 5.3 **Ubuntu 16.04 LTS**
* Dockerのホスト環境
* DockerコンテナとしてGitLabを運用
* いずれGitLab-CIを使用してMacと連携した自動ビルド環境を構築したいと企んでます

<!------------------------------------------------------------------------->

# **6. ビルド環境について**

私はメイン開発環境としてWindowsを使用しているのでiOSアプリのビルドとアップロードができないため、別途何かしら対応する必要がありました。
**最終的にはビルド用のMac環境を用意することで落ち着きました**が、そこに行きつくまでの知見を時系列順に記載します。

## 6.1 Microsoft / Visual Studio App Center クラウドサービス
Microsoftがクラウド上で提供するビルド、テスト、デプロイ環境です。

* とりあえず試したところ、**Ionic(Cordova)のビルドには対応していませんでした。**
* Cordovaのプロジェクトは作成可能なのですが、自動テストやPush通知、クラッシュレポートの管理などができるだけで肝心のビルドはできないようです。

## 6.2 Adobe / PhoneGap Build クラウドサービス
Adobeがクラウド上で提供するビルド環境です。

* Cordovaプロジェクトのビルドができます。
* 無料プランはプライベートアプリを1つまでしか扱えません。
* 有料プランで契約しようとしたところ、**日本では`PhoneGap Build`の単体契約できなくなっていました。**(以前はできました)
* Adobeに問い合わせたところ、`Adobe Creative Cloud`の高額な有料プランに加入することで使えると回答を頂きました。(値段は忘れました)

## 6.3 Microsoft / TACO ソフトウェア
メンテは終了していますが、Microsoftが開発したWindows環境から自前のMac環境にリモートビルドを行えるソフトウェアです。

* 自前でmacOS環境を用意する必要があります。
* Windows側からコマンド1発でMac側でリモートビルドができます。
* **扱っていた当時は私の知見不足によりアプリの署名関係がうまく自動化できませんでした。**
* リモートビルドでMac側に転送されたプロジェクトをXcodeで開いて手動でビルドしていた記憶があります。
* 今思うと署名関連の設定ファイルである**`build.json`を正しく作成できていれば問題なく使えるツールだと思います。**

## 6.4 Asial / Monaca クラウドサービス
Asial社がクラウド上で提供している、クラウド開発&ビルド環境です。

* 非常に簡単にiOSアプリのビルドができます。
* フリープランだとCordovaのサードパーティープラグインが使用できず、リモートビルドは3回/日までです。
* 有料プランは以前より安くなりましたが**1ユーザー2,000円/月～と結構高額なので利用をやめました。**
* AppleのAppStoreへの代理アップロードに対応していますが**別途料金が必要**です。

## 6.5 Microsoft / VSTS-CI (Visual Studio Team Service - CI) クラウドサービス
Microsoftがクラウド上で提供するビルド、テスト、デプロイ環境です。

* 自由度が高く割と何でもできそうです。CordovaプロジェクトはiOS/Androidどちらもビルドできました。
* ただ、できることが多いので扱いが難しいです。
* 当初5ユーザーまでなら無料でCI使いたい放題！と思っていた時代が私にはありました。
* 実際には**240分/月までの利用制限があったので利用をやめました。**
* 料金は公式ページのわかりにくいところにコッソリと記載があったはずですが、今改めて探しても見つからん・・・(\*'ω'*)

## 6.6 ビルド用のMac環境を用意
現在のビルド構成です。自前でMac環境を用意して、ビルド環境を構築しました。

* 現在はメイン開発環境のWindows側で編集したソースコードをMac側で取得して、手動でビルドコマンドを実行しています。
* 現状ビルド処理はCUIで完結しているため、今後GitLab-CIを利用してWindowsからgitにpushしたら自動ビルドできるように検討中です。
* 構築は面倒ですが**長い目で見れば一番コストがかからない方法**だと思います。

<!------------------------------------------------------------------------->

# **7. Appleの審査について**

今までiOS向けのアプリは作りかけた経験はあったのですが、実際にAppleにアップロードして審査を行ってもらうのは今回が初めてでした。

噂では「厳しく、理不尽で、時間のかかる」審査という事前情報を得ていたのですが、とりあえず審査申請してみたところ噂通り(笑)「[審査ガイドライン](https://developer.apple.com/jp/app-store/review/guidelines/)が決められており審査は厳しく、若干理不尽な対応を受けつつ、レスポンスは3-4日ぐらい」でした。

> @WattさんのQiita記事:
> [理不尽なリジェクトを受けたiOSアプリが公開されるまでの経緯](https://qiita.com/Watt/items/49d65b6377c1a44e670f)

私は審査で3回リジェクト(審査NG)をもらいましたが最終的に無事にリリースできました。

## 7.1 リジェクト1回目

* Guideline 1.5 - Safety - Developer Information
 * **アプリのサポートURLが無効**とのことでNGとなりました。
 * 連絡先を記載した簡単な[サポート用Webサイト](https://support.wehub.fun/)を作成しました。
* Guideline 2.3.10 - Performance - Accurate Metadata
 * アプリ内に関連性のないWebサイトへのリンクがあるとのことでNGとなりました。
 * 今回作成したメモ帳アプリはiOS以外にWebアプリとAndroidアプリに対応しているためそれぞれの入手先のURLをアプリ内に記載していたのですが、それがNGだったようです。
 * ガイドラインによると「許可を得た特定の相互作用的機能がある場合を除き、**他のモバイルプラットフォームの名前は出せない**」だそうです。
 * 関連はあるため審査員に掛け合えば通ったかもしれませんが、~~面倒だったので~~ いち早くリリースしたかったのでiOSではWebアプリとAndroidアプリのリンクを非表示になるように修正しました。

## 7.2 リジェクト2回目

* Guideline 2.3.10 - Performance - Accurate Metadata
 * アプリの**ログイン画面に他のプラットフォームの名前があるとのことでNG**となりました。
 * ログイン画面にあった「Androidとも自動的に同期する」との文面で弾かれたようでしたので該当部分の文章を削除しました。

## 7.3 リジェクト3回目

* Guideline 1.5 - Safety - Developer Information
 * プチ理不尽体験ですが「サポート用Webサイトが目的の場所に適切にナビゲートしません。」といった非常に**曖昧な内容で審査NG**となりました。笑
 * 「連絡先書いてあるけど何が問題なのか。具体的な対策を教えてほしい」と問い合わせたところ、そのまま無事に審査OKとなりました。

# **8. 技術的な記事**

今回の制作したアプリに関連する技術的な記事は以下に分けて記載しました。

### 8.1 Ionic関連
 * [[Ionic3] 開発環境の構築からAndroid実機デバッグまでの手順まとめ](https://qiita.com/alclimb/items/a266871625f1227f425d)
 * [[Ionic3] 1つのアプリアイコン画像から複数サイズのアイコンサイズを一括で作成する方法](https://qiita.com/alclimb/items/c6d0cf6d8c707f8b2540)
 * [Ionic3のiOSアプリでステータスバーのオーバーレイ表示をしない方法](https://qiita.com/alclimb/items/111ad9624a5aa0974f8e)
 * [Ionic3でiOSビルド時に「Error: Command failed: xcrun simctl list --json」エラーが発生した時の対処方法](https://qiita.com/alclimb/items/791f5013844e1a13c5af)

### 8.2 VSTS-CI関連
 * [Windows環境からCordova-iOSアプリがビルドできるVSTS-CIが凄い！と思ったらガッカリした話](https://qiita.com/alclimb/items/7c3eff59049a9c37c91c)
 * [VSTS-CIのCordova-iOSビルドで「 Error code 65 for command: xcodebuild」や「Error code 70 for command: xcodebuild」エラーが表示された時の対処法](https://qiita.com/alclimb/items/dad92b57c247fc820048)
 * [VSTS-CIのCordova-iOSビルドで「Error: Please specify a build.json file」エラーが表示された時の対処法](https://qiita.com/alclimb/items/67c2f2d54d45602e8577)
 * [VSTS-CIのCordova-iOSビルドで「TypeError: "file" argument must be a non-empty string」エラーが発生した時の対処法](https://qiita.com/alclimb/items/ff376fb88f399b777507)
 * [VSTS-CIのCordova-iOSビルド後のArtifactで「[error]Could not find file '\*\*\*\*/platforms/ios/build/device/\*\*\*\*.app'.」エラーが発生した時の対処法](https://qiita.com/alclimb/items/15b7135f9cd130dd3def)

### 8.3 Macでのビルド関連
 * [「codesignは、キーチェーンに含まれるキー"privateKey"を使用して署名しようとしています。」ポップアップを表示しないようにする](https://qiita.com/alclimb/items/81fdb5aa94f47aca1fe4)

# **9. 最後に**

ここまで読んでいただきありがとうございます！
この記事では採用した技術とは別に検討した他の技術も記載しているため、その辺が参考になれば幸いです。

次回は、ゲームアプリについて記事を書ければと思います(\*'ω'*)

---