毎回デプロイして確認するのは時間の無駄です。ローカルのエミュレータを使って爆速開発する手順と、その際に必ずぶつかる「App Checkエラー」の回避方法を解説します。
1. Cloud Functions側の実装 (App Check回避)
エミュレータからのリクエストには正規のApp Checkトークンがないため、そのままではエラーになります。
「本番環境(FUNCTIONS_EMULATOR が false)の時だけチェックする」 という条件分岐を入れます。
functions/src/index.ts
import * as functions from "firebase-functions/v1";
// 日本リージョンを指定(任意)
export const helloWorld = functions
.region('asia-northeast1')
.https.onCall((data, context) => {
// ★ 開発環境かどうかの判定
const isEmulator = process.env.FUNCTIONS_EMULATOR === "true";
// 「エミュレータじゃない(本番)」かつ「App Check認証がない」場合のみエラーにする
if (!isEmulator && context.app == undefined) {
throw new functions.https.HttpsError(
'failed-precondition',
'The function must be called from an App Check verified app.'
);
}
functions.logger.info("🎉 ガードを突破!処理を開始します。");
return { message: "成功!これはセキュアな通信(またはエミュレータ)です。" };
});
2. Flutter側の実装 (エミュレータ接続)
アプリが本番サーバーではなく、あなたのパソコン(ローカル)を見に行くように設定します。
lib/main.dart
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
// ★ 開発モード(Debug)の時だけエミュレータを使う
if (kDebugMode) {
// Androidエミュレータは '10.0.2.2'、iOSは 'localhost' を使うのが定石
final host = Platform.isAndroid ? '10.0.2.2' : 'localhost';
try {
// リージョンを指定している場合は instanceFor(region: ...) が必須!
FirebaseFunctions.instanceFor(region: 'asia-northeast1')
.useFunctionsEmulator(host, 5001);
print('🚀 Functions connected to emulator: $host:5001');
} catch (e) {
print(e);
}
}
runApp(const MyApp());
}
3. エミュレータの起動とコンパイル(最重要!)
TypeScriptを使っている場合、「保存しただけでは反映されない」 という罠があります。必ずJSへの変換(コンパイル)が必要です。
ターミナルA(コンパイル監視用)
cd functions
npm run build:watch
# これで .ts を保存するたびに自動で .js に変換されます
ターミナルB(エミュレータ起動用)
firebase emulators:start
# ログはここに流れます
4. 動作確認 (curlコマンドの作法)
アプリを作る前に、ターミナルから curl で疎通確認をするのがおすすめです。
ただし、onCall 関数は特殊なルール(data キーで包む)があるため注意してください。
# 成功するコマンド例
curl -X POST \
-H "Content-Type: application/json" \
-d '{"data": {"text": "テスト"}}' \
http://127.0.0.1:5001/[プロジェクトID]/asia-northeast1/helloWorld
- ポイント1:
Content-Type: application/jsonは必須。 - ポイント2: 送信データは必ず
{"data": ...}で包むこと!
💡 トラブルシューティング
Q: FAILED_PRECONDITION エラーが消えない!
A: Functionsのコードが古いまま動いている可能性大です。npm run build を手動で実行するか、watch が動いているか確認してください。
Q: 404 Not Found になる!
A: URLのプロジェクトID、関数名、そしてリージョンが合っているか確認してください。特にFlutter側で instanceFor(region: ‘asia-northeast1’) を忘れると、デフォルトの us-central1 を探しに行ってしまい404になります。
Q: ログが見にくい!
A: ブラウザで http://localhost:4000/logs を開くと、綺麗に整形されたログが見られます


コメント