Я сталкиваюсь с проблемами развертывания проекта на Next.js, который использует Prisma и MongoDB, на Vercel. Проект работает нормально локально, но при развертывании на Vercel я получаю следующую ошибку:
at 8428 (/vercel/path0/.next/server/app/page.js:1:3202)
at t (/vercel/path0/.next/server/webpack-runtime.js:1:128)
at 5857 (/vercel/path0/.next/server/app/page.js:1:825)
at t (/vercel/path0/.next/server/webpack-runtime.js:1:128)
at r (/vercel/path0/.next/server/app/page.js:1:3644)
at /vercel/path0/.next/server/app/page.js:1:3682
at t.X (/vercel/path0/.next/server/webpack-runtime.js:1:1206)
at /vercel/path0/.next/server/app/page.js:1:3657
at Object.<anonymous> (/vercel/path0/.next/server/app/page.js:1:3709)
> Произошла ошибка сборки
Ошибка: Не удалось собрать данные страницы для /
at /vercel/path0/node_modules/next/dist/build/utils.js:1268:15
at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
type: 'Error'
}
Ошибка: Команда "npm run build" завершилась с кодом 1
Добавлен скрипт postinstall в package.json:
"scripts": {
"postinstall": "prisma generate"
}
Проверил, что DATABASE_URL корректно установлен в Vercel.
Посмотрел детализированные логи на Vercel, но ошибка продолжает возникать.
Схема Prisma:
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mongodb"
url = env("DATABASE_URL")
}
model Course {
id String @id @default(auto()) @map("_id") @db.ObjectId
clerkId String
name String
description String?
imageUrl String?
price Float?
isPublished Boolean @default(false)
categoryId String? @db.ObjectId
category Category? @relation(fields: [categoryId], references: [id])
attachments Attachment[]
chapters Chapter[]
purchases Purchase[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([categoryId])
}
Создание клиента Prisma:
import { PrismaClient } from '@prisma/client';
const prismaClientSingleton = () => {
return new PrismaClient();
};
declare const globalThis: {
prismaGlobal: ReturnType<typeof prismaClientSingleton>;
} & typeof global;
const prisma = globalThis.prismaGlobal ?? prismaClientSingleton();
export default prisma;
if (process.env.NODE_ENV !== 'production') globalThis.prismaGlobal = prisma;
Код главной страницы:
import prisma from '@/lib/prisma';
export default async function Home() {
const courses = await prisma.course.findMany({
select: {
id: true,
name: true,
},
});
return (
<main className="text-2xl">
{courses.map((course) => (
<p key={course.id}>{course.name}</p>
))}
</main>
);
}
Дополнительная информация:
Проект работает идеально локально.
Строка подключения MongoDB правильная и доступная.
Все зависимости обновлены.
Вопрос:
Что может быть причиной этой проблемы, и как я могу решить её, чтобы успешно развернуть мой проект Next.js и Prisma с MongoDB на Vercel?
Похоже, что проблема может быть связана с тем, как Prisma и MongoDB обрабатываются в среде Vercel по сравнению с вашей локальной средой.
Известно, что Prisma открывает новое соединение с каждым запросом в безсерверных средах, таких как Vercel. Убедитесь, что вы повторно используете клиента Prisma, чтобы избежать слишком большого количества открытых соединений. Вы уже сделали это с помощью вашего prismaClientSingleton, но дважды проверьте, что паттерн одиночки используется правильно.
let prisma;
if (process.env.NODE_ENV === 'production') {
prisma = new PrismaClient();
} else {
if (!global.prisma) {
global.prisma = new PrismaClient();
}
prisma = global.prisma;
}
export default prisma;
Поскольку ошибка возникает во время процесса сборки (npm run build), может быть что-то неправильно в том, как страница извлекает данные во время сборки. Запросы Prisma (например, findMany) могут выполняться во время этапа сборки, что может привести к сбою, если база данных в это время недоступна.
Самое главное, во время команды сборки напишите:
npx prisma generate && npm run build
Ответ
Проблема, с которой вы столкнулись, скорее всего, связана с тем, как Prisma и MongoDB обрабатываются в окружении Vercel по сравнению с вашим локальным окружением. Давайте разберем основные шаги, которые могут помочь вам успешно развернуть ваш проект Next.js с использованием Prisma и MongoDB на Vercel.
Шаги для устранения проблемы:
-
Проверка кода PrismaClient:
Убедитесь, что вы правильно используете шаблон синглтона для создания экземпляра PrismaClient. Это важно, так как Vercel работает в серверном окружении без постоянного состояния. Попробуйте изменить ваш код следующим образом:import { PrismaClient } from '@prisma/client'; let prisma; if (process.env.NODE_ENV === 'production') { prisma = new PrismaClient(); } else { if (!global.prisma) { global.prisma = new PrismaClient(); } prisma = global.prisma; } export default prisma;
Этот код гарантирует, что в среде разработки вы не создаете новый экземпляр PrismaClient с каждой функцией, что может привести к исчерпанию соединений.
-
Проверка обращения к базе данных:
Ошибка, которую вы получаете, может быть связана с тем, что запросы к базе данных выполняются во время сборки приложения, а не во время запросов к страницам. Убедитесь, что ваши запросы к Prisma (например,findMany
) не выполняются до завершения сборки.Вам следует переместить запросы к базе данных на уровне страницы (например, в функцию
getServerSideProps
илиgetStaticProps
), чтобы они выполнялись во время обработки запросов, а не во время сборки.Например, если вы хотите использовать
getStaticProps
, ваш код может выглядеть так:import prisma from '@/lib/prisma'; export async function getStaticProps() { const courses = await prisma.course.findMany({ select: { id: true, name: true, }, }); return { props: { courses, }, }; } export default function Home({ courses }) { return ( <main className="text-2xl"> {courses.map((course) => ( <p key={course.id}>{course.name}</p> ))} </main> ); }
-
Проверка переменной окружения DATABASE_URL:
Вы упомянули, что DATABASE_URL правильно установлен в Vercel. Убедитесь, что он действительно указывает на вашу базу данных MongoDB и что вы не используете локальную или тестовую базу данных, которая недоступна в облаке. -
Использование команд Prisma во время сборки:
Убедитесь, что вы используете правильные команды в процессе сборки. В вашем файлеpackage.json
в секцииscripts
добавьте скрипт для генерации Prisma Client перед сборкой:"scripts": { "postinstall": "prisma generate", "build": "prisma generate && next build" }
Это гарантирует, что Prisma Client будет всегда генерироваться правильно перед сборкой вашего проекта.
-
Логи и отладка:
Если ошибка сохраняется, внимательно изучите логи сборки на Vercel. Они могут предоставить дополнительные подсказки о причинах ошибки. Попробуйте временно добавить обработчик ошибок в ваших асинхронных функциях, чтобы производить логирование.Например:
try { const courses = await prisma.course.findMany(); } catch (error) { console.error('Ошибка запроса к базе данных:', error); throw error; // Или обработайте ошибку соответствующим образом }
Заключение
Убедитесь, что все вышеперечисленные рекомендации выполнены, и ошибки сборки должны исчезнуть. Помните, что главное — это правильно выстроить взаимодействие с базой данных, особенно в безсерверной среде, как Vercel. Если ошибка сохраняется после всех изменений, рассмотрите возможность обращения в поддержку Vercel или Prisma для дальнейшей помощи.