[Feature] Progress bar for static build (#15297)
Co-authored-by: Tim Neutkens <timneutkens@me.com> Co-authored-by: JJ Kasper <jj@jjsweb.site>
This commit is contained in:
parent
1ea8bdcdc7
commit
6c59cbb46a
15 changed files with 129 additions and 122 deletions
|
@ -75,6 +75,8 @@ import {
|
||||||
import getBaseWebpackConfig from './webpack-config'
|
import getBaseWebpackConfig from './webpack-config'
|
||||||
import { PagesManifest } from './webpack/plugins/pages-manifest-plugin'
|
import { PagesManifest } from './webpack/plugins/pages-manifest-plugin'
|
||||||
import { writeBuildId } from './write-build-id'
|
import { writeBuildId } from './write-build-id'
|
||||||
|
import * as Log from './output/log'
|
||||||
|
|
||||||
const staticCheckWorker = require.resolve('./utils')
|
const staticCheckWorker = require.resolve('./utils')
|
||||||
|
|
||||||
export type SsgRoute = {
|
export type SsgRoute = {
|
||||||
|
@ -126,17 +128,13 @@ export default async function build(
|
||||||
// Intentionally not piping to stderr in case people fail in CI when
|
// Intentionally not piping to stderr in case people fail in CI when
|
||||||
// stderr is detected.
|
// stderr is detected.
|
||||||
console.log(
|
console.log(
|
||||||
chalk.bold.yellow(`Warning: `) +
|
`${Log.prefixes.warn} No build cache found. Please configure build caching for faster rebuilds. Read more: https://err.sh/next.js/no-cache`
|
||||||
chalk.bold(
|
|
||||||
`No build cache found. Please configure build caching for faster rebuilds. Read more: https://err.sh/next.js/no-cache`
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
console.log('')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildSpinner = createSpinner({
|
const buildSpinner = createSpinner({
|
||||||
prefixText: 'Creating an optimized production build',
|
prefixText: `${Log.prefixes.info} Creating an optimized production build`,
|
||||||
})
|
})
|
||||||
|
|
||||||
const telemetry = new Telemetry({ distDir })
|
const telemetry = new Telemetry({ distDir })
|
||||||
|
@ -243,16 +241,10 @@ export default async function build(
|
||||||
})
|
})
|
||||||
|
|
||||||
if (nestedReservedPages.length) {
|
if (nestedReservedPages.length) {
|
||||||
console.warn(
|
Log.warn(
|
||||||
'\n' +
|
`The following reserved Next.js pages were detected not directly under the pages directory:\n` +
|
||||||
chalk.bold.yellow(`Warning: `) +
|
|
||||||
chalk.bold(
|
|
||||||
`The following reserved Next.js pages were detected not directly under the pages directory:\n`
|
|
||||||
) +
|
|
||||||
nestedReservedPages.join('\n') +
|
nestedReservedPages.join('\n') +
|
||||||
chalk.bold(
|
`\nSee more info here: https://err.sh/next.js/nested-reserved-page\n`
|
||||||
`\nSee more info here: https://err.sh/next.js/nested-reserved-page\n`
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,11 +346,8 @@ export default async function build(
|
||||||
(clientConfig.optimization.minimizer &&
|
(clientConfig.optimization.minimizer &&
|
||||||
clientConfig.optimization.minimizer.length === 0))
|
clientConfig.optimization.minimizer.length === 0))
|
||||||
) {
|
) {
|
||||||
console.warn(
|
Log.warn(
|
||||||
chalk.bold.yellow(`Warning: `) +
|
`Production code optimization has been disabled in your project. Read more: https://err.sh/vercel/next.js/minification-disabled`
|
||||||
chalk.bold(
|
|
||||||
`Production code optimization has been disabled in your project. Read more: https://err.sh/vercel/next.js/minification-disabled`
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,7 +378,6 @@ export default async function build(
|
||||||
if (buildSpinner) {
|
if (buildSpinner) {
|
||||||
buildSpinner.stopAndPersist()
|
buildSpinner.stopAndPersist()
|
||||||
}
|
}
|
||||||
console.log()
|
|
||||||
|
|
||||||
result = formatWebpackMessages(result)
|
result = formatWebpackMessages(result)
|
||||||
|
|
||||||
|
@ -435,15 +423,16 @@ export default async function build(
|
||||||
)
|
)
|
||||||
|
|
||||||
if (result.warnings.length > 0) {
|
if (result.warnings.length > 0) {
|
||||||
console.warn(chalk.yellow('Compiled with warnings.\n'))
|
Log.warn('Compiled with warnings\n')
|
||||||
console.warn(result.warnings.join('\n\n'))
|
console.warn(result.warnings.join('\n\n'))
|
||||||
console.warn()
|
console.warn()
|
||||||
} else {
|
} else {
|
||||||
console.log(chalk.green('Compiled successfully.\n'))
|
Log.info('Compiled successfully')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const postBuildSpinner = createSpinner({
|
|
||||||
prefixText: 'Automatically optimizing pages',
|
const postCompileSpinner = createSpinner({
|
||||||
|
prefixText: `${Log.prefixes.info} Collecting page data`,
|
||||||
})
|
})
|
||||||
|
|
||||||
const manifestPath = path.join(
|
const manifestPath = path.join(
|
||||||
|
@ -685,15 +674,18 @@ export default async function build(
|
||||||
const finalPrerenderRoutes: { [route: string]: SsgRoute } = {}
|
const finalPrerenderRoutes: { [route: string]: SsgRoute } = {}
|
||||||
const tbdPrerenderRoutes: string[] = []
|
const tbdPrerenderRoutes: string[] = []
|
||||||
|
|
||||||
|
if (postCompileSpinner) postCompileSpinner.stopAndPersist()
|
||||||
|
|
||||||
if (staticPages.size > 0 || ssgPages.size > 0 || useStatic404) {
|
if (staticPages.size > 0 || ssgPages.size > 0 || useStatic404) {
|
||||||
const combinedPages = [...staticPages, ...ssgPages]
|
const combinedPages = [...staticPages, ...ssgPages]
|
||||||
const exportApp = require('../export').default
|
const exportApp = require('../export').default
|
||||||
const exportOptions = {
|
const exportOptions = {
|
||||||
silent: true,
|
silent: false,
|
||||||
buildExport: true,
|
buildExport: true,
|
||||||
threads: config.experimental.cpus,
|
threads: config.experimental.cpus,
|
||||||
pages: combinedPages,
|
pages: combinedPages,
|
||||||
outdir: path.join(distDir, 'export'),
|
outdir: path.join(distDir, 'export'),
|
||||||
|
statusMessage: 'Generating static pages',
|
||||||
}
|
}
|
||||||
const exportConfig: any = {
|
const exportConfig: any = {
|
||||||
...config,
|
...config,
|
||||||
|
@ -745,6 +737,10 @@ export default async function build(
|
||||||
|
|
||||||
await exportApp(dir, exportOptions, exportConfig)
|
await exportApp(dir, exportOptions, exportConfig)
|
||||||
|
|
||||||
|
const postBuildSpinner = createSpinner({
|
||||||
|
prefixText: `${Log.prefixes.info} Finalizing page optimization`,
|
||||||
|
})
|
||||||
|
|
||||||
// remove server bundles that were exported
|
// remove server bundles that were exported
|
||||||
for (const page of staticPages) {
|
for (const page of staticPages) {
|
||||||
const serverBundle = getPagePath(page, distDir, isLikeServerless)
|
const serverBundle = getPagePath(page, distDir, isLikeServerless)
|
||||||
|
@ -876,10 +872,10 @@ export default async function build(
|
||||||
JSON.stringify(pagesManifest, null, 2),
|
JSON.stringify(pagesManifest, null, 2),
|
||||||
'utf8'
|
'utf8'
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
if (postBuildSpinner) postBuildSpinner.stopAndPersist()
|
if (postBuildSpinner) postBuildSpinner.stopAndPersist()
|
||||||
console.log()
|
console.log()
|
||||||
|
}
|
||||||
|
|
||||||
const analysisEnd = process.hrtime(analysisBegin)
|
const analysisEnd = process.hrtime(analysisBegin)
|
||||||
telemetry.record(
|
telemetry.record(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import chalk from 'next/dist/compiled/chalk'
|
import chalk from 'next/dist/compiled/chalk'
|
||||||
|
|
||||||
const prefixes = {
|
export const prefixes = {
|
||||||
wait: chalk.cyan('wait') + ' -',
|
wait: chalk.cyan('wait') + ' -',
|
||||||
error: chalk.red('error') + ' -',
|
error: chalk.red('error') + ' -',
|
||||||
warn: chalk.yellow('warn') + ' -',
|
warn: chalk.yellow('warn') + ' -',
|
||||||
|
@ -14,11 +14,11 @@ export function wait(...message: string[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function error(...message: string[]) {
|
export function error(...message: string[]) {
|
||||||
console.log(prefixes.error, ...message)
|
console.error(prefixes.error, ...message)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function warn(...message: string[]) {
|
export function warn(...message: string[]) {
|
||||||
console.log(prefixes.warn, ...message)
|
console.warn(prefixes.warn, ...message)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ready(...message: string[]) {
|
export function ready(...message: string[]) {
|
||||||
|
|
|
@ -7,7 +7,8 @@ const dotsSpinner = {
|
||||||
|
|
||||||
export default function createSpinner(
|
export default function createSpinner(
|
||||||
text: string | { prefixText: string },
|
text: string | { prefixText: string },
|
||||||
options: ora.Options = {}
|
options: ora.Options = {},
|
||||||
|
logFn: (...data: any[]) => void = console.log
|
||||||
) {
|
) {
|
||||||
let spinner: undefined | ora.Ora
|
let spinner: undefined | ora.Ora
|
||||||
let prefixText = text && typeof text === 'object' && text.prefixText
|
let prefixText = text && typeof text === 'object' && text.prefixText
|
||||||
|
@ -55,7 +56,7 @@ export default function createSpinner(
|
||||||
return spinner!
|
return spinner!
|
||||||
}
|
}
|
||||||
} else if (prefixText || text) {
|
} else if (prefixText || text) {
|
||||||
console.log(prefixText ? prefixText + '...' : text)
|
logFn(prefixText ? prefixText + '...' : text)
|
||||||
}
|
}
|
||||||
|
|
||||||
return spinner
|
return spinner
|
||||||
|
|
|
@ -12,6 +12,7 @@ import { cpus } from 'os'
|
||||||
import { dirname, join, resolve, sep } from 'path'
|
import { dirname, join, resolve, sep } from 'path'
|
||||||
import { promisify } from 'util'
|
import { promisify } from 'util'
|
||||||
import { AmpPageStatus, formatAmpMessages } from '../build/output/index'
|
import { AmpPageStatus, formatAmpMessages } from '../build/output/index'
|
||||||
|
import * as Log from '../build/output/log'
|
||||||
import createSpinner from '../build/spinner'
|
import createSpinner from '../build/spinner'
|
||||||
import { API_ROUTE, SSG_FALLBACK_EXPORT_ERROR } from '../lib/constants'
|
import { API_ROUTE, SSG_FALLBACK_EXPORT_ERROR } from '../lib/constants'
|
||||||
import { recursiveCopy } from '../lib/recursive-copy'
|
import { recursiveCopy } from '../lib/recursive-copy'
|
||||||
|
@ -97,6 +98,7 @@ interface ExportOptions {
|
||||||
threads?: number
|
threads?: number
|
||||||
pages?: string[]
|
pages?: string[]
|
||||||
buildExport?: boolean
|
buildExport?: boolean
|
||||||
|
statusMessage?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function exportApp(
|
export default async function exportApp(
|
||||||
|
@ -104,13 +106,6 @@ export default async function exportApp(
|
||||||
options: ExportOptions,
|
options: ExportOptions,
|
||||||
configuration?: any
|
configuration?: any
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
function log(message: string): void {
|
|
||||||
if (options.silent) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
console.log(message)
|
|
||||||
}
|
|
||||||
|
|
||||||
dir = resolve(dir)
|
dir = resolve(dir)
|
||||||
|
|
||||||
// attempt to load global env values so they are available in next.config.js
|
// attempt to load global env values so they are available in next.config.js
|
||||||
|
@ -136,7 +131,9 @@ export default async function exportApp(
|
||||||
const subFolders = nextConfig.trailingSlash
|
const subFolders = nextConfig.trailingSlash
|
||||||
const isLikeServerless = nextConfig.target !== 'server'
|
const isLikeServerless = nextConfig.target !== 'server'
|
||||||
|
|
||||||
log(`> using build directory: ${distDir}`)
|
if (!options.silent && !options.buildExport) {
|
||||||
|
Log.info(`using build directory: ${distDir}`)
|
||||||
|
}
|
||||||
|
|
||||||
if (!existsSync(distDir)) {
|
if (!existsSync(distDir)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
|
@ -213,13 +210,20 @@ export default async function exportApp(
|
||||||
|
|
||||||
// Copy static directory
|
// Copy static directory
|
||||||
if (!options.buildExport && existsSync(join(dir, 'static'))) {
|
if (!options.buildExport && existsSync(join(dir, 'static'))) {
|
||||||
log(' copying "static" directory')
|
if (!options.silent) {
|
||||||
|
Log.info('Copying "static" directory')
|
||||||
|
}
|
||||||
await recursiveCopy(join(dir, 'static'), join(outDir, 'static'))
|
await recursiveCopy(join(dir, 'static'), join(outDir, 'static'))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy .next/static directory
|
// Copy .next/static directory
|
||||||
if (existsSync(join(distDir, CLIENT_STATIC_FILES_PATH))) {
|
if (
|
||||||
log(' copying "static build" directory')
|
!options.buildExport &&
|
||||||
|
existsSync(join(distDir, CLIENT_STATIC_FILES_PATH))
|
||||||
|
) {
|
||||||
|
if (!options.silent) {
|
||||||
|
Log.info('Copying "static build" directory')
|
||||||
|
}
|
||||||
await recursiveCopy(
|
await recursiveCopy(
|
||||||
join(distDir, CLIENT_STATIC_FILES_PATH),
|
join(distDir, CLIENT_STATIC_FILES_PATH),
|
||||||
join(outDir, '_next', CLIENT_STATIC_FILES_PATH)
|
join(outDir, '_next', CLIENT_STATIC_FILES_PATH)
|
||||||
|
@ -228,9 +232,11 @@ export default async function exportApp(
|
||||||
|
|
||||||
// Get the exportPathMap from the config file
|
// Get the exportPathMap from the config file
|
||||||
if (typeof nextConfig.exportPathMap !== 'function') {
|
if (typeof nextConfig.exportPathMap !== 'function') {
|
||||||
console.log(
|
if (!options.silent) {
|
||||||
`> No "exportPathMap" found in "${CONFIG_FILE}". Generating map from "./pages"`
|
Log.info(
|
||||||
)
|
`No "exportPathMap" found in "${CONFIG_FILE}". Generating map from "./pages"`
|
||||||
|
)
|
||||||
|
}
|
||||||
nextConfig.exportPathMap = async (defaultMap: ExportPathMap) => {
|
nextConfig.exportPathMap = async (defaultMap: ExportPathMap) => {
|
||||||
return defaultMap
|
return defaultMap
|
||||||
}
|
}
|
||||||
|
@ -264,7 +270,9 @@ export default async function exportApp(
|
||||||
nextExport: true,
|
nextExport: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
log(` launching ${threads} workers`)
|
if (!options.silent && !options.buildExport) {
|
||||||
|
Log.info(`Launching ${threads} workers`)
|
||||||
|
}
|
||||||
const exportPathMap = await nextConfig.exportPathMap(defaultPathMap, {
|
const exportPathMap = await nextConfig.exportPathMap(defaultPathMap, {
|
||||||
dev: false,
|
dev: false,
|
||||||
dir,
|
dir,
|
||||||
|
@ -322,27 +330,35 @@ export default async function exportApp(
|
||||||
|
|
||||||
// Warn if the user defines a path for an API page
|
// Warn if the user defines a path for an API page
|
||||||
if (hasApiRoutes) {
|
if (hasApiRoutes) {
|
||||||
log(
|
if (!options.silent) {
|
||||||
chalk.bold.red(`Warning`) +
|
Log.warn(
|
||||||
': ' +
|
|
||||||
chalk.yellow(
|
chalk.yellow(
|
||||||
`Statically exporting a Next.js application via \`next export\` disables API routes.`
|
`Statically exporting a Next.js application via \`next export\` disables API routes.`
|
||||||
) +
|
) +
|
||||||
`\n` +
|
`\n` +
|
||||||
chalk.yellow(
|
chalk.yellow(
|
||||||
`This command is meant for static-only hosts, and is` +
|
`This command is meant for static-only hosts, and is` +
|
||||||
' ' +
|
' ' +
|
||||||
chalk.bold(`not necessary to make your application static.`)
|
chalk.bold(`not necessary to make your application static.`)
|
||||||
) +
|
) +
|
||||||
`\n` +
|
`\n` +
|
||||||
chalk.yellow(
|
chalk.yellow(
|
||||||
`Pages in your application without server-side data dependencies will be automatically statically exported by \`next build\`, including pages powered by \`getStaticProps\`.`
|
`Pages in your application without server-side data dependencies will be automatically statically exported by \`next build\`, including pages powered by \`getStaticProps\`.`
|
||||||
) +
|
) +
|
||||||
`\nLearn more: https://err.sh/vercel/next.js/api-routes-static-export`
|
`\n` +
|
||||||
)
|
chalk.yellow(
|
||||||
|
`Learn more: https://err.sh/vercel/next.js/api-routes-static-export`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const progress = !options.silent && createProgress(filteredPaths.length)
|
const progress =
|
||||||
|
!options.silent &&
|
||||||
|
createProgress(
|
||||||
|
filteredPaths.length,
|
||||||
|
`${Log.prefixes.info} ${options.statusMessage}`
|
||||||
|
)
|
||||||
const pagesDataDir = options.buildExport
|
const pagesDataDir = options.buildExport
|
||||||
? outDir
|
? outDir
|
||||||
: join(outDir, '_next/data', buildId)
|
: join(outDir, '_next/data', buildId)
|
||||||
|
@ -353,7 +369,9 @@ export default async function exportApp(
|
||||||
const publicDir = join(dir, CLIENT_PUBLIC_FILES_PATH)
|
const publicDir = join(dir, CLIENT_PUBLIC_FILES_PATH)
|
||||||
// Copy public directory
|
// Copy public directory
|
||||||
if (!options.buildExport && existsSync(publicDir)) {
|
if (!options.buildExport && existsSync(publicDir)) {
|
||||||
log(' copying "public" directory')
|
if (!options.silent) {
|
||||||
|
Log.info('Copying "public" directory')
|
||||||
|
}
|
||||||
await recursiveCopy(publicDir, outDir, {
|
await recursiveCopy(publicDir, outDir, {
|
||||||
filter(path) {
|
filter(path) {
|
||||||
// Exclude paths used by pages
|
// Exclude paths used by pages
|
||||||
|
@ -476,8 +494,6 @@ export default async function exportApp(
|
||||||
.join('\n\t')}`
|
.join('\n\t')}`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// Add an empty line to the console for the better readability.
|
|
||||||
log('')
|
|
||||||
|
|
||||||
writeFileSync(
|
writeFileSync(
|
||||||
join(distDir, EXPORT_DETAIL),
|
join(distDir, EXPORT_DETAIL),
|
||||||
|
|
|
@ -238,9 +238,8 @@ export default function loadConfig(
|
||||||
)
|
)
|
||||||
|
|
||||||
if (Object.keys(userConfig).length === 0) {
|
if (Object.keys(userConfig).length === 0) {
|
||||||
console.warn(
|
Log.warn(
|
||||||
chalk.yellow.bold('Warning: ') +
|
'Detected next.config.js, no exported configuration found. https://err.sh/vercel/next.js/empty-configuration'
|
||||||
'Detected next.config.js, no exported configuration found. https://err.sh/vercel/next.js/empty-configuration'
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -430,12 +430,12 @@ function runTests(dev = false) {
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
it('should show warning with next export', async () => {
|
it('should show warning with next export', async () => {
|
||||||
const { stdout } = await nextExport(
|
const { stderr } = await nextExport(
|
||||||
appDir,
|
appDir,
|
||||||
{ outdir: join(appDir, 'out') },
|
{ outdir: join(appDir, 'out') },
|
||||||
{ stdout: true }
|
{ stderr: true }
|
||||||
)
|
)
|
||||||
expect(stdout).toContain(
|
expect(stderr).toContain(
|
||||||
'https://err.sh/vercel/next.js/api-routes-static-export'
|
'https://err.sh/vercel/next.js/api-routes-static-export'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -19,9 +19,9 @@ describe('Empty configuration', () => {
|
||||||
stderr: true,
|
stderr: true,
|
||||||
stdout: true,
|
stdout: true,
|
||||||
})
|
})
|
||||||
expect(stdout).toMatch(/Compiled successfully./)
|
expect(stdout).toMatch(/Compiled successfully/)
|
||||||
expect(stderr).toMatch(
|
expect(stderr).toMatch(
|
||||||
/Warning: Detected next.config.js, no exported configuration found. https:\/\/err.sh\/vercel\/next.js\/empty-configuration/
|
/Detected next\.config\.js, no exported configuration found\. https:\/\/err\.sh\/vercel\/next\.js\/empty-configuration/
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ describe('Empty configuration', () => {
|
||||||
await killApp(app)
|
await killApp(app)
|
||||||
|
|
||||||
expect(stderr).toMatch(
|
expect(stderr).toMatch(
|
||||||
/Warning: Detected next.config.js, no exported configuration found. https:\/\/err.sh\/vercel\/next.js\/empty-configuration/
|
/Detected next\.config\.js, no exported configuration found\. https:\/\/err\.sh\/vercel\/next\.js\/empty-configuration/
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -20,8 +20,8 @@ describe('Promise in next config', () => {
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
|
|
||||||
const { stdout } = await nextBuild(appDir, [], { stdout: true })
|
const { stderr } = await nextBuild(appDir, [], { stderr: true })
|
||||||
expect(stdout).not.toMatch(/experimental feature/)
|
expect(stderr).not.toMatch(/experimental feature/)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not show warning with config from object', async () => {
|
it('should not show warning with config from object', async () => {
|
||||||
|
@ -30,8 +30,8 @@ describe('Promise in next config', () => {
|
||||||
target: 'server'
|
target: 'server'
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
const { stdout } = await nextBuild(appDir, [], { stdout: true })
|
const { stderr } = await nextBuild(appDir, [], { stderr: true })
|
||||||
expect(stdout).not.toMatch(/experimental feature/)
|
expect(stderr).not.toMatch(/experimental feature/)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should show warning with config from object with experimental', async () => {
|
it('should show warning with config from object with experimental', async () => {
|
||||||
|
@ -43,8 +43,8 @@ describe('Promise in next config', () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
const { stdout } = await nextBuild(appDir, [], { stdout: true })
|
const { stderr } = await nextBuild(appDir, [], { stderr: true })
|
||||||
expect(stdout).toMatch(/experimental feature/)
|
expect(stderr).toMatch(/experimental feature/)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should show warning with config from function with experimental', async () => {
|
it('should show warning with config from function with experimental', async () => {
|
||||||
|
@ -56,7 +56,7 @@ describe('Promise in next config', () => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
`)
|
`)
|
||||||
const { stdout } = await nextBuild(appDir, [], { stdout: true })
|
const { stderr } = await nextBuild(appDir, [], { stderr: true })
|
||||||
expect(stdout).toMatch(/experimental feature/)
|
expect(stderr).toMatch(/experimental feature/)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -16,8 +16,8 @@ const appDir = path.join(__dirname, '..')
|
||||||
describe('Handles Duplicate Pages', () => {
|
describe('Handles Duplicate Pages', () => {
|
||||||
describe('production', () => {
|
describe('production', () => {
|
||||||
it('Throws an error during build', async () => {
|
it('Throws an error during build', async () => {
|
||||||
const { stdout } = await nextBuild(appDir, [], { stdout: true })
|
const { stderr } = await nextBuild(appDir, [], { stderr: true })
|
||||||
expect(stdout).toContain('Duplicate page detected')
|
expect(stderr).toContain('Duplicate page detected')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -15,12 +15,12 @@ export default function (context) {
|
||||||
|
|
||||||
it('Should throw if a route is matched', async () => {
|
it('Should throw if a route is matched', async () => {
|
||||||
const outdir = join(context.appDir, 'outApi')
|
const outdir = join(context.appDir, 'outApi')
|
||||||
const { stdout } = await runNextCommand(
|
const { stderr } = await runNextCommand(
|
||||||
['export', context.appDir, '--outdir', outdir],
|
['export', context.appDir, '--outdir', outdir],
|
||||||
{ stdout: true }
|
{ stderr: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(stdout).toContain(
|
expect(stderr).toContain(
|
||||||
'https://err.sh/vercel/next.js/api-routes-static-export'
|
'https://err.sh/vercel/next.js/api-routes-static-export'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -15,12 +15,12 @@ export default function (context) {
|
||||||
|
|
||||||
it('Should throw if a route is matched', async () => {
|
it('Should throw if a route is matched', async () => {
|
||||||
const outdir = join(context.appDir, 'outApi')
|
const outdir = join(context.appDir, 'outApi')
|
||||||
const { stdout } = await runNextCommand(
|
const { stderr } = await runNextCommand(
|
||||||
['export', context.appDir, '--outdir', outdir],
|
['export', context.appDir, '--outdir', outdir],
|
||||||
{ stdout: true }
|
{ stderr: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(stdout).toContain(
|
expect(stderr).toContain(
|
||||||
'https://err.sh/vercel/next.js/api-routes-static-export'
|
'https://err.sh/vercel/next.js/api-routes-static-export'
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -11,7 +11,7 @@ const appDir = join(__dirname, '..')
|
||||||
describe('jsconfig.json', () => {
|
describe('jsconfig.json', () => {
|
||||||
it('should build normally', async () => {
|
it('should build normally', async () => {
|
||||||
const res = await await nextBuild(appDir, [], { stdout: true })
|
const res = await await nextBuild(appDir, [], { stdout: true })
|
||||||
expect(res.stdout).toMatch(/Compiled successfully\./)
|
expect(res.stdout).toMatch(/Compiled successfully/)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should fail on invalid jsconfig.json', async () => {
|
it('should fail on invalid jsconfig.json', async () => {
|
||||||
|
|
|
@ -19,25 +19,25 @@ describe('no anonymous default export warning', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('show correct warnings for page', async () => {
|
it('show correct warnings for page', async () => {
|
||||||
let stdout = ''
|
let stderr = ''
|
||||||
|
|
||||||
const appPort = await findPort()
|
const appPort = await findPort()
|
||||||
const app = await launchApp(appDir, appPort, {
|
const app = await launchApp(appDir, appPort, {
|
||||||
env: { __NEXT_TEST_WITH_DEVTOOL: true },
|
env: { __NEXT_TEST_WITH_DEVTOOL: true },
|
||||||
onStdout(msg) {
|
onStderr(msg) {
|
||||||
stdout += msg || ''
|
stderr += msg || ''
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const browser = await webdriver(appPort, '/page')
|
const browser = await webdriver(appPort, '/page')
|
||||||
|
|
||||||
const found = await check(() => stdout, /anonymous/i, false)
|
const found = await check(() => stderr, /anonymous/i, false)
|
||||||
expect(found).toBeTruthy()
|
expect(found).toBeTruthy()
|
||||||
await browser.close()
|
await browser.close()
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
getRegexCount(
|
getRegexCount(
|
||||||
stdout,
|
stderr,
|
||||||
/page.js\r?\n.*not preserve local component state\./g
|
/page.js\r?\n.*not preserve local component state\./g
|
||||||
)
|
)
|
||||||
).toBe(1)
|
).toBe(1)
|
||||||
|
@ -46,25 +46,25 @@ describe('no anonymous default export warning', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('show correct warnings for child', async () => {
|
it('show correct warnings for child', async () => {
|
||||||
let stdout = ''
|
let stderr = ''
|
||||||
|
|
||||||
const appPort = await findPort()
|
const appPort = await findPort()
|
||||||
const app = await launchApp(appDir, appPort, {
|
const app = await launchApp(appDir, appPort, {
|
||||||
env: { __NEXT_TEST_WITH_DEVTOOL: true },
|
env: { __NEXT_TEST_WITH_DEVTOOL: true },
|
||||||
onStdout(msg) {
|
onStderr(msg) {
|
||||||
stdout += msg || ''
|
stderr += msg || ''
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const browser = await webdriver(appPort, '/child')
|
const browser = await webdriver(appPort, '/child')
|
||||||
|
|
||||||
const found = await check(() => stdout, /anonymous/i, false)
|
const found = await check(() => stderr, /anonymous/i, false)
|
||||||
expect(found).toBeTruthy()
|
expect(found).toBeTruthy()
|
||||||
await browser.close()
|
await browser.close()
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
getRegexCount(
|
getRegexCount(
|
||||||
stdout,
|
stderr,
|
||||||
/Child.js\r?\n.*not preserve local component state\./g
|
/Child.js\r?\n.*not preserve local component state\./g
|
||||||
)
|
)
|
||||||
).toBe(1)
|
).toBe(1)
|
||||||
|
@ -73,31 +73,31 @@ describe('no anonymous default export warning', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('show correct warnings for both', async () => {
|
it('show correct warnings for both', async () => {
|
||||||
let stdout = ''
|
let stderr = ''
|
||||||
|
|
||||||
const appPort = await findPort()
|
const appPort = await findPort()
|
||||||
const app = await launchApp(appDir, appPort, {
|
const app = await launchApp(appDir, appPort, {
|
||||||
env: { __NEXT_TEST_WITH_DEVTOOL: true },
|
env: { __NEXT_TEST_WITH_DEVTOOL: true },
|
||||||
onStdout(msg) {
|
onStderr(msg) {
|
||||||
stdout += msg || ''
|
stderr += msg || ''
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const browser = await webdriver(appPort, '/both')
|
const browser = await webdriver(appPort, '/both')
|
||||||
|
|
||||||
const found = await check(() => stdout, /anonymous/i, false)
|
const found = await check(() => stderr, /anonymous/i, false)
|
||||||
expect(found).toBeTruthy()
|
expect(found).toBeTruthy()
|
||||||
await browser.close()
|
await browser.close()
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
getRegexCount(
|
getRegexCount(
|
||||||
stdout,
|
stderr,
|
||||||
/Child.js\r?\n.*not preserve local component state\./g
|
/Child.js\r?\n.*not preserve local component state\./g
|
||||||
)
|
)
|
||||||
).toBe(1)
|
).toBe(1)
|
||||||
expect(
|
expect(
|
||||||
getRegexCount(
|
getRegexCount(
|
||||||
stdout,
|
stderr,
|
||||||
/both.js\r?\n.*not preserve local component state\./g
|
/both.js\r?\n.*not preserve local component state\./g
|
||||||
)
|
)
|
||||||
).toBe(1)
|
).toBe(1)
|
||||||
|
|
|
@ -16,15 +16,11 @@ const appDir = join(__dirname, '../')
|
||||||
|
|
||||||
describe('no duplicate compile error output', () => {
|
describe('no duplicate compile error output', () => {
|
||||||
it('should not show compile error on page refresh', async () => {
|
it('should not show compile error on page refresh', async () => {
|
||||||
let stdout = ''
|
|
||||||
let stderr = ''
|
let stderr = ''
|
||||||
|
|
||||||
const appPort = await findPort()
|
const appPort = await findPort()
|
||||||
const app = await launchApp(appDir, appPort, {
|
const app = await launchApp(appDir, appPort, {
|
||||||
env: { __NEXT_TEST_WITH_DEVTOOL: true },
|
env: { __NEXT_TEST_WITH_DEVTOOL: true },
|
||||||
onStdout(msg) {
|
|
||||||
stdout += msg || ''
|
|
||||||
},
|
|
||||||
onStderr(msg) {
|
onStderr(msg) {
|
||||||
stderr += msg || ''
|
stderr += msg || ''
|
||||||
},
|
},
|
||||||
|
@ -63,12 +59,11 @@ describe('no duplicate compile error output', () => {
|
||||||
const correctMessagesRegex = /error - [^\r\n]+\r?\n[^\r\n]+Unexpected token/g
|
const correctMessagesRegex = /error - [^\r\n]+\r?\n[^\r\n]+Unexpected token/g
|
||||||
const totalMessagesRegex = /Unexpected token/g
|
const totalMessagesRegex = /Unexpected token/g
|
||||||
|
|
||||||
const correctMessages = getRegexCount(stdout, correctMessagesRegex)
|
const correctMessages = getRegexCount(stderr, correctMessagesRegex)
|
||||||
const totalMessages = getRegexCount(stdout, totalMessagesRegex)
|
const totalMessages = getRegexCount(stderr, totalMessagesRegex)
|
||||||
|
|
||||||
expect(correctMessages).toBeGreaterThanOrEqual(1)
|
expect(correctMessages).toBeGreaterThanOrEqual(1)
|
||||||
expect(correctMessages).toBe(totalMessages)
|
expect(correctMessages).toBe(totalMessages)
|
||||||
expect(stderr).toBe('')
|
|
||||||
|
|
||||||
await killApp(app)
|
await killApp(app)
|
||||||
})
|
})
|
||||||
|
|
|
@ -36,7 +36,7 @@ describe('Non-Standard NODE_ENV', () => {
|
||||||
let output = ''
|
let output = ''
|
||||||
|
|
||||||
app = await launchApp(appDir, await findPort(), {
|
app = await launchApp(appDir, await findPort(), {
|
||||||
onStdout(msg) {
|
onStderr(msg) {
|
||||||
output += msg || ''
|
output += msg || ''
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -52,7 +52,7 @@ describe('Non-Standard NODE_ENV', () => {
|
||||||
env: {
|
env: {
|
||||||
NODE_ENV: 'development',
|
NODE_ENV: 'development',
|
||||||
},
|
},
|
||||||
onStdout(msg) {
|
onStderr(msg) {
|
||||||
output += msg || ''
|
output += msg || ''
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -69,7 +69,7 @@ describe('Non-Standard NODE_ENV', () => {
|
||||||
NODE_ENV: 'development',
|
NODE_ENV: 'development',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onStdout(msg) {
|
onStderr(msg) {
|
||||||
output += msg || ''
|
output += msg || ''
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ describe('Non-Standard NODE_ENV', () => {
|
||||||
env: {
|
env: {
|
||||||
NODE_ENV: 'abc',
|
NODE_ENV: 'abc',
|
||||||
},
|
},
|
||||||
onStdout(msg) {
|
onStderr(msg) {
|
||||||
output += msg || ''
|
output += msg || ''
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -103,7 +103,7 @@ describe('Non-Standard NODE_ENV', () => {
|
||||||
NODE_ENV: 'abc',
|
NODE_ENV: 'abc',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onStdout(msg) {
|
onStderr(msg) {
|
||||||
output += msg || ''
|
output += msg || ''
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue