Merge branch 'main' of github.com:nuxt/nuxt into feat/unhead-v2

This commit is contained in:
harlan 2025-01-14 20:08:09 +11:00
commit edc88d2267
25 changed files with 131 additions and 122 deletions

View File

@ -21,7 +21,7 @@ jobs:
- run: corepack enable
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: 22
node-version: lts/*
cache: "pnpm"
- name: Install dependencies

View File

@ -17,14 +17,14 @@ jobs:
- run: corepack enable
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: 22
node-version: lts/*
cache: "pnpm"
- name: Install dependencies
run: pnpm install
- name: Check engine ranges, peer dependency ranges and installed versions
run: pnpm installed-check -d --fix
run: pnpm installed-check --no-include-workspace-root --ignore-dev --workspace-ignore='test/**,playground' --fix
- name: Build (stub)
run: pnpm dev:prepare

View File

@ -33,7 +33,7 @@ jobs:
- run: corepack enable
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: 22
node-version: lts/*
cache: "pnpm"
- name: Install dependencies

View File

@ -28,7 +28,7 @@ jobs:
- run: corepack enable
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: 22
node-version: lts/*
cache: "pnpm"
- name: Install dependencies

View File

@ -41,7 +41,7 @@ jobs:
- run: corepack enable
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: 20
node-version: lts/*
cache: "pnpm"
- name: Install dependencies
@ -56,9 +56,6 @@ jobs:
- name: Build
run: pnpm build
- name: Check types
run: pnpm test:attw
- name: Cache dist
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
with:
@ -118,7 +115,7 @@ jobs:
- run: corepack enable
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: 22
node-version: lts/*
cache: "pnpm"
- name: Install dependencies
@ -149,7 +146,7 @@ jobs:
- run: corepack enable
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: 22
node-version: lts/*
cache: "pnpm"
- name: Install dependencies
@ -161,6 +158,9 @@ jobs:
- name: Lint
run: pnpm lint
- name: Check built types
run: pnpm test:attw
test-unit:
# autofix workflow will be triggered instead for PRs
if: github.event_name == 'push'
@ -173,7 +173,7 @@ jobs:
- run: corepack enable
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: 22
node-version: lts/*
cache: "pnpm"
- name: Install dependencies
@ -260,20 +260,18 @@ jobs:
with:
token: ${{ secrets.CODECOV_TOKEN }}
build-release:
release-nightly:
concurrency:
group: release
permissions:
id-token: write
if: |
github.event_name == 'push' &&
github.repository == 'nuxt/nuxt' &&
github.repository_owner == 'nuxt' &&
!contains(github.event.head_commit.message, '[skip-release]') &&
!startsWith(github.event.head_commit.message, 'docs')
needs:
- lint
- build
- test-fixtures
runs-on: ubuntu-latest
timeout-minutes: 20
@ -284,7 +282,7 @@ jobs:
- run: corepack enable
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: 22
node-version: lts/*
cache: "pnpm"
- name: Install dependencies
@ -299,22 +297,15 @@ jobs:
- name: Release Edge
run: ./scripts/release-edge.sh ${{ github.ref == 'refs/heads/main' && 'latest' || '3x' }}
env:
NODE_AUTH_TOKEN: ${{secrets.NODE_AUTH_TOKEN}}
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
NPM_CONFIG_PROVENANCE: true
release-pr:
concurrency:
group: release
permissions:
id-token: write
pull-requests: write
if: |
github.event_name == 'pull_request' &&
contains(github.event.pull_request.labels.*.name, '🧷 edge release')
if: github.repository_owner == 'nuxt' && github.event_name != 'push'
needs:
- lint
- build
- test-fixtures
runs-on: ubuntu-latest
timeout-minutes: 20
@ -325,7 +316,7 @@ jobs:
- run: corepack enable
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: 22
node-version: lts/*
cache: "pnpm"
- name: Install dependencies
@ -337,8 +328,4 @@ jobs:
name: dist
path: packages
- name: Release Edge
run: ./scripts/release-edge.sh pr-${{ github.event.issue.number }}
env:
NODE_AUTH_TOKEN: ${{secrets.NODE_AUTH_TOKEN}}
NPM_CONFIG_PROVENANCE: true
- run: pnpm pkg-pr-new publish --compact './packages/kit' './packages/nuxt' './packages/rspack' './packages/schema' './packages/vite' './packages/webpack'

View File

@ -25,7 +25,7 @@ jobs:
- run: corepack enable
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: 22
node-version: lts/*
cache: "pnpm"
- name: Install dependencies

View File

@ -1,4 +1,4 @@
name: CI
name: ci
on:
push:
@ -29,7 +29,7 @@ jobs:
- run: corepack enable
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: 22
node-version: lts/*
cache: "pnpm"
- name: Install dependencies
@ -39,4 +39,4 @@ jobs:
run: pnpm sherif -r multiple-dependency-versions
- name: Check engine ranges, peer dependency ranges and installed versions
run: pnpm installed-check -d
run: pnpm installed-check --no-include-workspace-root --ignore-dev --workspace-ignore='test/**,playground'

View File

@ -25,7 +25,7 @@ jobs:
- run: corepack enable
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: 20
node-version: lts/*
registry-url: "https://registry.npmjs.org/"
cache: "pnpm"

View File

@ -17,7 +17,7 @@ jobs:
statuses: write # for amannn/action-semantic-pull-request to mark status of analyzed PR
if: github.repository == 'nuxt/nuxt' && !startsWith(github.head_ref, 'v')
runs-on: ubuntu-latest
name: Semantic pull request
name: semantic-pr
steps:
- name: Validate PR title
uses: amannn/action-semantic-pull-request@0723387faaf9b38adef4775cd42cfd5155ed6017 # v5.5.3

View File

@ -4,7 +4,7 @@ description: The recommended way to provide head data with user input.
links:
- label: Source
icon: i-simple-icons-github
to: https://github.com/unjs/unhead/blob/main/packages/unhead/src/composables/useHeadSafe.ts
to: https://github.com/unjs/unhead/blob/main/packages/vue/src/composables/useHeadSafe.ts
size: xs
---

View File

@ -4,7 +4,7 @@ description: useHead customizes the head properties of individual pages of your
links:
- label: Source
icon: i-simple-icons-github
to: https://github.com/unjs/unhead/blob/main/packages/unhead/src/composables/useHead.ts
to: https://github.com/unjs/unhead/blob/main/packages/vue/src/composables/useHead.ts
size: xs
---

View File

@ -9,11 +9,27 @@ links:
---
::note
`useNuxtData` gives you access to the current cached value of [`useAsyncData`](/docs/api/composables/use-async-data) , `useLazyAsyncData`, [`useFetch`](/docs/api/composables/use-fetch) and [`useLazyFetch`](/docs/api/composables/use-lazy-fetch) with explicitly provided key.
`useNuxtData` gives you access to the current cached value of [`useAsyncData`](/docs/api/composables/use-async-data) , [`useLazyAsyncData`](/docs/api/composables/use-lazy-async-data), [`useFetch`](/docs/api/composables/use-fetch) and [`useLazyFetch`](/docs/api/composables/use-lazy-fetch) with explicitly provided key.
::
## Usage
The `useNuxtData` composable is used to access the current cached value of data-fetching composables such as `useAsyncData`, `useLazyAsyncData`, `useFetch`, and `useLazyFetch`. By providing the key used during the data fetch, you can retrieve the cached data and use it as needed.
This is particularly useful for optimizing performance by reusing already-fetched data or implementing features like Optimistic Updates or cascading data updates.
To use `useNuxtData`, ensure that the data-fetching composable (`useFetch`, `useAsyncData`, etc.) has been called with an explicitly provided key.
## Params
- `key`: The unique key that identifies the cached data. This key should match the one used during the original data fetch.
## Return Values
- `data`: A reactive reference to the cached data associated with the provided key. If no cached data exists, the value will be `null`. This `Ref` automatically updates if the cached data changes, allowing seamless reactivity in your components.
## Example
The example below shows how you can use cached data as a placeholder while the most recent data is being fetched from the server.
```vue [pages/posts.vue]
@ -26,13 +42,15 @@ const { data } = await useFetch('/api/posts', { key: 'posts' })
```vue [pages/posts/[id\\].vue]
<script setup lang="ts">
// Access to the cached value of useFetch in posts.vue (parent route)
const { id } = useRoute().params
const { data: posts } = useNuxtData('posts')
const { data } = useLazyFetch(`/api/posts/${id}`, {
key: `post-${id}`,
const route = useRoute()
const { data } = useLazyFetch(`/api/posts/${route.params.id}`, {
key: `post-${route.params.id}`,
default() {
// Find the individual post from the cache and set it as the default value.
return posts.value.find(post => post.id === id)
return posts.value.find(post => post.id === route.params.id)
}
})
</script>
@ -40,7 +58,9 @@ const { data } = useLazyFetch(`/api/posts/${id}`, {
## Optimistic Updates
We can leverage the cache to update the UI after a mutation, while the data is being invalidated in the background.
The example below shows how implementing Optimistic Updates can be achieved using useNuxtData.
Optimistic Updates is a technique where the user interface is updated immediately, assuming a server operation will succeed. If the operation eventually fails, the UI is rolled back to its previous state.
```vue [pages/todos.vue]
<script setup lang="ts">
@ -52,28 +72,34 @@ const { data } = await useAsyncData('todos', () => $fetch('/api/todos'))
```vue [components/NewTodo.vue]
<script setup lang="ts">
const newTodo = ref('')
const previousTodos = ref([])
let previousTodos = []
// Access to the cached value of useAsyncData in todos.vue
const { data: todos } = useNuxtData('todos')
const { data } = await useFetch('/api/addTodo', {
const addTodo = async () => {
return $fetch('/api/addTodo', {
method: 'post',
body: {
todo: newTodo.value
},
onRequest () {
previousTodos.value = todos.value // Store the previously cached value to restore if fetch fails.
// Store the previously cached value to restore if fetch fails.
previousTodos = todos.value
todos.value.push(newTodo.value) // Optimistically update the todos.
// Optimistically update the todos.
todos.value = [...todos.value, newTodo.value]
},
onRequestError () {
todos.value = previousTodos.value // Rollback the data if the request failed.
onResponseError () {
// Rollback the data if the request failed.
todos.value = previousTodos
},
async onResponse () {
await refreshNuxtData('todos') // Invalidate todos in the background if the request succeeded.
// Invalidate todos in the background if the request succeeded.
await refreshNuxtData('todos')
}
})
})
}
</script>
```

View File

@ -4,7 +4,7 @@ description: The useSeoMeta composable lets you define your site's SEO meta tags
links:
- label: Source
icon: i-simple-icons-github
to: https://github.com/unjs/unhead/blob/main/packages/unhead/src/composables/useSeoMeta.ts
to: https://github.com/unjs/unhead/blob/main/packages/vue/src/composables/useSeoMeta.ts
size: xs
---

View File

@ -4,7 +4,7 @@ description: The useServerSeoMeta composable lets you define your site's SEO met
links:
- label: Source
icon: i-simple-icons-github
to: https://github.com/unjs/unhead/blob/main/packages/unhead/src/composables/useServerSeoMeta.ts
to: https://github.com/unjs/unhead/blob/main/packages/vue/src/composables/useServerSeoMeta.ts
size: xs
---

View File

@ -53,19 +53,19 @@
"nitro": "npm:nitro-nightly@3.0.0-beta-28796231.359af68d",
"nuxt": "workspace:*",
"ohash": "1.1.4",
"postcss": "8.4.49",
"postcss": "8.5.0",
"rollup": "4.30.1",
"send": ">=1.1.0",
"typescript": "5.7.3",
"ufo": "1.5.4",
"unbuild": "3.2.0",
"unbuild": "3.3.1",
"unhead": "2.0.0-alpha.2",
"unimport": "3.14.5",
"vite": "6.0.7",
"vue": "3.5.13"
},
"devDependencies": {
"@arethetypeswrong/cli": "0.17.2",
"@arethetypeswrong/cli": "0.17.3",
"@nuxt/cli": "3.20.0",
"@nuxt/eslint-config": "0.7.5",
"@nuxt/kit": "workspace:*",
@ -73,7 +73,7 @@
"@nuxt/test-utils": "3.15.4",
"@nuxt/webpack-builder": "workspace:*",
"@testing-library/vue": "8.1.0",
"@types/node": "22.10.5",
"@types/node": "22.10.6",
"@types/semver": "7.5.8",
"@unhead/schema": "2.0.0-alpha.2",
"@unhead/vue": "2.0.0-alpha.2",
@ -82,7 +82,7 @@
"autoprefixer": "10.4.20",
"case-police": "0.7.2",
"changelogen": "0.5.7",
"consola": "3.3.3",
"consola": "3.4.0",
"cssnano": "7.0.6",
"destr": "2.0.3",
"devalue": "5.1.1",
@ -102,6 +102,7 @@
"nuxt-content-twoslash": "0.1.2",
"ofetch": "1.4.1",
"pathe": "2.0.1",
"pkg-pr-new": "0.0.39",
"playwright-core": "1.49.1",
"semver": "7.6.3",
"sherif": "1.1.1",
@ -116,9 +117,6 @@
"vue-tsc": "2.2.0",
"webpack": "5.97.1"
},
"packageManager": "pnpm@9.15.3",
"engines": {
"node": "^18.20.4 || ^20.9.0 || ^22.0.0 || >=23.0.0"
},
"packageManager": "pnpm@9.15.4",
"version": ""
}

View File

@ -29,15 +29,15 @@
"dependencies": {
"@nuxt/schema": "workspace:*",
"c12": "^2.0.1",
"consola": "^3.3.3",
"consola": "^3.4.0",
"defu": "^6.1.4",
"destr": "^2.0.3",
"errx": "^0.1.0",
"globby": "^14.0.2",
"ignore": "^7.0.0",
"ignore": "^7.0.1",
"jiti": "^2.4.2",
"klona": "^2.0.6",
"mlly": "^1.7.3",
"mlly": "^1.7.4",
"ohash": "^1.1.4",
"pathe": "^2.0.1",
"pkg-types": "^1.3.0",
@ -52,12 +52,12 @@
"@rspack/core": "1.1.8",
"@types/semver": "7.5.8",
"nitro": "npm:nitro-nightly@3.0.0-beta-28796231.359af68d",
"unbuild": "3.2.0",
"unbuild": "3.3.1",
"vite": "6.0.7",
"vitest": "2.1.8",
"webpack": "5.97.1"
},
"engines": {
"node": ">=18.20.5"
"node": ">=18.0.0"
}
}

View File

@ -95,11 +95,10 @@ export async function loadNuxtModuleInstance (nuxtModule: string | NuxtModule, n
paths.add(nuxtModule)
for (const path of paths) {
for (const parentURL of nuxt.options.modulesDir) {
try {
const src = isAbsolute(path)
? pathToFileURL(await resolvePath(path, { cwd: parentURL, fallbackToOriginal: false, extensions: nuxt.options.extensions })).href
: await resolveModule(path, { url: pathToFileURL(parentURL.replace(/\/node_modules\/?$/, '')), extensions: nuxt.options.extensions })
? pathToFileURL(await resolvePath(path, { fallbackToOriginal: false, extensions: nuxt.options.extensions })).href
: await resolveModule(path, { url: nuxt.options.modulesDir.map(m => pathToFileURL(m.replace(/\/node_modules\/?$/, ''))), extensions: nuxt.options.extensions })
nuxtModule = await jiti.import(src, { default: true }) as NuxtModule
resolvedModulePath = fileURLToPath(new URL(src))
@ -119,8 +118,6 @@ export async function loadNuxtModuleInstance (nuxtModule: string | NuxtModule, n
throw error
}
}
if (typeof nuxtModule !== 'string') { break }
}
}
// Throw error if module could not be found

View File

@ -77,7 +77,7 @@
"c12": "^2.0.1",
"chokidar": "^4.0.3",
"compatx": "^0.1.8",
"consola": "^3.3.3",
"consola": "^3.4.0",
"cookie-es": "^1.2.2",
"defu": "^6.1.4",
"destr": "^2.0.3",
@ -89,13 +89,13 @@
"globby": "^14.0.2",
"h3": "npm:h3-nightly@2.0.0-1718872656.6765a6e",
"hookable": "^5.5.3",
"ignore": "^7.0.0",
"ignore": "^7.0.1",
"impound": "^0.2.0",
"jiti": "^2.4.2",
"klona": "^2.0.6",
"knitwork": "^1.2.0",
"magic-string": "^0.30.17",
"mlly": "^1.7.3",
"mlly": "^1.7.4",
"nanotar": "^0.1.1",
"nitro": "npm:nitro-nightly@3.0.0-beta-28796231.359af68d",
"nypm": "^0.4.1",
@ -131,7 +131,7 @@
"@types/estree": "1.0.6",
"@vitejs/plugin-vue": "5.2.1",
"@vue/compiler-sfc": "3.5.13",
"unbuild": "3.2.0",
"unbuild": "3.3.1",
"vite": "6.0.7",
"vitest": "2.1.8"
},

View File

@ -36,7 +36,7 @@ export const createImportProtectionPatterns = (nuxt: { options: NuxtOptions }, o
])
}
for (const i of [/(^|node_modules\/)@nuxt\/(kit|test-utils)/, /(^|node_modules\/)nuxi/, /(^|node_modules\/)nitro(?:pack)?(?:-nightly)?(?:$|\/)(?!(?:dist\/)?(?:node_modules|presets|runtime|types))/, /(^|node_modules\/)nuxt\/(config|kit|schema)/]) {
for (const i of [/(^|node_modules\/)@nuxt\/(cli|kit|test-utils)/, /(^|node_modules\/)nuxi/, /(^|node_modules\/)nitro(?:pack)?(?:-nightly)?(?:$|\/)(?!(?:dist\/)?(?:node_modules|presets|runtime|types))/, /(^|node_modules\/)nuxt\/(config|kit|schema)/]) {
patterns.push([i, `This module cannot be imported in ${context}.`])
}

View File

@ -51,7 +51,7 @@
"ohash": "^1.1.4",
"pathe": "^2.0.1",
"pify": "^6.1.0",
"postcss": "^8.4.49",
"postcss": "^8.5.0",
"postcss-import": "^16.1.0",
"postcss-import-resolver": "^2.0.0",
"postcss-loader": "^8.1.1",
@ -76,13 +76,13 @@
"@types/webpack-bundle-analyzer": "4.7.0",
"@types/webpack-hot-middleware": "2.25.9",
"rollup": "4.30.1",
"unbuild": "3.2.0",
"unbuild": "3.3.1",
"vue": "3.5.13"
},
"peerDependencies": {
"vue": "^3.3.4"
},
"engines": {
"node": "^18.20.5 || ^20.9.0 || >=22.0.0"
"node": "^18.12.0 || ^20.9.0 || >=22.0.0"
}
}

View File

@ -49,13 +49,13 @@
"file-loader": "6.2.0",
"h3": "npm:h3-nightly@2.0.0-1718872656.6765a6e",
"hookable": "5.5.3",
"ignore": "7.0.0",
"ignore": "7.0.1",
"nitro": "npm:nitro-nightly@3.0.0-beta-28796231.359af68d",
"ofetch": "1.4.1",
"pkg-types": "1.3.0",
"sass-loader": "16.0.4",
"scule": "1.3.0",
"unbuild": "3.2.0",
"unbuild": "3.3.1",
"unctx": "2.4.1",
"unimport": "3.14.5",
"untyped": "1.5.2",
@ -68,7 +68,7 @@
"webpack-dev-middleware": "7.4.2"
},
"dependencies": {
"consola": "^3.3.3",
"consola": "^3.4.0",
"defu": "^6.1.4",
"pathe": "^2.0.1",
"std-env": "^3.8.0"

View File

@ -31,8 +31,5 @@
"tinyglobby": "0.2.10",
"unocss": "65.4.0",
"vite": "6.0.7"
},
"engines": {
"node": "^18.0.0 || ^20.0.0 || >=22.0.0"
}
}

View File

@ -27,7 +27,7 @@
"devDependencies": {
"@nuxt/schema": "workspace:*",
"rollup": "4.30.1",
"unbuild": "3.2.0",
"unbuild": "3.3.1",
"vue": "3.5.13"
},
"dependencies": {
@ -36,7 +36,7 @@
"@vitejs/plugin-vue": "^5.2.1",
"@vitejs/plugin-vue-jsx": "^4.1.1",
"autoprefixer": "^10.4.20",
"consola": "^3.3.3",
"consola": "^3.4.0",
"cssnano": "^7.0.6",
"defu": "^6.1.4",
"esbuild": "^0.24.2",
@ -47,10 +47,10 @@
"jiti": "^2.4.2",
"knitwork": "^1.2.0",
"magic-string": "^0.30.17",
"mlly": "^1.7.3",
"mlly": "^1.7.4",
"pathe": "^2.0.1",
"pkg-types": "^1.3.0",
"postcss": "^8.4.49",
"postcss": "^8.5.0",
"rollup-plugin-visualizer": "^5.13.1",
"std-env": "^3.8.0",
"ufo": "^1.5.4",
@ -65,6 +65,6 @@
"vue": "^3.3.4"
},
"engines": {
"node": "^18.20.5 || ^20.9.0 || >=22.0.0"
"node": "^18.12.0 || ^20.9.0 || >=22.0.0"
}
}

View File

@ -51,7 +51,7 @@
"ohash": "^1.1.4",
"pathe": "^2.0.1",
"pify": "^6.1.0",
"postcss": "^8.4.49",
"postcss": "^8.5.0",
"postcss-import": "^16.1.0",
"postcss-import-resolver": "^2.0.0",
"postcss-loader": "^8.1.1",
@ -78,13 +78,13 @@
"@types/webpack-bundle-analyzer": "4.7.0",
"@types/webpack-hot-middleware": "2.25.9",
"rollup": "4.30.1",
"unbuild": "3.2.0",
"unbuild": "3.3.1",
"vue": "3.5.13"
},
"peerDependencies": {
"vue": "^3.3.4"
},
"engines": {
"node": "^18.20.5 || ^20.9.0 || >=22.0.0"
"node": "^18.12.0 || ^20.9.0 || >=22.0.0"
}
}

View File

@ -9,6 +9,10 @@
"main",
"3.x"
],
"ignoreDeps": [
"node",
"npm"
],
"packageRules": [
{
"groupName": "vitest",