mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 15:15:19 +00:00
feat(nuxt): check schema/kit versions when loading nuxt (#27224)
This commit is contained in:
parent
9a33892cec
commit
b4002f37d1
@ -15,6 +15,10 @@ Discover all Nuxt Kit utilities.
|
||||
|
||||
You can install the latest Nuxt Kit by adding it to the `dependencies` section of your `package.json`. However, please consider always explicitly installing the `@nuxt/kit` package even if it is already installed by Nuxt.
|
||||
|
||||
::note
|
||||
`@nuxt/kit` and `@nuxt/schema` are key dependencies for Nuxt. If you are installing it separately, make sure that the versions of `@nuxt/kit` and `@nuxt/schema` are equal to or greater than your `nuxt` version to avoid any unexpected behavior.
|
||||
::
|
||||
|
||||
```json [package.json]
|
||||
{
|
||||
"dependencies": {
|
||||
|
@ -99,6 +99,7 @@
|
||||
"pkg-types": "^1.1.1",
|
||||
"radix3": "^1.1.2",
|
||||
"scule": "^1.3.0",
|
||||
"semver": "^7.6.2",
|
||||
"std-env": "^3.7.0",
|
||||
"strip-literal": "^2.1.0",
|
||||
"ufo": "^1.5.3",
|
||||
|
@ -13,6 +13,7 @@ import fse from 'fs-extra'
|
||||
import { withTrailingSlash, withoutLeadingSlash } from 'ufo'
|
||||
|
||||
import defu from 'defu'
|
||||
import { gte } from 'semver'
|
||||
import pagesModule from '../pages/module'
|
||||
import metaModule from '../head/module'
|
||||
import componentsModule from '../components/module'
|
||||
@ -63,6 +64,11 @@ const nightlies = {
|
||||
'@nuxt/kit': '@nuxt/kit-nightly',
|
||||
}
|
||||
|
||||
const keyDependencies = [
|
||||
'@nuxt/kit',
|
||||
'@nuxt/schema',
|
||||
]
|
||||
|
||||
async function initNuxt (nuxt: Nuxt) {
|
||||
// Register user hooks
|
||||
for (const config of nuxt.options._layers.map(layer => layer.config).reverse()) {
|
||||
@ -616,6 +622,8 @@ export async function loadNuxt (opts: LoadNuxtOptions): Promise<Nuxt> {
|
||||
|
||||
const nuxt = createNuxt(options)
|
||||
|
||||
await Promise.all(keyDependencies.map(dependency => checkDependencyVersion(dependency, nuxt._version)))
|
||||
|
||||
// We register hooks layer-by-layer so any overrides need to be registered separately
|
||||
if (opts.overrides?.hooks) {
|
||||
nuxt.hooks.addHooks(opts.overrides.hooks)
|
||||
@ -632,4 +640,15 @@ export async function loadNuxt (opts: LoadNuxtOptions): Promise<Nuxt> {
|
||||
return nuxt
|
||||
}
|
||||
|
||||
async function checkDependencyVersion (name: string, nuxtVersion: string): Promise<void> {
|
||||
const path = await resolvePath(name).catch(() => null)
|
||||
|
||||
if (!path) { return }
|
||||
const { version } = await readPackageJSON(path)
|
||||
|
||||
if (version && gte(nuxtVersion, version)) {
|
||||
console.warn(`[nuxt] Expected \`${name}\` to be at least \`${nuxtVersion}\` but got \`${version}\`. This might lead to unexpected behavior. Check your package.json or refresh your lockfile.`)
|
||||
}
|
||||
}
|
||||
|
||||
const RESTART_RE = /^(?:app|error|app\.config)\.(?:js|ts|mjs|jsx|tsx|vue)$/i
|
||||
|
@ -1,11 +1,32 @@
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest'
|
||||
import { normalize } from 'pathe'
|
||||
import { withoutTrailingSlash } from 'ufo'
|
||||
import { readPackageJSON } from 'pkg-types'
|
||||
import { inc } from 'semver'
|
||||
import { loadNuxt } from '../src'
|
||||
import { version } from '../package.json'
|
||||
|
||||
const repoRoot = withoutTrailingSlash(normalize(fileURLToPath(new URL('../../../', import.meta.url))))
|
||||
|
||||
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('loadNuxt', () => {
|
||||
it('respects hook overrides', async () => {
|
||||
let hookRan = false
|
||||
@ -24,3 +45,44 @@ describe('loadNuxt', () => {
|
||||
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,
|
||||
})
|
||||
|
||||
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.`)
|
||||
expect(console.warn).toHaveBeenCalledWith(`[nuxt] Expected \`@nuxt/schema\` 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()
|
||||
})
|
||||
})
|
||||
|
@ -369,6 +369,9 @@ importers:
|
||||
scule:
|
||||
specifier: ^1.3.0
|
||||
version: 1.3.0
|
||||
semver:
|
||||
specifier: ^7.6.2
|
||||
version: 7.6.2
|
||||
std-env:
|
||||
specifier: ^3.7.0
|
||||
version: 3.7.0
|
||||
|
Loading…
Reference in New Issue
Block a user