Polish turbopack start logging (#57203)

Bring a tiny util to get a `(turbo)` label after next.js info for turbopack dev-server logging and also remove the disclaimer of "thank you for trying".

### After

<img width="597" alt="image" src="https://github.com/vercel/next.js/assets/4800338/c3658775-3ce6-48fc-8128-7baebe9f104b">


### Before

<img width="597" alt="image" src="https://github.com/vercel/next.js/assets/4800338/d008dd0b-4c58-4612-b1c4-d5e97e041c1b">


* Fixes the bad dim color
* Colorize the `Next.js (turbo)` label
* Move the learning link down after start message
* Use Log util to format logs
* Remove "v13" related text
This commit is contained in:
Jiachi Liu 2023-10-22 19:53:40 -07:00 committed by GitHub
parent ac00e86452
commit c5207751a2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 71 additions and 81 deletions

View file

@ -4,7 +4,7 @@ export const prefixes = {
wait: white(bold('○')),
error: red(bold('')),
warn: yellow(bold('⚠')),
ready: bold('▲'), // no color
ready: '▲', // no color
info: white(bold(' ')),
event: green(bold('✓')),
trace: magenta(bold('»')),

View file

@ -28,7 +28,6 @@ import type { SelfSignedCertificate } from '../lib/mkcert'
import uploadTrace from '../trace/upload-trace'
import { initialEnv } from '@next/env'
import { trace } from '../trace'
import { validateTurboNextConfig } from '../lib/turbopack-warning'
import { fork } from 'child_process'
import {
getReservedPortExplanation,
@ -214,13 +213,7 @@ const nextDev: CliCommand = async (args) => {
process.env.TURBOPACK = '1'
}
if (process.env.TURBOPACK) {
isTurboSession = true
await validateTurboNextConfig({
...devServerOptions,
isDev: true,
})
}
isTurboSession = !!process.env.TURBOPACK
const distDir = path.join(dir, config.distDir ?? '.next')
setGlobal('phase', PHASE_DEVELOPMENT_SERVER)

View file

@ -1,6 +1,7 @@
import type { NextConfig } from '../server/config-shared'
import path from 'path'
import loadConfig from '../server/config'
import type { NextConfig } from '../server/config-shared'
import * as Log from '../build/output/log'
import { PHASE_DEVELOPMENT_SERVER } from '../shared/lib/constants'
const supportedTurbopackNextConfigOptions = [
@ -171,34 +172,17 @@ export async function validateTurboNextConfig({
require('../build/get-babel-config-file') as typeof import('../build/get-babel-config-file')
const { defaultConfig } =
require('../server/config-shared') as typeof import('../server/config-shared')
const { bold, cyan, dim, red, underline, yellow } =
const { bold, cyan, red, underline } =
require('../lib/picocolors') as typeof import('../lib/picocolors')
const { interopDefault } =
require('../lib/interop-default') as typeof import('../lib/interop-default')
// To regenerate the TURBOPACK gradient require('gradient-string')('blue', 'red')('>>> TURBOPACK')
const isTTY = process.stdout.isTTY
const turbopackGradient = `${bold(
isTTY
? '\x1B[38;2;0;0;255m>\x1B[39m\x1B[38;2;23;0;232m>\x1B[39m\x1B[38;2;46;0;209m>\x1B[39m \x1B[38;2;70;0;185mT\x1B[39m\x1B[38;2;93;0;162mU\x1B[39m\x1B[38;2;116;0;139mR\x1B[39m\x1B[38;2;139;0;116mB\x1B[39m\x1B[38;2;162;0;93mO\x1B[39m\x1B[38;2;185;0;70mP\x1B[39m\x1B[38;2;209;0;46mA\x1B[39m\x1B[38;2;232;0;23mC\x1B[39m\x1B[38;2;255;0;0mK\x1B[39m'
: '>>> TURBOPACK'
)} ${dim('(beta)')}\n\n`
let thankYouMessage =
[
'Thank you for trying Next.js v13 with Turbopack! As a reminder',
'Turbopack is currently in beta and not yet ready for production.',
'We appreciate your ongoing support as we work to make it ready',
'for everyone.',
].join('\n') + '\n\n'
let unsupportedParts = ''
let babelrc = await getBabelConfigFile(dir)
if (babelrc) babelrc = path.basename(babelrc)
let hasWebpack = false
let hasTurbo = false
let hasTurbo = !!process.env.TURBOPACK
let unsupportedConfig: string[] = []
let rawNextConfig: NextConfig = {}
@ -275,30 +259,24 @@ export async function validateTurboNextConfig({
}
}
} catch (e) {
console.error('Unexpected error occurred while checking config', e)
Log.error('Unexpected error occurred while checking config', e)
}
const hasWarningOrError = babelrc || unsupportedConfig.length
if (!hasWarningOrError) {
thankYouMessage = dim(thankYouMessage)
}
console.log(turbopackGradient + thankYouMessage)
let feedbackMessage = `Learn more about Next.js v13 and Turbopack: ${underline(
let feedbackMessage = `Learn more about Next.js and Turbopack: ${underline(
'https://nextjs.link/with-turbopack'
)}\n`
if (hasWebpack && !hasTurbo) {
console.warn(
`\n${yellow(
'Warning:'
)} Webpack is configured while Turbopack is not, which may cause problems.\n
${`See instructions if you need to configure Turbopack:\n https://turbo.build/pack/docs/features/customizing-turbopack\n`}`
Log.warn(
`Webpack is configured while Turbopack is not, which may cause problems.`
)
Log.warn(
`See instructions if you need to configure Turbopack:\n https://turbo.build/pack/docs/features/customizing-turbopack\n`
)
}
if (babelrc) {
unsupportedParts += `\n- Babel detected (${cyan(
unsupportedParts += `Babel detected (${cyan(
babelrc
)})\n Babel is not yet supported. To use Turbopack at the moment,\n you'll need to remove your usage of Babel.`
}
@ -307,10 +285,8 @@ export async function validateTurboNextConfig({
unsupportedConfig.length === 1 &&
unsupportedConfig[0] === 'experimental.optimizePackageImports'
) {
console.warn(
`\n${yellow('Warning:')} ${cyan(
'experimental.optimizePackageImports'
)} is not yet supported by Turbopack and will be ignored.`
Log.warn(
`'experimental.optimizePackageImports' is not yet supported by Turbopack and will be ignored.`
)
} else if (unsupportedConfig.length) {
unsupportedParts += `\n\n- Unsupported Next.js configuration option(s) (${cyan(
@ -323,9 +299,9 @@ export async function validateTurboNextConfig({
if (unsupportedParts) {
const pkgManager = getPkgManager(dir)
console.error(
`Error: You are using configuration and/or tools that are not yet\nsupported by Next.js v13 with Turbopack:\n${unsupportedParts}\n
If you cannot make the changes above, but still want to try out\nNext.js v13 with Turbopack, create the Next.js v13 playground app\nby running the following commands:
Log.error(
`You are using configuration and/or tools that are not yet\nsupported by Next.js with Turbopack:\n${unsupportedParts}\n
If you cannot make the changes above, but still want to try out\nNext.js with Turbopack, create the Next.js playground app\nby running the following commands:
${bold(
cyan(
@ -339,12 +315,12 @@ If you cannot make the changes above, but still want to try out\nNext.js v13 wit
`
)
console.warn(feedbackMessage)
Log.warn(feedbackMessage)
process.exit(1)
}
console.log(feedbackMessage)
Log.info(feedbackMessage)
return rawNextConfig
}

View file

@ -14,13 +14,19 @@ export function logStartInfo({
}: {
networkUrl: string | null
appUrl: string | null
formatDurationText: string | null
maxExperimentalFeatures?: number
envInfo?: string[]
expFeatureInfo?: string[]
formatDurationText: string | null
maxExperimentalFeatures?: number
}) {
Log.bootstrap(
bold(purple(`${Log.prefixes.ready} Next.js ${process.env.__NEXT_VERSION}`))
bold(
purple(
`${Log.prefixes.ready} Next.js ${process.env.__NEXT_VERSION}${
process.env.TURBOPACK ? ' (turbo)' : ''
}`
)
)
)
if (appUrl) {
Log.bootstrap(`- Local: ${appUrl}`)

View file

@ -9,6 +9,7 @@ import type { SelfSignedCertificate } from '../../lib/mkcert'
import type { WorkerRequestHandler, WorkerUpgradeHandler } from './types'
import fs from 'fs'
import v8 from 'v8'
import path from 'path'
import http from 'http'
import https from 'https'
@ -20,7 +21,8 @@ import { formatHostname } from './format-hostname'
import { initialize } from './router-server'
import { CONFIG_FILES } from '../../shared/lib/constants'
import { getStartServerInfo, logStartInfo } from './app-info-log'
import v8 from 'v8'
import { validateTurboNextConfig } from '../../lib/turbopack-warning'
const debug = setupDebug('next:start-server')
export interface StartServerOptions {
@ -74,17 +76,21 @@ export async function getRequestHandlers({
})
}
export async function startServer({
dir,
port,
isDev,
hostname,
minimalMode,
allowRetry,
keepAliveTimeout,
isExperimentalTestProxy,
selfSignedCertificate,
}: StartServerOptions): Promise<void> {
export async function startServer(
serverOptions: StartServerOptions
): Promise<void> {
const {
dir,
isDev,
hostname,
minimalMode,
allowRetry,
keepAliveTimeout,
isExperimentalTestProxy,
selfSignedCertificate,
} = serverOptions
let { port } = serverOptions
process.title = 'next-server'
let handlersReady = () => {}
let handlersError = () => {}
@ -292,6 +298,12 @@ export async function startServer({
formatDurationText,
maxExperimentalFeatures: 3,
})
if (process.env.TURBOPACK) {
await validateTurboNextConfig({
...serverOptions,
isDev: true,
})
}
} catch (err) {
// fatal error if we can't setup
handlersError()

View file

@ -1,4 +1,10 @@
import { findPort, killApp, launchApp, renderViaHTTP } from 'next-test-utils'
import {
check,
findPort,
killApp,
launchApp,
renderViaHTTP,
} from 'next-test-utils'
import fs from 'fs-extra'
import { join } from 'path'
@ -19,13 +25,11 @@ describe('turbopack unsupported features log', () => {
})
try {
expect(output).toContain(
'Thank you for trying Next.js v13 with Turbopack!'
)
expect(await renderViaHTTP(appPort, '/')).toContain('hello world')
expect(output).toContain('(turbo)')
expect(output).not.toContain(
'You are using configuration and/or tools that are not yet'
)
expect(await renderViaHTTP(appPort, '/')).toContain('hello world')
} finally {
await killApp(app).catch(() => {})
}
@ -46,9 +50,7 @@ describe('turbopack unsupported features log', () => {
})
try {
expect(output).toContain(
'Thank you for trying Next.js v13 with Turbopack!'
)
expect(output).toContain('(turbo)')
expect(output).not.toContain(
'You are using configuration and/or tools that are not yet'
)
@ -81,12 +83,13 @@ describe('turbopack unsupported features log', () => {
})
try {
expect(output).toContain(
'Thank you for trying Next.js v13 with Turbopack!'
)
expect(output).toContain(
'You are using configuration and/or tools that are not yet'
)
await check(() => {
expect(output).toContain('(turbo)')
expect(output).toContain(
'You are using configuration and/or tools that are not yet'
)
return 'success'
}, /success/)
} finally {
await killApp(app).catch(() => {})
await fs.remove(nextConfigPath)