mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-22 13:45:18 +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.
|
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]
|
```json [package.json]
|
||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -99,6 +99,7 @@
|
|||||||
"pkg-types": "^1.1.1",
|
"pkg-types": "^1.1.1",
|
||||||
"radix3": "^1.1.2",
|
"radix3": "^1.1.2",
|
||||||
"scule": "^1.3.0",
|
"scule": "^1.3.0",
|
||||||
|
"semver": "^7.6.2",
|
||||||
"std-env": "^3.7.0",
|
"std-env": "^3.7.0",
|
||||||
"strip-literal": "^2.1.0",
|
"strip-literal": "^2.1.0",
|
||||||
"ufo": "^1.5.3",
|
"ufo": "^1.5.3",
|
||||||
|
@ -13,6 +13,7 @@ import fse from 'fs-extra'
|
|||||||
import { withTrailingSlash, withoutLeadingSlash } from 'ufo'
|
import { withTrailingSlash, withoutLeadingSlash } from 'ufo'
|
||||||
|
|
||||||
import defu from 'defu'
|
import defu from 'defu'
|
||||||
|
import { gte } from 'semver'
|
||||||
import pagesModule from '../pages/module'
|
import pagesModule from '../pages/module'
|
||||||
import metaModule from '../head/module'
|
import metaModule from '../head/module'
|
||||||
import componentsModule from '../components/module'
|
import componentsModule from '../components/module'
|
||||||
@ -63,6 +64,11 @@ const nightlies = {
|
|||||||
'@nuxt/kit': '@nuxt/kit-nightly',
|
'@nuxt/kit': '@nuxt/kit-nightly',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const keyDependencies = [
|
||||||
|
'@nuxt/kit',
|
||||||
|
'@nuxt/schema',
|
||||||
|
]
|
||||||
|
|
||||||
async function initNuxt (nuxt: Nuxt) {
|
async function initNuxt (nuxt: Nuxt) {
|
||||||
// Register user hooks
|
// Register user hooks
|
||||||
for (const config of nuxt.options._layers.map(layer => layer.config).reverse()) {
|
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)
|
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
|
// We register hooks layer-by-layer so any overrides need to be registered separately
|
||||||
if (opts.overrides?.hooks) {
|
if (opts.overrides?.hooks) {
|
||||||
nuxt.hooks.addHooks(opts.overrides.hooks)
|
nuxt.hooks.addHooks(opts.overrides.hooks)
|
||||||
@ -632,4 +640,15 @@ export async function loadNuxt (opts: LoadNuxtOptions): Promise<Nuxt> {
|
|||||||
return 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
|
const RESTART_RE = /^(?:app|error|app\.config)\.(?:js|ts|mjs|jsx|tsx|vue)$/i
|
||||||
|
@ -1,11 +1,32 @@
|
|||||||
import { fileURLToPath } from 'node:url'
|
import { fileURLToPath } from 'node:url'
|
||||||
import { describe, expect, it } 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))))
|
||||||
|
|
||||||
|
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', () => {
|
describe('loadNuxt', () => {
|
||||||
it('respects hook overrides', async () => {
|
it('respects hook overrides', async () => {
|
||||||
let hookRan = false
|
let hookRan = false
|
||||||
@ -24,3 +45,44 @@ 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,
|
||||||
|
})
|
||||||
|
|
||||||
|
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:
|
scule:
|
||||||
specifier: ^1.3.0
|
specifier: ^1.3.0
|
||||||
version: 1.3.0
|
version: 1.3.0
|
||||||
|
semver:
|
||||||
|
specifier: ^7.6.2
|
||||||
|
version: 7.6.2
|
||||||
std-env:
|
std-env:
|
||||||
specifier: ^3.7.0
|
specifier: ^3.7.0
|
||||||
version: 3.7.0
|
version: 3.7.0
|
||||||
|
Loading…
Reference in New Issue
Block a user