Flutter でWebで動作させる場合にAPI Keyを直書きしない方法について解説します。
通常 index.html にそのまま書けば動作します。
<body>
<script src="flutter_bootstrap.js" async></script>
<script>
const apiKey = "{{API_KEY}}"; // Dartコードで置換
const script = document.createElement('script');
script.src = `https://maps.googleapis.com/maps/api/js?key=ここにAPI KEYベタ打ち`;
document.head.appendChild(script);
</script>
</body>
しかしこれだと、Gitなどでの管理ができなくなってしまうため、.env ファイルから読み出したいところです。しかしindex.html から直接.env を参照することはできません。
解決方法
プラットフォームごとの処理を追加
Web の場合は以下のファイルを読み込むようにします。 lib の直下に utils ディレクトリを作成し、web_utils.dart を作成しました。
このようにファイルを分けることで、
import ‘dart:html’ as html;
が使えるようになります。
このパッケージはWebのみで動作するため、他のプラットフォームのコードに含められないからです。
// ignore: avoid_web_libraries_in_flutter
import 'dart:html' as html;
void addGoogleMapsScript(String apiKey) {
final script = html.ScriptElement()
..src = 'https://maps.googleapis.com/maps/api/js?key=$apiKey&callback=initMap'
..type = 'text/javascript'
..async = true
..defer = true;
html.document.body!.append(script);
}
Web 以外(iOS, Android)の場合の処理を書いたファイルも用意します。utils ディレクトリに stub_utils.dart を作成。以下のように書きました。
void addGoogleMapsScript(String apiKey) {
// モバイルプラットフォームでは何もしない
}
main.dart での処理
flutter_dotenv パッケージを追加します。
flutter pub add flutter_dotenv
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'firebase_options.dart';
import 'widgets/bottom_nav_layout.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
// 条件付きインポート
import 'utils/web_utils.dart'
if (dart.library.html) 'utils/web_utils.dart'
if (dart.library.io) 'utils/stub_utils.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// 環境変数を読み込む
await dotenv.load(fileName: ".env");
// Firebaseの初期化
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
// Webの場合のみGoogle Mapsスクリプトを追加
if (kIsWeb) {
final apiKey = dotenv.env['GOOGLE_MAPS_API_KEY'];
if (apiKey != null && apiKey.isNotEmpty) {
addGoogleMapsScript(apiKey);
} else {
print('Error: GOOGLE_MAPS_API_KEY is not set in the .env file.');
}
}
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Anonymous Login Demo',
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepOrange),
),
home: const BottomNavLayout(currentIndex: 0),
);
}
}
firebase console で web を追加
firebase console でモバイルだけでなく、webを追加して、apikey を発行しましょう。
これを.envに追加します。
.evn ファイルの設定
以下のように設定します。
api_key_here のところで先ほど設定したapi key を入力しましょう。
GOOGLE_MAPS_API_KEY=your_google_maps_api_key_here
# Firebase iOS Configuration
FIREBASE_IOS_API_KEY=your_firebase_ios_api_key_here
FIREBASE_IOS_APP_ID=your_firebase_ios_app_id_here
FIREBASE_IOS_MESSAGING_SENDER_ID=your_firebase_ios_messaging_sender_id_here
FIREBASE_IOS_PROJECT_ID=your_firebase_ios_project_id_here
FIREBASE_IOS_STORAGE_BUCKET=your_firebase_ios_storage_bucket_here
FIREBASE_IOS_BUNDLE_ID=your_firebase_ios_bundle_id_here
# Firebase Web Configuration
FIREBASE_WEB_API_KEY=your_firebase_web_api_key_here
FIREBASE_WEB_AUTH_DOMAIN=your_firebase_web_auth_domain_here
FIREBASE_WEB_PROJECT_ID=your_firebase_web_project_id_here
FIREBASE_WEB_STORAGE_BUCKET=your_firebase_web_storage_bucket_here
FIREBASE_WEB_MESSAGING_SENDER_ID=your_firebase_web_messaging_sender_id_here
FIREBASE_WEB_APP_ID=your_firebase_web_app_id_here
FIREBASE_WEB_MEASUREMENT_ID=your_firebase_web_measurement_id_here
firebase の設定 firebase_options.dart
プラットフォームごとに api key を切り分けるのに使います。
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart' show defaultTargetPlatform, kIsWeb, TargetPlatform;
import 'package:flutter_dotenv/flutter_dotenv.dart';
/// Default [FirebaseOptions] for use with your Firebase apps.
class DefaultFirebaseOptions {
static FirebaseOptions get currentPlatform {
if (kIsWeb) {
return web;
}
switch (defaultTargetPlatform) {
case TargetPlatform.android:
throw UnsupportedError('DefaultFirebaseOptions have not been configured for android.');
case TargetPlatform.iOS:
return ios;
case TargetPlatform.macOS:
throw UnsupportedError('DefaultFirebaseOptions have not been configured for macos.');
case TargetPlatform.windows:
throw UnsupportedError('DefaultFirebaseOptions have not been configured for windows.');
case TargetPlatform.linux:
throw UnsupportedError('DefaultFirebaseOptions have not been configured for linux.');
default:
throw UnsupportedError('DefaultFirebaseOptions are not supported for this platform.');
}
}
static final FirebaseOptions ios = FirebaseOptions(
apiKey: dotenv.env['FIREBASE_IOS_API_KEY']!,
appId: dotenv.env['FIREBASE_IOS_APP_ID']!,
messagingSenderId: dotenv.env['FIREBASE_IOS_MESSAGING_SENDER_ID']!,
projectId: dotenv.env['FIREBASE_IOS_PROJECT_ID']!,
storageBucket: dotenv.env['FIREBASE_IOS_STORAGE_BUCKET']!,
iosBundleId: dotenv.env['FIREBASE_IOS_BUNDLE_ID']!,
);
static final FirebaseOptions web = FirebaseOptions(
apiKey: dotenv.env['FIREBASE_WEB_API_KEY']!,
authDomain: dotenv.env['FIREBASE_WEB_AUTH_DOMAIN']!,
projectId: dotenv.env['FIREBASE_WEB_PROJECT_ID']!,
storageBucket: dotenv.env['FIREBASE_WEB_STORAGE_BUCKET']!,
messagingSenderId: dotenv.env['FIREBASE_WEB_MESSAGING_SENDER_ID']!,
appId: dotenv.env['FIREBASE_WEB_APP_ID']!,
measurementId: dotenv.env['FIREBASE_WEB_MEASUREMENT_ID'],
);
}
コメントを残す