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

Firebase云函数部署SSR Next.js应用时React Hooks调用报错

解决Firebase Cloud Functions托管SSR Next.js时的Invalid Hook Call错误

我之前在部署Next.js SSR到Firebase Cloud Functions时也踩过这个Hook调用的坑,结合你描述的情况,咱们来一步步排查解决:

核心问题分析

你遇到的Invariant Violation: Invalid hook call错误,结合SSR场景和Firebase部署的特点,最可能的原因是应用中存在多份React副本,其次是React与React DOM版本不匹配,Hook使用规则违反的概率相对较低(毕竟不用Hook时能正常访问)。


具体解决方案

1. 统一React/React DOM版本,排查重复依赖

首先确认你的项目根目录和Firebase Functions目录(通常是functions/)的package.json中,react和react-dom的版本都是16.10.2,并且都放在dependencies字段下(SSR环境需要生产依赖,不能放在devDependencies)。

然后执行命令查看依赖树,检查是否有重复的React包:

# 项目根目录
npm ls react react-dom
# 切换到functions目录
cd functions && npm ls react react-dom

如果输出中出现多个版本的React,说明存在重复副本。

2. 强制依赖统一版本(关键步骤)

针对多份React副本的问题,我们可以通过依赖锁定来强制所有子依赖使用同一版本的React:

  • 如果使用npm(8.x及以上版本):在functions/package.json中添加overrides字段:
    "overrides": {
      "react": "$react",
      "react-dom": "$react-dom"
    }
    
  • 如果使用yarn:在functions/package.json中添加resolutions字段:
    "resolutions": {
      "react": "16.10.2",
      "react-dom": "16.10.2"
    }
    

添加完成后,删除functions/node_modules和锁文件,重新安装依赖:

cd functions
rm -rf node_modules package-lock.json # yarn的话删yarn.lock
npm install # 或者yarn install

3. 验证Next.js SSR配置正确性

确保Firebase Functions的入口文件(比如functions/index.js)中,Next.js的初始化配置正确,特别是distDir要和Next.js的输出目录一致:

const functions = require('firebase-functions');
const next = require('next');
const dev = process.env.NODE_ENV !== 'production';
// 注意distDir配置,要匹配Next.js的默认输出目录
const app = next({ dev, conf: { distDir: '.next' } });
const handle = app.getRequestHandler();

exports.nextApp = functions.https.onRequest((req, res) => {
  // 确保每次请求都先准备好Next.js应用
  return app.prepare().then(() => handle(req, res));
});

4. 最后确认Hook使用规则

虽然不用Hook时能正常访问,但还是快速检查pages/about.tsx中的useState是否符合规则:

  • 必须在函数组件的顶级作用域调用Hook
  • 不能在条件判断、循环、嵌套函数中调用Hook

正确示例:

import { useState } from 'react';

export default function About() {
  // 顶级作用域调用Hook,正确
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

补充说明

这个问题确实在firebase-functions的GitHub仓库中有相关上报,本质是Firebase Functions的依赖隔离机制可能导致Next.js的依赖和Functions自身的依赖出现冲突,生成多份React副本。按照上面的步骤强制统一版本后,基本能解决这个问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:17:36