You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter Web项目中Firebase JS SDK抛出未捕获语法错误求助

Flutter Web + Firebase 控制台语法错误排查

首次基于Flutter开发Firebase Web应用,浏览器控制台出现大量未捕获语法错误,需解决该问题以实现用户认证、登录及登出功能。

index.html 中的 Firebase SDK 引入代码

<!DOCTYPE html>
<html>
<head>
  <base href="$FLUTTER_BASE_HREF">

  <meta charset="UTF-8">
  <meta content="IE=Edge" http-equiv="X-UA-Compatible">
  <meta name="description" content="A new Flutter project.">

  <!-- iOS meta tags & icons -->
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <meta name="apple-mobile-web-app-title" content="lithaexpress_admin_web_portal">
  <link rel="apple-touch-icon" href="icons/Icon-192.png">

  <!-- Favicon -->
  <link rel="icon" type="image/png" href="favicon.png"/>

  <title>lithaexpress_admin_web_portal</title>
  <link rel="manifest" href="manifest.json">

  <script>
    // The value below is injected by flutter build, do not touch.
    const serviceWorkerVersion = null;
  </script>
  <!-- This script adds the flutter initialization JS code -->
  <script src="flutter.js" defer></script>
</head>
<body>
  <script>
    window.addEventListener('load', function(ev) {
      // Download main.dart.js
      _flutter.loader.loadEntrypoint({
        serviceWorker: {
          serviceWorkerVersion: serviceWorkerVersion,
        },
        onEntrypointLoaded: function(engineInitializer) {
          engineInitializer.initializeEngine().then(function(appRunner) {
            appRunner.runApp();
          });
        }
      });
    });
  </script>

<script src="https://www.gstatic.com/firebasejs/10.3.1/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/10.3.1/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/10.3.1/firebase-firestore.js"></script>
<script src="main.dart.js" type="application/javascript"></script>

<script src="https://www.gstatic.com/firebasejs/10.3.1/firebase-analytics.js"></script>
<script>
  // Your web app's Firebase configuration
  const firebaseConfig = {
    #firebase config info
  };

  // Initialize Firebase
  firebase.initializeApp(firebaseConfig);
  firebase.analytics();
</script>

</body>
</html>

登录页面代码(LoginScreen.dart)

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:mohaexpress_admin_web_portal/main_screens/home_screen.dart';

class LoginScreen extends StatefulWidget {
  const LoginScreen({super.key});

  @override
  State<LoginScreen> createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {
  String adminEmail = '';
  String adminPassword = '';

  allowAdminToLogin() async {
    SnackBar snackBar = const SnackBar(
      content: Text(
        'Checking Credentials, Please Wait... ',
        style: TextStyle(
          fontSize: 36,
          color: Colors.black,
        ),
      ),
      backgroundColor: Colors.pinkAccent,
      duration: Duration(seconds: 6),
    );
    ScaffoldMessenger.of(context).showSnackBar(snackBar);

    User? currentAdmin;
    await FirebaseAuth.instance
        .signInWithEmailAndPassword(
      email: adminEmail,
      password: adminPassword,
    )
        .then((fAuth) {
      currentAdmin = fAuth.user;
    }).catchError((onError) {
      final snackBar = SnackBar(
        content: Text(
          'Error Occured: $onError',
          style: const TextStyle(
            fontSize: 36,
            color: Colors.black,
          ),
        ),
        backgroundColor: Colors.pinkAccent,
        duration: const Duration(seconds: 5),
      );
      ScaffoldMessenger.of(context).showSnackBar(snackBar);
    });

    if (currentAdmin != null) {
      await FirebaseFirestore.instance
          .collection('admins')
          .doc(currentAdmin!.uid)
          .get()
          .then((snap) {
        if (snap.exists) {
          Navigator.push(
            context,
            MaterialPageRoute(
              builder: (c) => const HomeScreen(),
            ),
          );
        } else {
          SnackBar snackBar = const SnackBar(
            content: Text(
              'No record found, you are not an admin.',
              style: TextStyle(
                fontSize: 36,
                color: Colors.black,
              ),
            ),
            backgroundColor: Colors.pinkAccent,
            duration: Duration(seconds: 6),
          );
          ScaffoldMessenger.of(context).showSnackBar(snackBar);
        }
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      body: Stack(
        children: [
          Center(
            child: SizedBox(
              width: MediaQuery.of(context).size.width * 0.5,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Image.asset(
                    'images/admin.png',
                  ),

                  TextField(
                    onChanged: (value) {
                      adminEmail = value;
                    },
                    style: const TextStyle(
                      fontSize: 16,
                      color: Colors.white,
                    ),
                    decoration: const InputDecoration(
                      enabledBorder: OutlineInputBorder(
                        borderSide: BorderSide(
                          color: Colors.green,
                          width: 2,
                        ),
                      ),
                      focusedBorder: OutlineInputBorder(
                        borderSide: BorderSide(
                          color: Colors.amber,
                          width: 2,
                        ),
                      ),
                      hintText: 'Email',
                      hintStyle: TextStyle(color: Colors.grey),
                      icon: Icon(
                        Icons.email,
                        color: Colors.green,
                      ),
                    ),
                  ),

                  const SizedBox(
                    height: 20,
                  ),

                  TextField(
                    onChanged: (value) {
                      adminPassword = value;
                    },
                    obscureText: true,
                    style: const TextStyle(
                      fontSize: 16,
                      color: Colors.white,
                    ),
                    decoration: const InputDecoration(
                      enabledBorder: OutlineInputBorder(
                        borderSide: BorderSide(
                          color: Colors.green,
                          width: 2,
                        ),
                      ),
                      focusedBorder: OutlineInputBorder(
                        borderSide: BorderSide(
                          color: Colors.amber,
                          width: 2,
                        ),
                      ),
                      hintText: 'Password',
                      hintStyle: TextStyle(color: Colors.grey),
                      icon: Icon(
                        Icons.admin_panel_settings,
                        color: Colors.green,
                      ),
                    ),
                  ),

                  const SizedBox(
                    height: 30,
                  ),

                  ElevatedButton(
                    onPressed: () {
                      allowAdminToLogin();
                    },
                    style: ButtonStyle(
                      padding: MaterialStateProperty.all(
                        const EdgeInsets.symmetric(
                            horizontal: 90, vertical: 20),
                      ),
                      backgroundColor:
                          MaterialStateProperty.all<Color>(Colors.green),
                      foregroundColor:
                          MaterialStateProperty.all<Color>(Colors.pinkAccent),
                    ),
                    child: const Text(
                      'Login',
                      style: TextStyle(
                        color: Colors.white,
                        letterSpacing: 2,
                        fontSize: 16,
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

main.dart 代码

import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:mohaexpress_admin_web_portal/authentication/login_screen.dart';

Future<void> main() async {
  await Firebase.initializeApp();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Admin Web Portal',
      theme: ThemeData(
        primarySwatch: Colors.green,
      ),
      debugShowCheckedModeBanner: false,
      home: const LoginScreen(),
    );
  }
}

错误原因及解决方案

核心问题分析

  1. 重复初始化Firebase:同时在index.html的JS代码和Flutter的main.dart中初始化Firebase,导致冲突引发错误。
  2. 配置占位符语法错误:index.html中firebaseConfig里的#firebase config info是无效JS语法,直接触发语法错误。
  3. 脚本加载逻辑错误:Flutter Web使用Firebase官方插件时,无需手动引入JS SDK,插件会自动处理依赖,手动引入会导致版本或初始化冲突。

具体修复步骤

  1. 移除index.html中的Firebase JS代码:
    删除所有Firebase相关的<script>标签及初始化代码,包括SDK引入和firebase.initializeApp部分。

  2. 添加Firebase配置文件:
    在项目根目录创建firebase_options.dart,通过flutterfire configure命令生成(需先安装flutterfire_cli),或手动写入你的Firebase Web配置:

    import 'package:firebase_core/firebase_core.dart';
    import 'package:flutter/foundation.dart';
    
    class DefaultFirebaseOptions {
      static FirebaseOptions get currentPlatform {
        if (kIsWeb) {
          return const FirebaseOptions(
            apiKey: "你的API_KEY",
            authDomain: "你的AUTH_DOMAIN",
            projectId: "你的PROJECT_ID",
            storageBucket: "你的STORAGE_BUCKET",
            messagingSenderId: "你的MESSAGING_SENDER_ID",
            appId: "你的APP_ID",
            measurementId: "你的MEASUREMENT_ID",
          );
        }
        throw UnsupportedError('当前平台不支持默认Firebase配置');
      }
    }
    
  3. 修正main.dart初始化逻辑:

    import 'package:firebase_core/firebase_core.dart';
    import 'package:flutter/material.dart';
    import 'package:mohaexpress_admin_web_portal/authentication/login_screen.dart';
    import 'firebase_options.dart';
    
    Future<void> main() async {
      WidgetsFlutterBinding.ensureInitialized(); // 必须添加,确保Flutter绑定完成
      await Firebase.initializeApp(
        options: DefaultFirebaseOptions.currentPlatform,
      );
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({Key? key}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Admin Web Portal',
          theme: ThemeData(
            primarySwatch: Colors.green,
          ),
          debugShowCheckedModeBanner: false,
          home: const LoginScreen(),
        );
      }
    }
    
  4. 检查并更新依赖:
    确保pubspec.yaml中依赖版本正确,执行flutter pub get更新:

    dependencies:
      flutter:
        sdk: flutter
      firebase_core: ^2.15.0
      firebase_auth: ^4.10.0
      cloud_firestore: ^4.8.0
    

额外注意事项

  • Flutter Web项目中,优先使用Firebase官方Flutter插件,不要混用JS SDK,避免版本冲突。
  • 确保Firebase控制台已正确创建Web应用,并复制完整的配置信息到firebase_options.dart中。

内容的提问来源于stack exchange,提问作者Moha Nkossie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 12:19:51