perf(nuxt): defer version/config warnings to after build (#30567)

This commit is contained in:
Daniel Roe 2025-01-14 10:43:42 +00:00
parent b2a1b63f18
commit 77d34f75bc
No known key found for this signature in database
GPG Key ID: CBC814C393D93268
4 changed files with 76 additions and 51 deletions

View File

@ -63,8 +63,11 @@ export async function build (nuxt: Nuxt) {
return return
} }
if (nuxt.options.dev) { if (nuxt.options.dev && !nuxt.options.test) {
checkForExternalConfigurationFiles() nuxt.hooks.hookOnce('build:done', () => {
checkForExternalConfigurationFiles()
.catch(e => logger.warn('Problem checking for external configuration files.', e))
})
} }
await bundle(nuxt) await bundle(nuxt)

View File

@ -79,7 +79,7 @@ const nightlies = {
'@nuxt/kit': '@nuxt/kit-nightly', '@nuxt/kit': '@nuxt/kit-nightly',
} }
const keyDependencies = [ export const keyDependencies = [
'@nuxt/kit', '@nuxt/kit',
'@nuxt/schema', '@nuxt/schema',
] ]
@ -801,8 +801,13 @@ export async function loadNuxt (opts: LoadNuxtOptions): Promise<Nuxt> {
const nuxt = createNuxt(options) const nuxt = createNuxt(options)
for (const dep of keyDependencies) { if (nuxt.options.dev && !nuxt.options.test) {
checkDependencyVersion(dep, nuxt._version) nuxt.hooks.hookOnce('build:done', () => {
for (const dep of keyDependencies) {
checkDependencyVersion(dep, nuxt._version)
.catch(e => logger.warn(`Problem checking \`${dep}\` version.`, e))
}
})
} }
// We register hooks layer-by-layer so any overrides need to be registered separately // We register hooks layer-by-layer so any overrides need to be registered separately
@ -821,7 +826,7 @@ export async function loadNuxt (opts: LoadNuxtOptions): Promise<Nuxt> {
return nuxt return nuxt
} }
async function checkDependencyVersion (name: string, nuxtVersion: string): Promise<void> { export async function checkDependencyVersion (name: string, nuxtVersion: string): Promise<void> {
const path = await resolvePath(name, { fallbackToOriginal: true }).catch(() => null) const path = await resolvePath(name, { fallbackToOriginal: true }).catch(() => null)
if (!path || path === name) { return } if (!path || path === name) { return }

View File

@ -0,0 +1,62 @@
import { afterEach, describe, expect, it, vi } from 'vitest'
import { readPackageJSON } from 'pkg-types'
import { inc } from 'semver'
import { version } from '../package.json'
import { checkDependencyVersion, keyDependencies } from '../src/core/nuxt'
vi.stubGlobal('console', {
...console,
error: vi.fn(console.error),
warn: vi.fn(console.warn),
})
vi.mock('pkg-types', async (og) => {
const originalPkgTypes = (await og<typeof import('pkg-types')>())
return {
...originalPkgTypes,
readPackageJSON: vi.fn(originalPkgTypes.readPackageJSON),
}
})
afterEach(() => {
vi.clearAllMocks()
})
describe('dependency mismatch', () => {
it.sequential('expect mismatched dependency to log a warning', async () => {
vi.mocked(readPackageJSON).mockReturnValue(Promise.resolve({
version: '3.0.0',
}))
for (const dep of keyDependencies) {
await checkDependencyVersion(dep, version)
}
// @nuxt/kit is explicitly installed in repo root but @nuxt/schema isn't, so we only
// get warnings about @nuxt/schema
expect(console.warn).toHaveBeenCalledWith(`[nuxt] Expected \`@nuxt/kit\` to be at least \`${version}\` but got \`3.0.0\`. This might lead to unexpected behavior. Check your package.json or refresh your lockfile.`)
vi.mocked(readPackageJSON).mockRestore()
})
it.sequential.each([
{
name: 'nuxt version is lower',
depVersion: inc(version, 'minor'),
},
{
name: 'version matches',
depVersion: version,
},
])('expect no warning when $name.', async ({ depVersion }) => {
vi.mocked(readPackageJSON).mockReturnValue(Promise.resolve({
depVersion,
}))
for (const dep of keyDependencies) {
await checkDependencyVersion(dep, version)
}
expect(console.warn).not.toHaveBeenCalled()
vi.mocked(readPackageJSON).mockRestore()
})
})

View File

@ -2,10 +2,7 @@ import { fileURLToPath } from 'node:url'
import { afterEach, describe, expect, it, vi } from 'vitest' import { afterEach, describe, expect, it, vi } from 'vitest'
import { normalize } from 'pathe' import { normalize } from 'pathe'
import { withoutTrailingSlash } from 'ufo' import { withoutTrailingSlash } from 'ufo'
import { readPackageJSON } from 'pkg-types'
import { inc } from 'semver'
import { loadNuxt } from '../src' import { loadNuxt } from '../src'
import { version } from '../package.json'
const repoRoot = withoutTrailingSlash(normalize(fileURLToPath(new URL('../../../', import.meta.url)))) const repoRoot = withoutTrailingSlash(normalize(fileURLToPath(new URL('../../../', import.meta.url))))
@ -45,45 +42,3 @@ describe('loadNuxt', () => {
expect(hookRan).toBe(true) expect(hookRan).toBe(true)
}) })
}) })
describe('dependency mismatch', () => {
it('expect mismatched dependency to log a warning', async () => {
vi.mocked(readPackageJSON).mockReturnValue(Promise.resolve({
version: '3.0.0',
}))
const nuxt = await loadNuxt({
cwd: repoRoot,
})
// @nuxt/kit is explicitly installed in repo root but @nuxt/schema isn't, so we only
// get warnings about @nuxt/schema
expect(console.warn).toHaveBeenCalledWith(`[nuxt] Expected \`@nuxt/kit\` to be at least \`${version}\` but got \`3.0.0\`. This might lead to unexpected behavior. Check your package.json or refresh your lockfile.`)
vi.mocked(readPackageJSON).mockRestore()
await nuxt.close()
})
it.each([
{
name: 'nuxt version is lower',
depVersion: inc(version, 'minor'),
},
{
name: 'version matches',
depVersion: version,
},
])('expect no warning when $name.', async ({ depVersion }) => {
vi.mocked(readPackageJSON).mockReturnValue(Promise.resolve({
depVersion,
}))
const nuxt = await loadNuxt({
cwd: repoRoot,
})
expect(console.warn).not.toHaveBeenCalled()
await nuxt.close()
vi.mocked(readPackageJSON).mockRestore()
})
})