next.js 프로젝트를 세팅한 뒤 yarn start 스크립트를 실행하면
next.js/packages/next/cli 경로에 있는 next-start.ts 파일이
실행되고 코드는 아래와 같다.
코드를 이해하기 위해 import된 함수들의 로직을 주석으로 추가해보았다.
#!/usr/bin/env node
import arg from 'next/dist/compiled/arg/index.js'
import { startServer } from '../server/lib/start-server' // 서버를 실행하는 함수
import { getPort, printAndExit } from '../server/lib/utils'
// getPort
// export function getPort(args: arg.Result<arg.Spec>): number {
// (args['--port']의 타입이 숫자인 경우 args['--port']를 리턴)
// if (typeof args['--port'] === 'number') {
// return args['--port']
// }
//
// (env 파일에 존재하는 PORT 환경 변수)
// const parsed = process.env.PORT && parseInt(process.env.PORT, 10)
// (parsed가 숫자인 경우 parsed 리턴)
// if (typeof parsed === 'number' && !Number.isNaN(parsed)) {
// return parsed
// }
// (위 두 조건에 맞지 않는 경우 3000 리턴)
// return 3000
// }
// printAndExit
// export function printAndExit(message: string, code = 1) {
// if (code === 0) {
// console.log(message)
// } else {
// console.error(message)
// }
// (code가 0인 경우 어떤 종류의 오류도 없이 프로세스를 종료한다는 의미)
// (code가 1인 경우 일부 실패와 함께 프로세스를 종료한다는 의미)
// process.exit(code)
// }
import * as Log from '../build/output/log'
import isError from '../lib/is-error'
// isError
// lib.es5.d.ts 파일에 정의된 Error를 extends하여 NextError 정의
// export interface NextError extends Error {
// type?: string
// page?: string
// code?: string | number
// cancelled?: boolean
// }
//
// lib.es5.d.ts 파일에 정의된 Error의 타입
// interface Error {
// name: string;
// message: string;
// stack?: string;
// }
//
// export default function isError(err: unknown): err is NextError {
// return (
// typeof err === 'object' && err !== null && 'name' in err && 'message' in err
// )
// }
import { getProjectDir } from '../lib/get-project-dir'
import { cliCommand } from '../lib/commands'
// export type cliCommand = (argv?: string[]) => void
const nextStart: cliCommand = (argv) => {
const validArgs: arg.Spec = {
// Types
'--help': Boolean,
'--port': Number,
'--hostname': String,
'--keepAliveTimeout': Number,
// Aliases
'-h': '--help',
'-p': '--port',
'-H': '--hostname',
}
let args: arg.Result<arg.Spec>
try {
// nextStart 함수 내부에서 선언한 변수 validArgs와 nextStart 함수의 매개변수
// argv를 arg 함수의 인자로 넘기고 arg 함수가 리턴하는 값을 args에 재할당
args = arg(validArgs, { argv })
} catch (error) { // import한 isError와 printAndExit을 활용한 에러 처리
if (isError(error) && error.code === 'ARG_UNKNOWN_OPTION') {
return printAndExit(error.message, 1)
}
throw error
}
if (args['--help']) {
// npx next start -h를 터미널에 입력하면 실행되는 코드
console.log(`
Description
Starts the application in production mode.
The application should be compiled with \`next build\` first.
Usage
$ next start <dir> -p <port>
<dir> represents the directory of the Next.js application.
If no directory is provided, the current directory will be used.
Options
--port, -p A port number on which to start the application
--hostname, -H Hostname on which to start the application (default: 0.0.0.0)
--keepAliveTimeout Max milliseconds to wait before closing inactive connections
--help, -h Displays this message
`)
process.exit(0)
}
const dir = getProjectDir(args._[0])
const host = args['--hostname'] || '0.0.0.0'
const port = getPort(args)
const keepAliveTimeoutArg: number | undefined = args['--keepAliveTimeout']
if (
typeof keepAliveTimeoutArg !== 'undefined' &&
(Number.isNaN(keepAliveTimeoutArg) ||
!Number.isFinite(keepAliveTimeoutArg) ||
keepAliveTimeoutArg < 0)
) {
printAndExit(
`Invalid --keepAliveTimeout, expected a non negative number but received "${keepAliveTimeoutArg}"`,
1
)
}
const keepAliveTimeout = keepAliveTimeoutArg
? Math.ceil(keepAliveTimeoutArg)
: undefined
// 서버 실행
startServer({
dir,
hostname: host,
port,
keepAliveTimeout,
})
.then(async (app) => {
const appUrl = `http://${app.hostname}:${app.port}`
Log.ready(`started server on ${host}:${app.port}, url: ${appUrl}`)
await app.prepare()
})
.catch((err) => {
console.error(err)
process.exit(1)
})
}
export { nextStart }
확실하게 이해하지는 못했지만 서버 실행에 필요한 값들을 모듈화되어 있는 함수들을 활용해서
선언해준 뒤 그 값들을 활용해 에러 처리를 한 후 서버를 실행하는 것으로 요약할 수 있을 것 같다.
진우님 화이팅