Проблемы с развертыванием проекта Next.js и Prisma с MongoDB на Vercel

Вопросы и ответы

Я сталкиваюсь с проблемами развертывания проекта на 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.

Шаги для устранения проблемы:

  1. Проверка кода 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 с каждой функцией, что может привести к исчерпанию соединений.

  2. Проверка обращения к базе данных:
    Ошибка, которую вы получаете, может быть связана с тем, что запросы к базе данных выполняются во время сборки приложения, а не во время запросов к страницам. Убедитесь, что ваши запросы к 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>
     );
    }
  3. Проверка переменной окружения DATABASE_URL:
    Вы упомянули, что DATABASE_URL правильно установлен в Vercel. Убедитесь, что он действительно указывает на вашу базу данных MongoDB и что вы не используете локальную или тестовую базу данных, которая недоступна в облаке.

  4. Использование команд Prisma во время сборки:
    Убедитесь, что вы используете правильные команды в процессе сборки. В вашем файле package.json в секции scripts добавьте скрипт для генерации Prisma Client перед сборкой:

    "scripts": {
     "postinstall": "prisma generate",
     "build": "prisma generate && next build"
    }

    Это гарантирует, что Prisma Client будет всегда генерироваться правильно перед сборкой вашего проекта.

  5. Логи и отладка:
    Если ошибка сохраняется, внимательно изучите логи сборки на Vercel. Они могут предоставить дополнительные подсказки о причинах ошибки. Попробуйте временно добавить обработчик ошибок в ваших асинхронных функциях, чтобы производить логирование.

    Например:

    try {
     const courses = await prisma.course.findMany();
    } catch (error) {
     console.error('Ошибка запроса к базе данных:', error);
     throw error; // Или обработайте ошибку соответствующим образом
    }

Заключение

Убедитесь, что все вышеперечисленные рекомендации выполнены, и ошибки сборки должны исчезнуть. Помните, что главное — это правильно выстроить взаимодействие с базой данных, особенно в безсерверной среде, как Vercel. Если ошибка сохраняется после всех изменений, рассмотрите возможность обращения в поддержку Vercel или Prisma для дальнейшей помощи.

Оцените материал
Добавить комментарий

Капча загружается...