Настройка пользовательского сервера в Next.js

Next.js по умолчанию включает собственный сервер с командой next start. Если у вас есть существующий бэкенд, вы все равно можете использовать его с Next.js (это не пользовательский сервер). Пользовательский сервер Next.js позволяет программно запускать сервер для реализации пользовательских сценариев. В большинстве случаев этот подход не требуется, но он доступен, если вам нужно выйти за рамки стандартного поведения.

Важно знать:

  • Прежде чем решить использовать пользовательский сервер, учтите, что это следует делать только тогда, когда встроенный маршрутизатор Next.js не может удовлетворить требования вашего приложения. Пользовательский сервер отключает важные оптимизации производительности, такие как Автоматическая статическая оптимизация.
  • При использовании режима standalone output он не отслеживает файлы пользовательского сервера. Вместо этого этот режим выводит отдельный минимальный файл server.js. Эти режимы нельзя использовать вместе.

Вот пример пользовательского сервера:

import { createServer } from 'http'
import { parse } from 'url'
import next from 'next'

const port = parseInt(process.env.PORT || '3000', 10)
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

app.prepare().then(() => {
  createServer((req, res) => {
    const parsedUrl = parse(req.url!, true)
    handle(req, res, parsedUrl)
  }).listen(port)

  console.log(
    `> Server listening at http://localhost:${port} as ${
      dev ? 'development' : process.env.NODE_ENV
    }`
  )
})
import { createServer } from 'http'
import { parse } from 'url'
import next from 'next'

const port = parseInt(process.env.PORT || '3000', 10)
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()

app.prepare().then(() => {
  createServer((req, res) => {
    const parsedUrl = parse(req.url, true)
    handle(req, res, parsedUrl)
  }).listen(port)

  console.log(
    `> Server listening at http://localhost:${port} as ${
      dev ? 'development' : process.env.NODE_ENV
    }`
  )
})

Файл server.js не проходит через компилятор Next.js или процесс сборки. Убедитесь, что синтаксис и исходный код этого файла совместимы с используемой версией Node.js. Пример.

Для запуска пользовательского сервера обновите scripts в package.json следующим образом:

package.json
{
  "scripts": {
    "dev": "node server.js",
    "build": "next build",
    "start": "NODE_ENV=production node server.js"
  }
}

Альтернативно можно настроить nodemon (пример). Пользовательский сервер использует следующий импорт для соединения с приложением Next.js:

import next from 'next'

const app = next({})

Импорт next представляет собой функцию, которая принимает объект со следующими опциями:

ОпцияТипОписание
confObjectТот же объект, что используется в next.config.js. По умолчанию {}
devBoolean(Опционально) Запускать ли Next.js в режиме разработки. По умолчанию false
dirString(Опционально) Расположение проекта Next.js. По умолчанию '.'
quietBoolean(Опционально) Скрывать сообщения об ошибках с информацией о сервере. По умолчанию false
hostnameString(Опционально) Имя хоста, на котором работает сервер
portNumber(Опционально) Порт, на котором работает сервер
httpServernode:http#Server(Опционально) HTTP-сервер, на котором работает Next.js
turboBoolean(Опционально) Включить Turbopack

Возвращаемый объект app может затем использоваться для обработки запросов Next.js по мере необходимости.

Отключение файловой маршрутизации

По умолчанию Next.js обслуживает каждый файл в папке pages по пути, соответствующему имени файла. Если ваш проект использует пользовательский сервер, это поведение может привести к тому, что один и тот же контент будет доступен по нескольким путям, что может вызвать проблемы с SEO и UX.

Чтобы отключить это поведение и предотвратить маршрутизацию на основе файлов в pages, откройте next.config.js и отключите конфигурацию useFileSystemPublicRoutes:

next.config.js
module.exports = {
  useFileSystemPublicRoutes: false,
}

Примечание: useFileSystemPublicRoutes отключает маршруты на основе имен файлов только для SSR; клиентская маршрутизация по-прежнему может обращаться к этим путям. При использовании этой опции следует программно запрещать навигацию к нежелательным маршрутам.

Вы также можете настроить клиентский маршрутизатор для запрета клиентских перенаправлений на маршруты по именам файлов; для этого см. router.beforePopState.