Flutter-boot を利用し 1 分でハイブリッドプロジェクトを構築する

#背景

Flutterは登場以来、クロスターミナル開発をリードしてきており、その実力を試す国内外の企業が増えています。Flutterには主に2つの開発モードが用意されています。1つ目はスタンドアロンアプリモードで、Flutterが主なコンポーネントとなり、ネイティブプロジェクトがFlutterプロジェクトに含まれます。2つ目のモードでは、Flutterが既存のiOSやAndroidのネイティブアプリに統合されたFlutterモジュールとしての役割を果たす。この場合、ネイティブプロジェクトは任意のディレクトリの下にあることができ、Flutter プロジェクトのアドレスとは関連付けられていないため、ネイティブプロジェクトのアーキテクチャでローカルの Flutter プロジェクトのアドレスを宣言する必要があります。

Alibaba Idle Fish アプリ（北京語では Xianyu）を開発したチームとして、私たちは長い間ハイブリッドアプリのアーキテクチャを使用しようとしてきましたが、Flutter がモジュールとして機能する前にネイティブプロジェクトにも多くの変更を加えました。Flutter モジュールモードが正式にリリースされた後、私たちは多くの研究を行い、最終的にハイブリッドプロジェクトのためのすぐに使える足場である flutter-boot をリリースしました。

*本ブログは英語版からの翻訳です。[オリジナル](https://www.alibabacloud.com/blog/constructing-hybrid-projects-in-just-one-minute-with-flutter-boot_595734)はこちらからご確認いただけます。一部機械翻訳を使用しております。翻訳の間違いがありましたら、ご指摘いただけると幸いです。*

#イントロダクション
本質的にflutter-bootは、ハイブリッド開発モードでの2つの問題、すなわちFlutterハイブリッド開発のためのプロジェクト設計とハイブリッドスタックを解決します。ここでは、flutter-boot がこれらの問題をどのように解決しているのかを見てみましょう。

まず、プロジェクト設計の問題を解決するために、flutter-bootは標準化されたプロジェクト作成プロセスとユーザーフレンドリーな対話型コマンドを確立しました。このプロセスが完了すると、ハイブリッド開発のための標準的なプロジェクト構造を手に入れることができます。このプロジェクト構造によって、Flutter と Native 開発の両方の視点を持つことができるようになります。Flutter は、ローカルな Flutter 開発とクラウドベースの Flutter 構築の 2 つの方法で統合することができます。両モードの基本構造を図 1-1 に示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647921/68e2cd24-75a6-dc9f-acbd-dafbb0f4ad88.png)

図1-1. flutter-bootの構造図

さらに、ハイブリッドスタックの問題を解決するために、flutter-boot はハイブリッドスタックの依存関係を自動的に注入し、重要なハイブリッドスタックのアクセスコードをネイティブプロジェクトにカプセル化して注入することができます。プロンプト通りに数行の簡単なテンプレートコードを挿入すると、ハイブリッドスタックが有効になります。

flutter-botを使って構築したハイブリッドプロジェクトは、作成してすぐに利用できるようになります。では、flutter-boot がこれらの問題をどのように解決しているのか、もう少し詳しく見ていきましょう。

#プロジェクトのデザイン
###「既存アプリにflutterを追加する」機能
flutter-bootのプロジェクトデザインを詳しく勉強する前に、まずはGoogleが提供している「既存のアプリにFlutterを追加する」機能を理解しておく必要があります。

既存のアプリにFlutterを追加する」機能では、Flutterをモジュールとして作成する方法を紹介しています。Flutterモジュールのプロジェクト構成は以下の通りです。

```
some/path/
  my_flutter/
    lib/main.dart
    .ios/
    .android/
```

公式のプロジェクト構造では、.ios と .android は Flutter を動かすためのテンプレートプロジェクトです。Flutter のプロジェクトディレクトリで実行すると、どちらのプロジェクトもアプリを起動するために使用されます。次に、ネイティブプロジェクトの関連付けを学ぶ必要があります。ここでは、関連付けをFlutterフレームワーク、Flutterビジネスコード、Flutterプラグインライブラリの3つに分けて説明します。Flutterプラグインライブラリは、Flutterプラグインネイティブ（プラグインネイティブコード）とFlutterプラグインダーツ（プラグインダーツコード）の2つに分かれています。ここでは、Flutterフレームワーク、Flutterプラグインネイティブ、Flutterプラグインダーツ、Flutterビジネスコードを含めた4つのパーツの違いを紹介します。

| Module | Number of modules | Content change frequency | Support for debugging |
|:--|:--|:--|:--|
| Flutter Framework | Unique | Low | No |
| Flutter Plug-in Native | High change frequency | Low | Yes |
| Flutter Plug-in Dart | High change frequency | Low | Yes |
| Flutter Business Code | Unique | High | Yes |


そのため、Flutter フレームワークは依存関係管理で宣言するだけで済みます。 Flutter プラグインネイティブはソースコードに直接組み込むことができるのに対し、Flutter プラグインのダーツはビジネスコードで参照された場合にのみ有効です。そのため、ビジネスコードと同様に、ダーツコードのデバッグモードと公開モードをサポートしなければなりません。その結果、ダーツコードの関連付けはアプリ構築プロセスに組み込まれ、ダーツコードの構築モードはアプリ構築モードによって決定されることになります。それでは、iOSを例に具体的な実装を見ていきましょう。まず、podfileファイル内にpodfilehelper rubyスクリプトのカスタムコールを追加します。この場合、podfilehelperはFlutter Frameworkの依存関係、Flutterプラグインのネイティブへの参照、ビジネスコードのパスを宣言します。次に、xcode のビルドフェーズで xcode_backend シェルスクリプトの呼び出しを追加して、ビルドプロセスに介入します。この場合、xcode_backend は現在のビルドモードに基づいてダーツのビルドプロダクトを生成します。

#Flutter-bootのメリット
公式のハイブリッドプロジェクト機能を使用すると、以下のような問題が発生します。

1.手動でのファイルや設定の追加に時間がかかる。
2.ネイティブプロジェクトを Flutter リポジトリで実行できない。
3.Flutter が独立したコードリポジトリとしてデプロイされている場合、リモートマシン構築はサポートされていない。
これらの問題を解決するために、ハイブリッドプロジェクトのデプロイを、flutter-bootscaffold の create、link、remotelink、update の 4 つのプロセスに分けています。

###create
create プロセスは、Flutter モジュールをビルドするために使用され、Flutter モジュールの作成と git リポジトリのデプロイが含まれます。Flutter モジュールの作成コマンドを呼び出す前に、基本的なチェックを行い、プロジェクトの場所と命名規則が公式の要件を満たしているかどうかを確認します。Git リポジトリのデプロイ時には、gitignore にあるファイルは無視されます。その間に、リポジトリの状態を確認します。リポジトリが空の場合は、直接ファイルを追加します。リポジトリが空でなければ、まずリポジトリを片付けます。

###Link
リンクプロセスは、ネイティブプロジェクトとフラッタープロジェクトの関連付けに使用されます。関連付けの際には、まずリクエストを開始して、Flutter プロジェクトとネイティブプロジェクトのアドレスを取得します。次に、スクリプトを使用して、公式プロセスで手動で統合しなければならなかったコンポーネントを自動的に統合します。ネイティブプロジェクトがFlutterプロジェクトの下で実行されるFlutter開発パースペクティブを使用するには、ネイティブプロジェクトをソフトリンクして、Flutterプロジェクトのiosとandroidのディレクトリにリンクさせます。Flutter を実行するには、まずプロジェクトの下にある ios または android ディレクトリに移動し、そこからネイティブプロジェクトを実行します。 Flutter プロジェクトの下で実行される iOS プロジェクトには制限があります。この問題を解決するには、ネイティブプロジェクトのプライマリターゲットをコピーして、"runner "という名前のレプリカターゲットを作成します。

同時に、リモートビルドモードをサポートするために、ローカルの Flutter リポジトリパスの宣言は、正確なビルドモードに応じて区別し、カスタムの依存関係スクリプトでカプセル化する必要があります。例えば、iOS プロジェクトでは、fbpodhelper.rb スクリプトファイルを追加する必要があります。次に、Flutter リポジトリのローカルパスを fbConfig.local.json 設定ファイルに追加します。

###Remotelink and Update
リモーテルリンク処理は、リモートビルドモードでFlutterリポジトリのコードを取得し、リモートマシン上でビルドする処理です。リモートビルドモードでは、依存関係の管理処理に介入する必要があります。依存関係を取得する際には、Flutter リポジトリのコードを引っ張ってきて、ネイティブプロジェクトの .fbflutter ディレクトリに配置し、このディレクトリをローカルの Flutter リポジトリのパスとして宣言します。このようにFlutterのコードを引っ張ってきてローカルにデプロイする処理を更新処理と呼びます。結果的に、これによりリモートのビルド処理はローカルのビルド処理と同じになります。

リモートモードとローカルモードを区別するために、リモートの Flutter リポジトリ情報を fbConfig.json に記録し、gitignore に fbConfig.local.json ファイルを無視するようにします。このようにすることで、ハイブリッドプロジェクトを開始したエンジニアはremotelinkを一度だけ実行するだけで済み、他の開発協力者はリモートビルドの設定プロセスを気にする必要がなくなります。

###Init
構築プロセスを容易にするために、initという名前のコマンドセットを提供し、必要なステップをコマンドラインインタラクションモードのinitコマンドに統合しました。

#Hybrid Stack
ハイブリッドスタックは、Flutter ハイブリッドプロジェクトにおいて、ネイティブページと Flutter ページ間の相互作用を調整するために Idle Fish が使用しているオープンソースのフレームワークです。現在、ハイブリッド開発モードでは主要なフレームワークとなっています。ハイブリッドスタックをオープンソース化した後、多数の開発者がハイブリッドスタックを統合すると、様々な環境構成が生成されたり、コードが追加されたりして、統合に支障をきたすことがあります。そこで、高速な統合を実現するためのソリューションを提供することにしました。高速統合を実現するためには、2つの問題を解決しなければなりませんでした。

1.Flutter とハイブリッドスタックのバージョン互換性
2.ハイブリッドスタックデモコードのカプセル化と挿入

##バージョンの互換性
現在サポートされているハイブリッドスタックのバージョンは 0.1.52 で、Flutter 1.5.4 をサポートしています。Flutter がアップグレードされると、それに合わせてハイブリッドスタックを適応させる必要があるため、統合されたハイブリッドスタックのバージョンを変更する必要があります。そのため、ハイブリッドスタックのバージョン構成をファイルで管理し、Flutter が必要とする現在のハイブリッドスタックのバージョンを記録しておく必要があります。flutter-boot の初期バージョンでは、ハイブリッドスタックのバージョン番号を制限しました。今後のバージョンでは、バージョン選択機能を提供する予定です。

##コードのカプセル化と挿入

ハイブリッドスタックの利用プロセスを見た上で、ハイブリッドスタックに必要なデモコードを4つの部分に分けてみました。

1.フラッターエンジンのホスティング
2.ページのルーティング設定
3.デモダーツのページ
4.ネイティブテストのリダイレクトエントリ

###フラッターエンジンのホスティング
エンジンホスティングでは、アプリの初期化に頼っています。初期化プロセスの複雑さはアプリの複雑さとともに増加するため、インターフェースとしてコードの行が追加されます。初期化中に、この行のコードを追加してホスティングを実装することができます。

###ページのルーティング設定とデモダーツのページ
識別子へのルーティングが設定されている場合、Flutter またはネイティブページは、対応するページを識別してリダイレクトする必要があります。ルート設定は、ネイティブ側とFlutter側の両方で展開する必要があります。ネイティブ側では、ハイブリッドスタックのデモルーティングコードを簡略化し、簡略化したコードをネイティブプロジェクトの固定ディレクトリに追加します。iOS でのみ追加されるコードファイルはビルドスコープから除外されるため、ファイル挿入用の iOS コード追加ツールをカプセル化しています。Flutter側では、main.dartファイルを上書きし、ルーティングロジックを提供するmain.dartファイルを統合し、デモダーツページの作成ロジックを提供します。

###ネイティブテストのリダイレクトエントリ
ハイブリッドプロジェクトのリダイレクトモードを素早く表示できるように、iOS と Android の両方に対応したエントリーボタンとボタン追加処理をカプセル化しました。これらを使用して、テストページにコードの行を手動で追加することで、Flutter のリダイレクトエントリを表示することができます。


#結論
以前は、開発者はハイブリッドプロジェクトの構築に数日を費やしていたかもしれません。flutter-boot を使えば、ハイブリッドプロジェクトを構築するために 1 つのコマンドを呼び出して 2 行のコードを追加するだけで済み、開発コストを大幅に削減することができます。しかし、flutter-boot はまだその潜在能力を十分に発揮できていないので、私たちはユーザーのために Flutter の開発をさらに単純化したいと考えています。今後は、共同開発プロセスの最適化や継続的インテグレーション環境の構築プロセスの改善を行い、より良い開発体験を提供していきたいと考えています。

*アリババクラウドは日本に２つのデータセンターを有し、世界で60を超えるアベラビリティーゾーンを有するアジア太平洋地域No.1(2019ガートナー)のクラウドインフラ事業者です。
アリババクラウドの詳細は、こちらからご覧ください。
[アリババクラウドジャパン公式ページ](https://www.alibabacloud.com/ja/)*