Пользовательский сервер

Примеры

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

Важно знать:

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

Рассмотрим следующий пример пользовательского сервера:

server.js
const { createServer } = require('http')
const { parse } = require('url')
const next = require('next')

const dev = process.env.NODE_ENV !== 'production'
const hostname = 'localhost'
const port = 3000
// при использовании middleware `hostname` и `port` должны быть указаны ниже
const app = next({ dev, hostname, port })
const handle = app.getRequestHandler()

app.prepare().then(() => {
  createServer(async (req, res) => {
    try {
      // Обязательно передавайте `true` вторым аргументом в `url.parse`.
      // Это указывает на необходимость разбора query-части URL.
      const parsedUrl = parse(req.url, true)
      const { pathname, query } = parsedUrl

      if (pathname === '/a') {
        await app.render(req, res, '/a', query)
      } else if (pathname === '/b') {
        await app.render(req, res, '/b', query)
      } else {
        await handle(req, res, parsedUrl)
      }
    } catch (err) {
      console.error('Ошибка при обработке', req.url, err)
      res.statusCode = 500
      res.end('внутренняя ошибка сервера')
    }
  })
    .once('error', (err) => {
      console.error(err)
      process.exit(1)
    })
    .listen(port, () => {
      console.log(`> Готово на http://${hostname}:${port}`)
    })
})

Файл server.js не проходит обработку через babel или webpack. Убедитесь, что синтаксис и используемые модули совместимы с текущей версией Node.js.

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

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

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

const next = require('next')
const app = next({})

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

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

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

Отключение файлового роутинга

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

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

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

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

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