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

Remix集成Firebase认证报错:Cannot read properties of undefined (reading '_getRecaptchaConfig')

解决Remix集成Firebase注册时的"_getRecaptchaConfig"未定义错误

错误原因

你遇到的Cannot read properties of undefined (reading '_getRecaptchaConfig')错误,是因为在Remix的服务端action函数中使用了Firebase客户端SDK的认证方法。Firebase客户端SDK的createUserWithEmailAndPassword依赖浏览器环境的reCAPTCHA配置,而服务端运行时没有这个环境,导致相关属性未定义。

解决方案

方案一:使用Firebase Admin SDK在服务端处理注册

Firebase Admin SDK专门用于服务端操作,不依赖浏览器环境,适合在Remix的action中使用:

  1. 安装Firebase Admin SDK
npm install firebase-admin
  1. 配置Admin SDK(新建app/utils/firebase-admin.ts)
import admin from 'firebase-admin';

if (!admin.apps.length) {
  admin.initializeApp({
    credential: admin.credential.cert({
      projectId: process.env.FIREBASE_PROJECT_ID,
      clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
      privateKey: process.env.FIREBASE_PRIVATE_KEY?.replace(/\\n/g, '\n'),
    }),
  });
}

export const adminAuth = admin.auth();
  1. 修改Remix的action函数
import { adminAuth } from '~/utils/firebase-admin';

export async function action({ request }: ActionArgs) {
    const formData = await request.formData();
    const formValues = Object.fromEntries(formData);

    invariant(
        formValues?.email && typeof formValues?.email === 'string',
        "email为空或不是字符串类型",
    );
    invariant(
        formValues?.password && typeof formValues?.password === 'string',
        "密码为空或不是字符串类型",
    );

    try {
        // 使用Admin SDK创建用户
        const userRecord = await adminAuth.createUser({
            email: formValues.email,
            password: formValues.password,
        });
        console.log('创建用户成功:', userRecord.uid);
    } catch (error) {
        console.log('注册错误:', error);
        logger.error(getErrorMessage(error));
    }

    return null;
}

方案二:将注册逻辑移到客户端执行

把注册操作放在浏览器端执行,避免服务端环境不兼容的问题:

修改表单组件,在客户端处理提交逻辑:

import { useState } from 'react';
import { Form, Link, useNavigation } from '@remix-run/react';
import { auth } from '~/utils/firebase';
import { createUserWithEmailAndPassword } from 'firebase/auth';

export default function SignupForm() {
    const navigation = useNavigation();
    const [error, setError] = useState<string | null>(null);

    const handleSubmit = async (e: React.FormEvent) => {
        e.preventDefault();
        const formData = new FormData(e.currentTarget);
        const email = formData.get('email') as string;
        const password = formData.get('password') as string;

        try {
            await createUserWithEmailAndPassword(auth, email, password);
            // 注册成功后的跳转或其他逻辑
        } catch (err) {
            setError((err as Error).message);
            console.log('注册错误:', err);
        }
    };

    return (
        <Form
            onSubmit={handleSubmit}
            className="space-y-3"
            noValidate
            replace
        >
            {error && <p className="text-red-500">{error}</p>}
            <fieldset>
                <label htmlFor="email">邮箱</label>
                <Input name="email" placeholder="邮箱" />
            </fieldset>
            <fieldset>
                <label htmlFor="password">密码</label>
                <Input
                    name="password"
                    type="password"
                    placeholder="密码"
                />
            </fieldset>
            <LoadingButton
                type="submit"
                size="lg"
                name="intent"
                value="__with_email"
                isLoading={navigation.state === 'loading'}
                className="mt-[18px] min-h-[56px] w-full text-base"
            >
                创建账号
            </LoadingButton>
            <p className="mt-[18px] text-center text-base">
                已有账号?{' '}
                <Link to="/login" className="font-bold hover:underline">
                    登录
                </Link>
            </p>
        </Form>
    );
}

注意事项

  • 使用Admin SDK时,需要在环境变量中配置Firebase服务账号的相关信息(projectId、clientEmail、privateKey),这些信息可以从Firebase控制台的"服务账号"页面下载JSON文件获取。
  • 客户端处理注册时,确保Firebase客户端SDK已正确初始化,且仅在浏览器环境中执行相关逻辑(Remix中可以通过typeof window !== 'undefined'判断环境)。

内容的提问来源于stack exchange,提问作者Elysee Bleu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 19:24:55