Next.jsMiddleTechnical

Что такое next.config.js и какие параметры конфигурации наиболее важны?

next.config.js/ts — корневой файл конфигурации Next.js. Ключевые параметры: images.remotePatterns, redirects/rewrites/headers (async функции), output: 'standalone' для Docker, compiler.removeConsole, experimental.typedRoutes.

next.config.js / next.config.ts

Файл конфигурации next.config.js (или next.config.ts начиная с Next.js 15) находится в корне проекта и позволяет настраивать компилятор, сборку, поведение сервера и многое другое. Экспортируется объект типа NextConfig.

// next.config.ts (Next.js 15+)
import type { NextConfig } from 'next';

const config: NextConfig = {
  // 1. Переменные окружения, доступные на клиенте
  env: {
    APP_VERSION: process.env.npm_package_version,
  },

  // 2. Публичные runtime-переменные (доступны через process.env на клиенте)
  // Альтернатива: префикс NEXT_PUBLIC_ в .env файлах

  // 3. Image Optimization
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'cdn.example.com',
        port: '',
        pathname: '/images/**',
      },
    ],
    formats: ['image/avif', 'image/webp'],
    deviceSizes: [640, 750, 828, 1080, 1200, 1920],
  },

  // 4. Redirects
  async redirects() {
    return [
      {
        source: '/old-jobs',
        destination: '/jobs',
        permanent: true, // 308
      },
      {
        source: '/blog/:slug',
        destination: '/articles/:slug',
        permanent: false, // 307
      },
    ];
  },

  // 5. Rewrites (прокси без смены URL)
  async rewrites() {
    return [
      {
        source: '/api/v1/:path*',
        destination: 'https://api.internal.example.com/:path*',
      },
    ];
  },

  // 6. Headers
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: [
          { key: 'X-Content-Type-Options', value: 'nosniff' },
          { key: 'X-Frame-Options', value: 'DENY' },
          {
            key: 'Content-Security-Policy',
            value: "default-src 'self'; img-src * data:;",
          },
        ],
      },
    ];
  },

  // 7. Webpack customization
  webpack(config, { isServer }) {
    if (!isServer) {
      config.resolve.fallback = { fs: false, net: false };
    }
    config.module.rules.push({
      test: /\.svg$/,
      use: ['@svgr/webpack'],
    });
    return config;
  },

  // 8. Compiler options
  compiler: {
    removeConsole: process.env.NODE_ENV === 'production',
  },

  // 9. Experimental features
  experimental: {
    turbo: {}, // Turbopack для dev (стабилен в 15.3+)
    typedRoutes: true, // типизированные href в Link
    serverActions: { bodySizeLimit: '2mb' },
  },

  // 10. Output mode
  output: 'standalone', // для Docker-деплоя: копирует только нужные зависимости

  // 11. Internationalization (App Router использует собственные механизмы,
  //     i18n в config актуален только для Pages Router)
  // i18n: { locales: ['en', 'ru'], defaultLocale: 'en' },

  // 12. Trailing slash
  trailingSlash: false,

  // 13. Base path (если приложение не в корне домена)
  // basePath: '/app',

  // 14. TypeScript и ESLint
  typescript: {
    ignoreBuildErrors: false, // никогда не ставить true в prod!
  },
  eslint: {
    ignoreDuringBuilds: false,
  },
};

export default config;

output: standalone для Docker

# Dockerfile
FROM node:22-alpine AS builder
WORKDIR /app
COPY . .
RUN npm ci && npm run build

FROM node:22-alpine AS runner
WORKDIR /app
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
EXPOSE 3000
CMD ["node", "server.js"]

Полезные флаги для продакшна

  • output: 'standalone' — уменьшает образ Docker, копируя только необходимые node_modules.
  • compiler.removeConsole — удаляет console.* из клиентского бандла в prod.
  • experimental.typedRoutes — добавляет TypeScript-проверку для всех href в компоненте Link.
  • images.remotePatterns — белый список внешних источников для <Image>; без этого next/image отказывает внешние URL.

Подводные камни

  • typescript.ignoreBuildErrors: true и eslint.ignoreDuringBuilds: true часто ставят «временно» и забывают убрать — в проде пойдут нетипизированные ошибки.
  • Функции redirects(), rewrites(), headers() должны возвращать Promise; синхронный возврат тоже работает, но нарушает типы и может сломаться в будущих версиях.
  • Изменения в next.config.js требуют перезапуска dev-сервера — горячая перезагрузка не применяется к конфигу.
  • При использовании output: 'standalone' файлы из public/ и .next/static нужно копировать вручную — они не включаются в standalone автоматически.
  • env в config встраивает значения во время сборки (build-time); если значение меняется в runtime, оно не применится без пересборки. Для runtime-переменных нужен NEXT_PUBLIC_ через process.env или runtimeConfig.
  • Webpack-конфиг вызывается дважды: для сервера и для клиента. Необходима проверка флага isServer, иначе серверные полифилы попадают в клиентский бандл.
  • Конфликт между rewrites и App Router Route Handlers: если rewrite совпадает с путём существующего Route Handler, обработчик не вызывается.

Common mistakes

  • Ждать, что next.config.js подхватит изменения без перезапуска
  • Полагаться на process.env.X в конфиге, не задав значение на build
  • Ставить CSP без nonce статикой
  • Использовать Pages-овский i18n в App Router

What the interviewer is testing

  • Знает основные секции конфига
  • Понимает порядок redirects → middleware → routing
  • Использует output: 'standalone' для Docker
  • Различает experimental и stable опции

Sources

Related topics