Cloud Run における Flutter: フルスタックの Dart アーキテクチャ

Karl Weinmeister
Director, Developer Relations
※この投稿は米国時間 2026 年 1 月 28 日に、Google Cloud blog に投稿されたものの抄訳です。
Flutter は、モバイル、ウェブ、デスクトップのアプリケーションを単一のコードベースから構築するためのフレームワークです。Flutter に使用されている言語である Dart は、バックエンド開発にも適したコンパイル言語です。
フロントエンドとバックエンドの両方に Dart を使用することで、フルスタック アーキテクチャを実現できます。これには多くのメリットがあります。コードベースが簡素化され、クライアントとサーバー間でロジックを共有でき、スタック全体を同じコンテナにデプロイできます。
これらすべてを Cloud Run で統合することにより、デプロイが簡単になります。フルマネージドのサーバーレス プラットフォームであるため、インフラストラクチャとスケーリングが自動的に処理されます。コンテナを提供するだけで、残りの作業はすべて Cloud Run により処理されます。その結果、スタック全体の安全でプロダクション レディな HTTPS URL を数分で取得できます。
このブログ投稿では、フルスタックの Dart アプリケーションを構築してデプロイする方法を紹介します。技術チュートリアルの業界標準である To-Do アプリを使って、これらすべてのデモを行います。コードはすべて Flutter Cloud Run リポジトリで入手できます。


Cloud Run にデプロイされた実際の To-Do アプリケーション
Flutter ウェブ フロントエンド
Flutter では、ウィジェットと呼ばれる再利用可能なコンポーネントを組み立ててユーザー インターフェースを作成します。
To-Do アプリでは、1 つのタスクをレンダリングするロジックを TodoTile ウィジェットに分離しました。このウィジェットは、スタック全体で使用される shared パッケージから TodoItem データモデルを直接インポートします。そのため、TodoItem の定義が変更される場合(priority フィールドを追加したなど)、UI ウィジェットの更新がコンパイラによりすぐに警告されます。
次のステップでは、タイルの build() メソッドをオーバーライドして、その UI を定義します。このメソッドは、標準的な下位レベルのウィジェットから TodoTile を構成します。構造には ListTile、インタラクションには Checkbox、表示には Text を使用します。
Dart バックエンド
多くの Flutter チュートリアルでは、フロントエンドを Backend-as-a-Service(BaaS)として Firebase に直接接続しています。これは、開発速度を大幅に加速させることができる、信頼できるアーキテクチャ パターンです。
ニーズによっては、Dart のフルスタック アーキテクチャには、移植性と制御性という利点もあります。さまざまなインフラストラクチャ環境に簡単にデプロイでき、クライアントとサーバー間でコードを再利用することもできます。
この例では、Dart の Shelf パッケージを使用しました。ここでは「魔法」なしで基本を説明するために、生の Shelf を選びましたが、エコシステムにはより高度なツールが豊富に用意されています。
大規模な本番環境アプリケーションの場合は、Serverpod(クライアントサイドのコードを生成し、型安全性を確保しながらデータベース操作を処理する完全なバックエンド ソリューション)や Dart Frog (最小限の開発者エクスペリエンス)など、より高レベルのフレームワークの使用を検討してください。
サーバーには 2 つの主な役割があります。1 つ目は、クライアントと同じデータ構造を使用して、API ビジネス ロジックを処理することです。2 つ目は、Flutter ウェブアプリのファイル(HTML、JS、Wasm)をブラウザに提供することです。API と静的ファイルを単一のプロセスから提供することで、デプロイを単一のコンテナに簡素化し、ルーティングとオブザーバビリティを統合しました。
この Dart サーバーは、dart compile exe を使用してスタンドアロンのネイティブ実行可能ファイルにコンパイルされます。ミリ秒単位で起動するため、ゼロにスケーリングされるワークロードに最適です。
共有ビジネス ロジック
フルスタック アーキテクチャにより、クライアントとサーバー間でデータモデルとビジネス ロジックを共有できます。shared パッケージで TodoItem モデルを定義することで、データの信頼できる唯一の情報源を作成しました。
タイトルのサニタイゼーションやデータ検証などの一般的なロジックは、拡張機能を介してこれらのモデルにアタッチできます。フロントエンドとバックエンドの両方でこのパッケージがインポートされるため、スタック全体に同一のルールが適用されます。
より複雑な検証要件がある場合は、Serverpod の使用を検討してください。サーバーサイドのモデルと検証ルールを自動的にミラーリングするクライアントサイドのコードを生成し、すべて完全に同期された状態を維持するため、このフルスタックの一貫性の点で優れています。
フロントエンドでは、この共有ロジックを使用して、サーバーの要件と「楽観的」な UI の更新の一貫性を常に保っています。これにより、重複するロジックを維持する必要がなく、応答性の高いユーザー エクスペリエンスを迅速に実現できます。
Dart ワークスペース
単一のリポジトリ(「monorepo」)で複数のパッケージを管理すると、複雑になる可能性があります。shared をインターネットに公開しなくてもフロントエンドが shared パッケージを参照できるように、これらをリンクする方法が必要です。さらに、すべてのパッケージでテストを一度に実行する方法も必要です。
Dart 3.5 以降では、Dart ワークスペースによりこの問題がネイティブに解決されています。ルートで pubspec.yaml を定義し、すべてのメンバー パッケージをリストできます。メンバー パッケージは互いに直接依存できるようになり、ルートで dart pub get を実行すると、ワークスペース全体の依存関係が解決されます。
複雑な monorepo のニーズがある場合は、Melos が役立ちます。自動バージョン管理や変更履歴生成などの高度な機能に加え、詳細なスクリプト フィルタリング(変更されたパッケージでのみテストを実行するなど)も備えています。
Cloud Run へのデプロイ
Cloud Run は、垂直方向と水平方向の両方のスケーリングをサポートしています。より多くの vCPU を割り当て、isolate を同時実行に利用することで、Dart アプリケーションを垂直方向にスケーリングできます。
このプラットフォームは、水平方向のスケーリングに優れています。各コンテナを使い捨てのユニットとして扱うことで、Cloud Run の自動スケーリング機能を利用して、トラフィックの急増を自動的に処理できます。このチュートリアルでは、この水平方向のアプローチに焦点を当てており、最小 / 最大インスタンスを構成して、費用とレイテンシを最適化しました。
Cloud Run には、柔軟なデプロイ オプションが用意されています。このフルスタックの Dart アプリでは、標準の Docker コンテナで最大限の制御が可能ですが、速度とシンプルさを考慮して「OS のみ」のランタイムをおすすめします。
OS のみのランタイム
OS のみのランタイムを使用すると、事前コンパイル済みのバイナリを最小限の Linux 環境に直接デプロイできます。リモート コンテナのビルドプロセスをスキップすることでデプロイが大幅に高速化されるため、この方法をおすすめします。さらに、Dockerfile を維持する必要がなくなるためワークフローも簡素化され、ローカルマシンで検証されたバイナリをそのままデプロイするため、一貫性が確保されます。
バックエンドを Linux 用にローカルでコンパイルするだけで、Cloud Run がそれを軽量な Ubuntu ベースイメージにマウントします。
(注: リポジトリには、このプロセスを自動化するヘルパー スクリプト tool/deploy.sh が含まれています。)
これにより、一般公開されたインスタンスがデプロイされます。本番環境では、Google IAM 認証を必須にするために --allow-unauthenticated を削除します。さらに、カスタム ドメインを構成し、最小インスタンスを設定してサービスをウォーム状態に保つこともできます。
Dockerfile を使用したコンテナのデプロイ
または、標準の Dockerfile を使用してデプロイすると、ランタイム環境を最大限に制御できます。このアプローチにより、ベース オペレーティング システムをカスタマイズ(Distroless や Alpine を使用するなど)して、システム依存関係を管理し、Cloud Build 上の汚れていない「クリーンルーム」環境で再現可能なビルドを確保できます。結果として得られるコンテナは完全に移植可能で、Docker がサポートされている場所であればどこでも実行できます。
継続的インテグレーション
GitHub Actions を使用して、アプリの品質チェックを自動化できます。ネイティブの Dart ワークスペース サポートにより、CI パイプラインが簡素化されます。dart pub get を 1 回実行するだけで、プロジェクト全体がセットアップされます。
ワークフローの重要な部分は flutter-action で、これにより Flutter SDK 環境がセットアップされます。これは、このような monorepo では特に役立ちます。単一の統合パイプラインで、標準の Dart パッケージ(バックエンドや共有ロジックなど)と Flutter 固有のパッケージ(フロントエンド)の両方をビルドしてテストするために必要なツールが提供されるからです。setup-dart だけでも純粋な Dart パッケージを処理することはできますが、フロントエンドのウィジェット テストとウェブ コンパイルには Flutter SDK が必要です。
最後に
言語、アーキテクチャ、プラットフォームを揃えることで、フロントエンド用に記述したコードがバックエンドと調和して動作するようになります。
このプロセスは、コア データモデルを Dart バックエンドと共有する、レスポンシブな Flutter フロントエンドから始まります。そこから、Melos でワークスペース全体を管理し、GitHub Actions で品質チェックを自動化しました。Cloud Run へのデプロイは、1 つのコマンドで完了します。
フルスタックのプロセスを始める準備が整ったら、Flutter Cloud Run リポジトリで完全なリファレンス実装を入手できます。皆様のプロジェクトで Dart と Cloud Run をどのように使用しているか、ぜひお聞かせください。LinkedIn、X、Bluesky でつながって、さらに話し合いましょう。
- デベロッパー リレーションズ担当ディレクター、Karl Weinmeister



