nextjs13的route handle post影响了get的响应结果?

vercel生产环境中的路由的post处理函数影响get处理函数的响应结果

本地开发环境是正常的,而且在本地进行build后,使用next start启动的环境也是正常的

但是如果我把这整个post都注释掉,再通过vercel部署,就正常了!
我整个应用都没有发起对应的post请求,无论是否注释掉

// app/api/nav/route.ts
import fs from 'fs-extra'
import path from 'path'
import { NextResponse } from 'next/server'
import { prisma } from '@/prisma'
import { usePrisma } from '@/config'
import { headers } from 'next/headers'

const blogDirName = 'blog'
async function getBlogUrlList(
  dir: string,
  result: any[] = [],
  parent: any = null
) {
  for (const name of await fs.readdir(dir)) {
    const fileStat = await fs.stat(path.resolve(dir, name))
    const isDirectory = fileStat.isDirectory()
    let item: any = { label: name, name, url: name }
    if (item.url.indexOf(blogDirName) !== 1) {
      item.url = `/${blogDirName}/${item.url}`
    }
    if (parent) {
      item.url = parent.url + '/' + name
      if (isDirectory || name === 'page.tsx') {
        if (name === 'page.tsx') parent.linked = true
        if (!parent.children) parent.children = []
        parent.children.push(item)
      }
    } else {
      result.push(item)
    }
    if (isDirectory) {
      await getBlogUrlList(path.resolve(dir, name), result, item)
      if (item.children) {
        const target = item.children.find((it: any) =>
          it.url.includes('page.tsx')
        )
        if (target) {
          item.flag = true
          if (parent) {
            parent.flag = true
          }
        }
        item.children = item.children.filter((it: any) => it.flag === true)
      }
    }
  }
  return result
}

function getFlatList(
  data: any[],
  result: any[] = [],
  parentName: string | null = null
) {
  for (const item of data) {
    result.push({
      name: item.name,
      url: item.url,
      label: item.label,
      linked: item.linked,
      parentName,
    })
    if (item.children) {
      getFlatList(item.children, result, item.name)
    }
  }
  return result
}
async function add2DB(list: any[]) {
  for (const menu of list) {
    const data = await prisma.menu.findUnique({ where: { name: menu.name } })
    let parentData = null
    if (menu.parentName) {
      parentData = await prisma.menu.findUnique({
        where: { name: menu.parentName },
      })
    }
    if (!data) {
      await prisma.menu.create({
        data: {
          label: menu.label,
          linked: !!menu.linked,
          url: menu.url,
          name: menu.name,
          parentId: parentData ? parentData.id : 0,
        },
      })
    }
  }
}

function formatMenu(data: any[], result: any[] = [], map = new Map()) {
  for (const item of data) {
    let menu = {
      id: item.id,
      label: item.label,
      linked: item.linked,
      name: item.name,
      url: item.url,
      children: [],
    }
    if (item.parentId === 0) {
      result.push(menu)
    } else {
      const parentMenu = map.get(item.parentId)
      parentMenu.children.push(menu)
    }
    map.set(item.id, menu)
  }
  return result
}

export async function GET(request: Request) {
  const blogPath = path.resolve(process.cwd(), 'app/' + blogDirName)
  const blogUrlList = await getBlogUrlList(blogPath)
  // usePrisma 这里是false
  if (usePrisma) {
    const flatList = getFlatList(blogUrlList)
    await add2DB(flatList)
    const menuList = await prisma.menu.findMany({
      orderBy: {
        id: 'asc',
      },
    })
    return NextResponse.json({ data: formatMenu(menuList) })
  } else {
    return NextResponse.json({ data: blogUrlList })
  }
}

export async function POST(request: Request) {
  const headersList = headers()
  const requestKey = headersList.get('authorization')!
  const target = await prisma.requsetKey.findFirst({
    where: {
      key: requestKey,
    },
  })
  if (!target) {
    return NextResponse.json({ code: 401, msg: '认证失败!' })
  }
  const { data } = await request.json()
  await prisma.$transaction(
    data.map((item: { id: number; label: string }) =>
      prisma.menu.update({
        where: { id: item.id },
        data: {
          label: item.label,
        },
      })
    )
  )
  return NextResponse.json({ data: true })
}
  • vercel的生产环境

    image.png

  • 本地开发环境
    image.png

错误在于vercel部署的get请求没有返回对应的flag字段和children字段,
但是如果注释掉post再部署,那么vercel的get请求结果有这两个字段,和本地开发环境一摸一样了?

阅读 327
avatarAI BotBETA

根据你提供的代码和描述,问题可能出在 prisma 模型中 menu 模型的 children 字段上。根据你提供的代码,children 字段在 menu 模型中是一个数组,但是在 prisma 模型中可能被定义为一个对象。

如果你在 prisma 模型中定义了 children 字段为一个对象,那么 menu.children 可能在查询时被转换为数组,而不是直接作为对象。这可能导致在获取菜单列表时出现错误。

为了验证这个问题,你可以尝试在 prisma 模型中修改 children 字段的定义,将其定义为数组。修改后的代码如下:

import { PrismaClient } from '@/prisma'

type Menu = {
  id: number;
  label: string;
  linked: boolean;
  name: string;
  url: string;
  children?: Array<Menu>;
};

这样,在获取菜单列表时,你应该可以正确地获取到 children 字段,并在获取 parentMenu.children 时将其转换为数组。然后,你需要在获取 menuList 后将 children 字段转换为数组,以便正确地渲染菜单。修改后的代码如下:

function formatMenu(data: any[], result: any[] = [], map = new Map()) {
  for (const item of data) {
    let menu = {
      id: item.id,
      label: item.label,
      linked: item.linked,
      name: item.name,
      url: item.url,
      children: item.children || [], // 添加这一行代码
    }
    if (item.parentId === 0) {
      result.push(menu)
    } else {
      const parentMenu = map.get(item.parentId)
      parentMenu.children.push(menu)
    }
    map.set(item.id, menu)
  }
  return result
}

请注意,这只是为了验证问题而进行的修改。在实际应用中,你可能需要根据具体的业务需求进行相应的修改。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题