【问题标题】:Next.js middleware Module not found: Can't resolve 'fs'Next.js 中间件模块未找到:无法解析“fs”
【发布时间】:2022-03-08 03:01:25
【问题描述】:

当我尝试初始化 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;

【问题讨论】:

    标签: javascript next.js firebase-admin


    【解决方案1】:

    Next.js 中间件使用的 Edge Runtime 不支持 Node.js 原生 API。

    来自Edge Runtime 文档:

    Edge Runtime 有一些限制,包括:

    • 本机 Node.js API不受支持。例如,您无法读取或写入文件系统
    • 可以使用节点模块,只要它们实现了 ES 模块并且不使用任何原生 Node.js API

    您不能在 Next.js 中间件中使用使用 fs 的 Node.js 库。尝试改用客户端库。

    【讨论】:

      【解决方案2】:

      我浪费了很多时间来解决这个问题。奇怪的是,这将在 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

      【讨论】:

        【解决方案3】:

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

        import * as admin from "firebase-admin";
        

        【讨论】:

          猜你喜欢
          • 2021-03-03
          • 2022-08-05
          • 2017-04-18
          • 2021-10-16
          • 1970-01-01
          • 2022-06-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多