mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
Make build output friendlier (#6320)
Success: ![image](https://user-images.githubusercontent.com/616428/52907314-5e636480-322d-11e9-9420-b348663a3a7a.png) Error: ![image](https://user-images.githubusercontent.com/616428/52907318-6c18ea00-322d-11e9-848d-e615d6af747d.png) Warnings: ![image](https://user-images.githubusercontent.com/616428/52907353-2d376400-322e-11e9-9778-370f36912491.png) --- We can still make build error output friendlier, but this is a good start.
This commit is contained in:
parent
3882979236
commit
7078f6567d
|
@ -1,11 +1,13 @@
|
|||
import webpack from 'webpack'
|
||||
|
||||
export type CompilerResult = {
|
||||
errors: Error[],
|
||||
errors: Error[]
|
||||
warnings: Error[]
|
||||
}
|
||||
|
||||
export function runCompiler (config: webpack.Configuration[]): Promise<CompilerResult> {
|
||||
export function runCompiler(
|
||||
config: webpack.Configuration[]
|
||||
): Promise<CompilerResult> {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
const compiler = webpack(config)
|
||||
compiler.run((err, multiStats: any) => {
|
||||
|
@ -13,17 +15,25 @@ export function runCompiler (config: webpack.Configuration[]): Promise<CompilerR
|
|||
return reject(err)
|
||||
}
|
||||
|
||||
const result: CompilerResult = multiStats.stats.reduce((result: CompilerResult, stat: webpack.Stats): CompilerResult => {
|
||||
if (stat.compilation.errors.length > 0) {
|
||||
result.errors.push(...stat.compilation.errors)
|
||||
}
|
||||
const result: CompilerResult = multiStats.stats.reduce(
|
||||
(result: CompilerResult, stat: webpack.Stats): CompilerResult => {
|
||||
const { errors, warnings } = stat.toJson({
|
||||
all: false,
|
||||
warnings: true,
|
||||
errors: true,
|
||||
})
|
||||
if (errors.length > 0) {
|
||||
result.errors.push(...errors)
|
||||
}
|
||||
|
||||
if (stat.compilation.warnings.length > 0) {
|
||||
result.warnings.push(...stat.compilation.warnings)
|
||||
}
|
||||
if (warnings.length > 0) {
|
||||
result.warnings.push(...warnings)
|
||||
}
|
||||
|
||||
return result
|
||||
}, {errors: [], warnings: []})
|
||||
return result
|
||||
},
|
||||
{ errors: [], warnings: [] }
|
||||
)
|
||||
|
||||
resolve(result)
|
||||
})
|
||||
|
|
|
@ -3,36 +3,53 @@ import nanoid from 'nanoid'
|
|||
import loadConfig from 'next-server/next-config'
|
||||
import { PHASE_PRODUCTION_BUILD } from 'next-server/constants'
|
||||
import getBaseWebpackConfig from './webpack-config'
|
||||
import {generateBuildId} from './generate-build-id'
|
||||
import {writeBuildId} from './write-build-id'
|
||||
import {isWriteable} from './is-writeable'
|
||||
import {runCompiler, CompilerResult} from './compiler'
|
||||
import { generateBuildId } from './generate-build-id'
|
||||
import { writeBuildId } from './write-build-id'
|
||||
import { isWriteable } from './is-writeable'
|
||||
import { runCompiler, CompilerResult } from './compiler'
|
||||
import globModule from 'glob'
|
||||
import {promisify} from 'util'
|
||||
import {createPagesMapping, createEntrypoints} from './entries'
|
||||
import { promisify } from 'util'
|
||||
import { createPagesMapping, createEntrypoints } from './entries'
|
||||
import formatWebpackMessages from '../client/dev-error-overlay/format-webpack-messages'
|
||||
import chalk from 'chalk'
|
||||
|
||||
const glob = promisify(globModule)
|
||||
|
||||
function collectPages (directory: string, pageExtensions: string[]): Promise<string[]> {
|
||||
return glob(`**/*.+(${pageExtensions.join('|')})`, {cwd: directory})
|
||||
function collectPages(
|
||||
directory: string,
|
||||
pageExtensions: string[]
|
||||
): Promise<string[]> {
|
||||
return glob(`**/*.+(${pageExtensions.join('|')})`, { cwd: directory })
|
||||
}
|
||||
|
||||
function printTreeView(list: string[]) {
|
||||
list
|
||||
.sort((a, b) => a > b ? 1 : -1)
|
||||
.sort((a, b) => (a > b ? 1 : -1))
|
||||
.forEach((item, i) => {
|
||||
const corner = i === 0 ? list.length === 1 ? '─' : '┌' : i === list.length - 1 ? '└' : '├'
|
||||
const corner =
|
||||
i === 0
|
||||
? list.length === 1
|
||||
? '─'
|
||||
: '┌'
|
||||
: i === list.length - 1
|
||||
? '└'
|
||||
: '├'
|
||||
console.log(` \x1b[90m${corner}\x1b[39m ${item}`)
|
||||
})
|
||||
|
||||
console.log()
|
||||
}
|
||||
|
||||
export default async function build (dir: string, conf = null): Promise<void> {
|
||||
if (!await isWriteable(dir)) {
|
||||
throw new Error('> Build directory is not writeable. https://err.sh/zeit/next.js/build-dir-not-writeable')
|
||||
export default async function build(dir: string, conf = null): Promise<void> {
|
||||
if (!(await isWriteable(dir))) {
|
||||
throw new Error(
|
||||
'> Build directory is not writeable. https://err.sh/zeit/next.js/build-dir-not-writeable'
|
||||
)
|
||||
}
|
||||
|
||||
console.log('Creating an optimized production build ...')
|
||||
console.log()
|
||||
|
||||
const config = loadConfig(PHASE_PRODUCTION_BUILD, dir, conf)
|
||||
const buildId = await generateBuildId(config.generateBuildId, nanoid)
|
||||
const distDir = join(dir, config.distDir)
|
||||
|
@ -42,34 +59,66 @@ export default async function build (dir: string, conf = null): Promise<void> {
|
|||
const pages = createPagesMapping(pagePaths, config.pageExtensions)
|
||||
const entrypoints = createEntrypoints(pages, config.target, buildId, config)
|
||||
const configs: any = await Promise.all([
|
||||
getBaseWebpackConfig(dir, { buildId, isServer: false, config, target: config.target, entrypoints: entrypoints.client }),
|
||||
getBaseWebpackConfig(dir, { buildId, isServer: true, config, target: config.target, entrypoints: entrypoints.server })
|
||||
getBaseWebpackConfig(dir, {
|
||||
buildId,
|
||||
isServer: false,
|
||||
config,
|
||||
target: config.target,
|
||||
entrypoints: entrypoints.client,
|
||||
}),
|
||||
getBaseWebpackConfig(dir, {
|
||||
buildId,
|
||||
isServer: true,
|
||||
config,
|
||||
target: config.target,
|
||||
entrypoints: entrypoints.server,
|
||||
}),
|
||||
])
|
||||
|
||||
let result: CompilerResult = {warnings: [], errors: []}
|
||||
let result: CompilerResult = { warnings: [], errors: [] }
|
||||
if (config.target === 'serverless') {
|
||||
if (config.publicRuntimeConfig) throw new Error('Cannot use publicRuntimeConfig with target=serverless https://err.sh/zeit/next.js/serverless-publicRuntimeConfig')
|
||||
if (config.publicRuntimeConfig)
|
||||
throw new Error(
|
||||
'Cannot use publicRuntimeConfig with target=serverless https://err.sh/zeit/next.js/serverless-publicRuntimeConfig'
|
||||
)
|
||||
|
||||
const clientResult = await runCompiler([configs[0]])
|
||||
// Fail build if clientResult contains errors
|
||||
if(clientResult.errors.length > 0) {
|
||||
result = {warnings: [...clientResult.warnings], errors: [...clientResult.errors]}
|
||||
if (clientResult.errors.length > 0) {
|
||||
result = {
|
||||
warnings: [...clientResult.warnings],
|
||||
errors: [...clientResult.errors],
|
||||
}
|
||||
} else {
|
||||
const serverResult = await runCompiler([configs[1]])
|
||||
result = {warnings: [...clientResult.warnings, ...serverResult.warnings], errors: [...clientResult.errors, ...serverResult.errors]}
|
||||
result = {
|
||||
warnings: [...clientResult.warnings, ...serverResult.warnings],
|
||||
errors: [...clientResult.errors, ...serverResult.errors],
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result = await runCompiler(configs)
|
||||
}
|
||||
|
||||
if (result.warnings.length > 0) {
|
||||
console.warn('> Emitted warnings from webpack')
|
||||
result.warnings.forEach((warning) => console.warn(warning))
|
||||
}
|
||||
result = formatWebpackMessages(result)
|
||||
|
||||
if (result.errors.length > 0) {
|
||||
result.errors.forEach((error) => console.error(error))
|
||||
// Only keep the first error. Others are often indicative
|
||||
// of the same problem, but confuse the reader with noise.
|
||||
if (result.errors.length > 1) {
|
||||
result.errors.length = 1
|
||||
}
|
||||
|
||||
console.error(chalk.red('Failed to compile.\n'))
|
||||
console.error(result.errors.join('\n\n'))
|
||||
console.error()
|
||||
throw new Error('> Build failed because of webpack errors')
|
||||
} else if (result.warnings.length > 0) {
|
||||
console.warn(chalk.yellow('Compiled with warnings.\n'))
|
||||
console.warn(result.warnings.join('\n\n'))
|
||||
console.warn()
|
||||
} else {
|
||||
console.log(chalk.green('Compiled successfully.\n'))
|
||||
}
|
||||
|
||||
printTreeView(Object.keys(pages))
|
||||
|
|
Loading…
Reference in a new issue