output

빌드 중에 Next.js는 각 페이지와 그 종속성을 자동으로 추적하여 애플리케이션의 프로덕션 버전을 배포하는 데 필요한 모든 파일을 결정합니다.

이 기능은 배포 크기를 크게 줄이는 데 도움이 됩니다. 이전에는 Docker로 배포할 때 next start를 실행하기 위해 패키지의 dependencies에 있는 모든 파일을 설치해야 했습니다. Next.js 12부터는 .next/ 디렉토리의 Output File Tracing을 활용하여 필요한 파일만 포함할 수 있습니다.

또한, 이는 다양한 문제를 일으킬 수 있고 불필요한 중복을 생성하는 serverless 타겟을 사용할 필요성을 제거합니다.

How it Works

next build 중에 Next.js는 @vercel/nft (opens in a new tab)를 사용하여 import, requirefs 사용을 정적으로 분석하여 페이지가 로드할 수 있는 모든 파일을 결정합니다.

Next.js의 프로덕션 서버도 필요한 파일을 추적하여 .next/next-server.js.nft.json에 출력되며, 이는 프로덕션에서 활용할 수 있습니다.

.next 출력 디렉토리에 생성된 .nft.json 파일을 활용하려면, 각 추적 파일 목록을 읽어 해당 파일을 배포 위치에 복사할 수 있습니다.

Automatically Copying Traced Files

Next.js는 프로덕션 배포에 필요한 파일만 복사하는 standalone 폴더를 자동으로 생성할 수 있습니다. 여기에는 node_modules의 선택된 파일도 포함됩니다.

이 자동 복사를 활용하려면 next.config.js에서 이를 활성화할 수 있습니다:

next.config.js
module.exports = {
  output: 'standalone',
}

이렇게 하면 .next/standalone 폴더가 생성되며, 이는 node_modules를 설치하지 않고도 자체적으로 배포할 수 있습니다.

또한, next start 대신 사용할 수 있는 최소한의 server.js 파일도 출력됩니다. 이 최소한의 서버는 기본적으로 public 또는 .next/static 폴더를 복사하지 않으며, 이러한 폴더는 이상적으로 CDN에서 처리되어야 합니다. 그러나 이러한 폴더를 standalone/publicstandalone/.next/static 폴더로 수동으로 복사한 후 server.js 파일이 이를 자동으로 서비스합니다.

참고:

  • 프로젝트가 특정 포트 또는 호스트 이름을 수신해야 하는 경우, server.js를 실행하기 전에 PORT 또는 HOSTNAME 환경 변수를 정의할 수 있습니다. 예를 들어, PORT=8080 HOSTNAME=0.0.0.0 node server.js를 실행하여 서버를 http://0.0.0.0:8080에서 시작할 수 있습니다.

Caveats

  • 모노레포 설정에서 추적할 때 프로젝트 디렉토리가 기본적으로 추적에 사용됩니다. next build packages/web-app의 경우, packages/web-app이 추적 루트가 되며 해당 폴더 외부의 파일은 포함되지 않습니다. 이 폴더 외부의 파일을 포함하려면 next.config.js에서 experimental.outputFileTracingRoot를 설정할 수 있습니다.
packages/web-app/next.config.js
module.exports = {
  experimental: {
    // 모노레포 베이스에서 두 디렉토리 위의 파일을 포함합니다
    outputFileTracingRoot: path.join(__dirname, '../../'),
  },
}
  • Next.js가 필요한 파일을 포함하지 못하거나 사용하지 않는 파일을 잘못 포함하는 경우가 있습니다. 이러한 경우, next.config.js에서 각각 experimental.outputFileTracingExcludesexperimental.outputFileTracingIncludes를 활용할 수 있습니다. 각 구성은 특정 페이지와 일치하는 키에 대한 minimatch globs (opens in a new tab)를 사용하고, 프로젝트의 루트에 상대적인 glob 배열을 값으로 가질 수 있습니다.
next.config.js
module.exports = {
  experimental: {
    outputFileTracingExcludes: {
      '/api/hello': ['./un-necessary-folder/**/*'],
    },
    outputFileTracingIncludes: {
      '/api/another': ['./necessary-folder/**/*'],
    },
  },
}
  • 현재 Next.js는 생성된 .nft.json 파일로 아무것도 하지 않습니다. 예를 들어 Vercel (opens in a new tab)과 같은 배포 플랫폼이 최소 배포를 생성하기 위해 이 파일을 읽어야 합니다. 향후 릴리스에서는 이 .nft.json 파일을 활용하는 새로운 명령어가 계획되어 있습니다.

Experimental turbotrace

종속성을 추적하는 것은 매우 복잡한 계산과 분석이 필요하기 때문에 느릴 수 있습니다. 우리는 Rust로 작성된 turbotrace를 JavaScript 구현보다 빠르고 스마트한 대안으로 만들었습니다.

이를 활성화하려면 next.config.js에 다음 구성을 추가할 수 있습니다:

next.config.js
module.exports = {
  experimental: {
    turbotrace: {
      // turbotrace의 로그 레벨을 제어합니다. 기본값은 `error`입니다.
      logLevel?:
      | 'bug'
      | 'fatal'
      | 'error'
      | 'warning'
      | 'hint'
      | 'note'
      | 'suggestions'
      | 'info',
      // turbotrace의 로그가 분석의 세부 정보를 포함할지 여부를 제어합니다. 기본값은 `false`입니다.
      logDetail?: boolean
      // 제한 없이 모든 로그 메시지를 표시합니다.
      // turbotrace는 기본적으로 각 카테고리에 대해 1개의 로그 메시지만 표시합니다.
      logAll?: boolean
      // turbotrace의 컨텍스트 디렉토리를 제어합니다.
      // 컨텍스트 디렉토리 외부의 파일은 추적되지 않습니다.
      // `experimental.outputFileTracingRoot`를 설정하는 것과 동일한 효과가 있습니다.
      // `experimental.outputFileTracingRoot`와 이 옵션이 모두 설정된 경우, `experimental.turbotrace.contextDirectory`가 사용됩니다.
      contextDirectory?: string
      // 코드에 `process.cwd()` 표현이 있는 경우, 추적 중에 `turbotrace`에 `process.cwd()`의 값을 알려줄 수 있습니다.
      // 예를 들어 require(process.cwd() + '/package.json')은 require('/path/to/cwd/package.json')로 추적됩니다.
      processCwd?: string
      // `turbotrace`의 최대 메모리 사용량을 제어합니다. 단위는 `MB`이며 기본값은 `6000`입니다.
      memoryLimit?: number
    },
  },
}