Next.js 未找到中间件模块:无法解析 'fs'

Next.js middleware Module not found: Can't resolve 'fs'

当我尝试初始化 Firebase admin V9 时,在 Next.js _middleware 文件中出现此错误。有人知道如何解决这个问题吗?

./node_modules/@google-cloud/storage/build/src/bucket.js:22:0
Module not found: Can't resolve 'fs'

../../firebase/auth-admin

import * as admin from "firebase-admin";

if (!admin.apps.length) {
  admin.initializeApp({
    credential: admin.credential.cert({
      projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
      clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
      privateKey: process.env.FIREBASE_ADMIN_PRIVATE_KEY,
    }),
  });
}

const firestore = admin.firestore();

const auth = admin.auth();

export { firestore, auth };

在我的 _middleware

中调用它
import { NextFetchEvent, NextRequest, NextResponse } from "next/server";
import { auth } from "../../firebase/auth-admin";

export default async function authenticate(
  req: NextRequest,
  ev: NextFetchEvent
) {
  const token = req.headers.get("token");
  console.log("auth = ", auth);
  //   const decodeToken = await auth.verifyIdToken(token);
  return NextResponse.next();
}

我通过自定义 webpack 看到了一个解决方案 here,但这并不能解决问题。

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  webpack: (config, { isServer, node }) => {
    node = {
      ...node,
      fs: "empty",
      child_process: "empty",
      net: "empty",
      tls: "empty",
    };
    return config;
  },
};

module.exports = nextConfig;

Next.js 中间件使用的边缘运行时不支持 Node.js 本机 API。

来自 Edge Runtime 文档:

The Edge Runtime has some restrictions including:

  • Native Node.js APIs are not supported. For example, you can't read or write to the filesystem
  • Node Modules can be used, as long as they implement ES Modules and do not use any native Node.js APIs

您不能使用在 Next.js 中间件中使用 fs 的 Node.js 库。尝试使用 client-side 库。

我浪费了很多时间来解决这个问题。奇怪的是,这将在 api 本身中起作用。

所以不要在 _middleware 文件中调用 firebase-admin 操作。在 api 本身中调用它,例如:

import type { NextApiRequest, NextApiResponse } from 'next'
import { auth } from "../../firebase/auth-admin";

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  const authorization = req.headers.authorization
  console.log(`Handler auth header: ${authorization}`)

  if (!authorization) {
    return res.status(401).json({ message: 'Authorisation header not found.' })
  }

  const token = authorization.split(' ')[1]
  if (!token) {
    return res.status(401).json({ message: 'Bearer token not found.' })
  }

  console.log(`Token: ${token}`)

  try {
    const {uid} = await auth.verifyIdToken("sd" + token)
    console.log(`User uid: ${uid}`)
    res.status(200).json({ userId: uid })
  } catch (error) {
    console.log(`verifyIdToken error: ${error}`)
    res.status(401).json({ message: `Error while verifying token. Error: ${error}` })
  }
}

使这个可重用的解决方法是创建一个包装函数。

如果有人知道如何在 _middleware 文件中进行这项工作,我将不胜感激。

编辑:包装中间件函数的要点: https://gist.github.com/jvgrootveld/ed1863f0beddc1cc2bf2d3593dedb6da

确保您没有在客户端中调用 firebase-admin

import * as admin from "firebase-admin";