mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-11 08:33:53 +00:00
Merge remote-tracking branch 'origin/main' into patch-21
This commit is contained in:
commit
31779d2371
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@ -85,7 +85,7 @@ jobs:
|
|||||||
run: pnpm install
|
run: pnpm install
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@eb055d739abdc2e8de2e5f4ba1a8b246daa779aa # v3.26.0
|
uses: github/codeql-action/init@883d8588e56d1753a8a58c1c86e88976f0c23449 # v3.26.3
|
||||||
with:
|
with:
|
||||||
languages: javascript
|
languages: javascript
|
||||||
queries: +security-and-quality
|
queries: +security-and-quality
|
||||||
@ -97,7 +97,7 @@ jobs:
|
|||||||
path: packages
|
path: packages
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
- name: Perform CodeQL Analysis
|
||||||
uses: github/codeql-action/analyze@eb055d739abdc2e8de2e5f4ba1a8b246daa779aa # v3.26.0
|
uses: github/codeql-action/analyze@883d8588e56d1753a8a58c1c86e88976f0c23449 # v3.26.3
|
||||||
with:
|
with:
|
||||||
category: "/language:javascript"
|
category: "/language:javascript"
|
||||||
|
|
||||||
|
17
.github/workflows/reproduire-sur-stackblitz.yml
vendored
Normal file
17
.github/workflows/reproduire-sur-stackblitz.yml
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
name: reproduire-sur-stackblitz
|
||||||
|
on:
|
||||||
|
issues:
|
||||||
|
types:
|
||||||
|
opened
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
reproduire-sur-stackblitz:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: huang-julien/reproduire-sur-stackblitz@v1.0.0
|
||||||
|
with:
|
||||||
|
reproduction-heading: '### Reproduction'
|
2
.github/workflows/scorecards.yml
vendored
2
.github/workflows/scorecards.yml
vendored
@ -68,7 +68,7 @@ jobs:
|
|||||||
|
|
||||||
# Upload the results to GitHub's code scanning dashboard.
|
# Upload the results to GitHub's code scanning dashboard.
|
||||||
- name: "Upload to code-scanning"
|
- name: "Upload to code-scanning"
|
||||||
uses: github/codeql-action/upload-sarif@eb055d739abdc2e8de2e5f4ba1a8b246daa779aa # v3.26.0
|
uses: github/codeql-action/upload-sarif@883d8588e56d1753a8a58c1c86e88976f0c23449 # v3.26.3
|
||||||
if: github.repository == 'nuxt/nuxt' && success()
|
if: github.repository == 'nuxt/nuxt' && success()
|
||||||
with:
|
with:
|
||||||
sarif_file: results.sarif
|
sarif_file: results.sarif
|
||||||
|
@ -22,13 +22,13 @@ In order to allow you to manage your other testing dependencies, `@nuxt/test-uti
|
|||||||
- you can choose between `vitest`, `cucumber`, `jest` and `playwright` for end-to-end test runners
|
- you can choose between `vitest`, `cucumber`, `jest` and `playwright` for end-to-end test runners
|
||||||
- `playwright-core` is only required if you wish to use the built-in browser testing utilities (and are not using `@playwright/test` as your test runner)
|
- `playwright-core` is only required if you wish to use the built-in browser testing utilities (and are not using `@playwright/test` as your test runner)
|
||||||
|
|
||||||
::code-group
|
::package-managers
|
||||||
```bash [yarn]
|
|
||||||
yarn add --dev @nuxt/test-utils vitest @vue/test-utils happy-dom playwright-core
|
|
||||||
```
|
|
||||||
```bash [npm]
|
```bash [npm]
|
||||||
npm i --save-dev @nuxt/test-utils vitest @vue/test-utils happy-dom playwright-core
|
npm i --save-dev @nuxt/test-utils vitest @vue/test-utils happy-dom playwright-core
|
||||||
```
|
```
|
||||||
|
```bash [yarn]
|
||||||
|
yarn add --dev @nuxt/test-utils vitest @vue/test-utils happy-dom playwright-core
|
||||||
|
```
|
||||||
```bash [pnpm]
|
```bash [pnpm]
|
||||||
pnpm add -D @nuxt/test-utils vitest @vue/test-utils happy-dom playwright-core
|
pnpm add -D @nuxt/test-utils vitest @vue/test-utils happy-dom playwright-core
|
||||||
```
|
```
|
||||||
@ -421,13 +421,13 @@ If you prefer to use `@vue/test-utils` on its own for unit testing in Nuxt, and
|
|||||||
|
|
||||||
1. Install the needed dependencies
|
1. Install the needed dependencies
|
||||||
|
|
||||||
::code-group
|
::package-managers
|
||||||
```bash [yarn]
|
|
||||||
yarn add --dev vitest @vue/test-utils happy-dom @vitejs/plugin-vue
|
|
||||||
```
|
|
||||||
```bash [npm]
|
```bash [npm]
|
||||||
npm i --save-dev vitest @vue/test-utils happy-dom @vitejs/plugin-vue
|
npm i --save-dev vitest @vue/test-utils happy-dom @vitejs/plugin-vue
|
||||||
```
|
```
|
||||||
|
```bash [yarn]
|
||||||
|
yarn add --dev vitest @vue/test-utils happy-dom @vitejs/plugin-vue
|
||||||
|
```
|
||||||
```bash [pnpm]
|
```bash [pnpm]
|
||||||
pnpm add -D vitest @vue/test-utils happy-dom @vitejs/plugin-vue
|
pnpm add -D vitest @vue/test-utils happy-dom @vitejs/plugin-vue
|
||||||
```
|
```
|
||||||
@ -487,13 +487,13 @@ If you prefer to use `@vue/test-utils` on its own for unit testing in Nuxt, and
|
|||||||
|
|
||||||
6. Run vitest command
|
6. Run vitest command
|
||||||
|
|
||||||
::code-group
|
::package-managers
|
||||||
```bash [yarn]
|
|
||||||
yarn test
|
|
||||||
```
|
|
||||||
```bash [npm]
|
```bash [npm]
|
||||||
npm run test
|
npm run test
|
||||||
```
|
```
|
||||||
|
```bash [yarn]
|
||||||
|
yarn test
|
||||||
|
```
|
||||||
```bash [pnpm]
|
```bash [pnpm]
|
||||||
pnpm run test
|
pnpm run test
|
||||||
```
|
```
|
||||||
@ -658,13 +658,13 @@ const page = await createPage('/page')
|
|||||||
|
|
||||||
We also provide first-class support for testing Nuxt within [the Playwright test runner](https://playwright.dev/docs/intro).
|
We also provide first-class support for testing Nuxt within [the Playwright test runner](https://playwright.dev/docs/intro).
|
||||||
|
|
||||||
::code-group
|
::package-managers
|
||||||
```bash [yarn]
|
|
||||||
yarn add --dev @playwright/test @nuxt/test-utils
|
|
||||||
```
|
|
||||||
```bash [npm]
|
```bash [npm]
|
||||||
npm i --save-dev @playwright/test @nuxt/test-utils
|
npm i --save-dev @playwright/test @nuxt/test-utils
|
||||||
```
|
```
|
||||||
|
```bash [yarn]
|
||||||
|
yarn add --dev @playwright/test @nuxt/test-utils
|
||||||
|
```
|
||||||
```bash [pnpm]
|
```bash [pnpm]
|
||||||
pnpm add -D @playwright/test @nuxt/test-utils
|
pnpm add -D @playwright/test @nuxt/test-utils
|
||||||
```
|
```
|
||||||
|
@ -11,7 +11,7 @@ navigation.icon: i-ph-arrow-circle-up-duotone
|
|||||||
|
|
||||||
To upgrade Nuxt to the [latest release](https://github.com/nuxt/nuxt/releases), use the `nuxi upgrade` command.
|
To upgrade Nuxt to the [latest release](https://github.com/nuxt/nuxt/releases), use the `nuxi upgrade` command.
|
||||||
|
|
||||||
::code-group
|
::package-managers
|
||||||
|
|
||||||
```bash [npm]
|
```bash [npm]
|
||||||
npx nuxi upgrade
|
npx nuxi upgrade
|
||||||
|
@ -35,7 +35,7 @@ Or follow the steps below to set up a new Nuxt project on your computer.
|
|||||||
|
|
||||||
Open a terminal (if you're using [Visual Studio Code](https://code.visualstudio.com), you can open an [integrated terminal](https://code.visualstudio.com/docs/editor/integrated-terminal)) and use the following command to create a new starter project:
|
Open a terminal (if you're using [Visual Studio Code](https://code.visualstudio.com), you can open an [integrated terminal](https://code.visualstudio.com/docs/editor/integrated-terminal)) and use the following command to create a new starter project:
|
||||||
|
|
||||||
::code-group
|
::package-managers
|
||||||
|
|
||||||
```bash [npm]
|
```bash [npm]
|
||||||
npx nuxi@latest init <project-name>
|
npx nuxi@latest init <project-name>
|
||||||
@ -75,16 +75,16 @@ cd <project-name>
|
|||||||
|
|
||||||
Now you'll be able to start your Nuxt app in development mode:
|
Now you'll be able to start your Nuxt app in development mode:
|
||||||
|
|
||||||
::code-group
|
::package-managers
|
||||||
|
|
||||||
```bash [yarn]
|
|
||||||
yarn dev --open
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash [npm]
|
```bash [npm]
|
||||||
npm run dev -- -o
|
npm run dev -- -o
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```bash [yarn]
|
||||||
|
yarn dev --open
|
||||||
|
```
|
||||||
|
|
||||||
```bash [pnpm]
|
```bash [pnpm]
|
||||||
pnpm dev -o
|
pnpm dev -o
|
||||||
```
|
```
|
||||||
|
@ -77,7 +77,7 @@ h1 {
|
|||||||
|
|
||||||
You can also reference stylesheets that are distributed through npm. Let's use the popular `animate.css` library as an example.
|
You can also reference stylesheets that are distributed through npm. Let's use the popular `animate.css` library as an example.
|
||||||
|
|
||||||
::code-group
|
::package-managers
|
||||||
|
|
||||||
```bash [npm]
|
```bash [npm]
|
||||||
npm install animate.css
|
npm install animate.css
|
||||||
|
@ -14,7 +14,7 @@ Use the [`nuxi generate` command](/docs/api/commands/generate) to build and pre-
|
|||||||
|
|
||||||
This will build your site, stand up a nuxt instance, and, by default, prerender the root page `/` along with any of your site's pages it links to, any of your site's pages they link to, and so on.
|
This will build your site, stand up a nuxt instance, and, by default, prerender the root page `/` along with any of your site's pages it links to, any of your site's pages they link to, and so on.
|
||||||
|
|
||||||
::code-group
|
::package-managers
|
||||||
|
|
||||||
```bash [npm]
|
```bash [npm]
|
||||||
npx nuxi generate
|
npx nuxi generate
|
||||||
|
@ -203,7 +203,7 @@ You can explore open source examples deployed on some of the platform mentioned
|
|||||||
target: _blank
|
target: _blank
|
||||||
ui.icon.base: text-black dark:text-white
|
ui.icon.base: text-black dark:text-white
|
||||||
---
|
---
|
||||||
An editable website with universal rendering based on CloudFlare KV.
|
An editable website with universal rendering based on Cloudflare KV.
|
||||||
::
|
::
|
||||||
::
|
::
|
||||||
|
|
||||||
|
@ -9,16 +9,16 @@ By default, Nuxt doesn't check types when you run [`nuxi dev`](/docs/api/command
|
|||||||
|
|
||||||
To enable type-checking at build or development time, install `vue-tsc` and `typescript` as development dependency:
|
To enable type-checking at build or development time, install `vue-tsc` and `typescript` as development dependency:
|
||||||
|
|
||||||
::code-group
|
::package-managers
|
||||||
|
|
||||||
```bash [yarn]
|
|
||||||
yarn add --dev vue-tsc typescript
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash [npm]
|
```bash [npm]
|
||||||
npm install --save-dev vue-tsc typescript
|
npm install --save-dev vue-tsc typescript
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```bash [yarn]
|
||||||
|
yarn add --dev vue-tsc typescript
|
||||||
|
```
|
||||||
|
|
||||||
```bash [pnpm]
|
```bash [pnpm]
|
||||||
pnpm add -D vue-tsc typescript
|
pnpm add -D vue-tsc typescript
|
||||||
```
|
```
|
||||||
|
@ -246,13 +246,13 @@ If you want to use Vue plugins, like [vue-gtag](https://github.com/MatteoGabriel
|
|||||||
|
|
||||||
First, install the Vue plugin dependency:
|
First, install the Vue plugin dependency:
|
||||||
|
|
||||||
::code-group
|
::package-managers
|
||||||
```bash [yarn]
|
|
||||||
yarn add --dev vue-gtag-next
|
|
||||||
```
|
|
||||||
```bash [npm]
|
```bash [npm]
|
||||||
npm install --save-dev vue-gtag-next
|
npm install --save-dev vue-gtag-next
|
||||||
```
|
```
|
||||||
|
```bash [yarn]
|
||||||
|
yarn add --dev vue-gtag-next
|
||||||
|
```
|
||||||
```bash [pnpm]
|
```bash [pnpm]
|
||||||
pnpm add -D vue-gtag-next
|
pnpm add -D vue-gtag-next
|
||||||
```
|
```
|
||||||
|
@ -13,7 +13,7 @@ With modules, you can encapsulate, properly test, and share custom solutions as
|
|||||||
|
|
||||||
We recommend you get started with Nuxt Modules using our [starter template](https://github.com/nuxt/starter/tree/module):
|
We recommend you get started with Nuxt Modules using our [starter template](https://github.com/nuxt/starter/tree/module):
|
||||||
|
|
||||||
::code-group
|
::package-managers
|
||||||
|
|
||||||
```bash [npm]
|
```bash [npm]
|
||||||
npx nuxi init -t module my-module
|
npx nuxi init -t module my-module
|
||||||
@ -228,9 +228,9 @@ Learn more about asset injection in [the recipes section](#recipes).
|
|||||||
|
|
||||||
::warning
|
::warning
|
||||||
Published modules cannot leverage auto-imports for assets within their runtime directory. Instead, they have to import them explicitly from `#imports` or alike.
|
Published modules cannot leverage auto-imports for assets within their runtime directory. Instead, they have to import them explicitly from `#imports` or alike.
|
||||||
|
:br :br
|
||||||
Indeed, auto-imports are not enabled for files within `node_modules` (the location where a published module will eventually live) for performance reasons.
|
Indeed, auto-imports are not enabled for files within `node_modules` (the location where a published module will eventually live) for performance reasons.
|
||||||
|
:br :br
|
||||||
If you are using the module starter, auto-imports will not be enabled in your playground either.
|
If you are using the module starter, auto-imports will not be enabled in your playground either.
|
||||||
::
|
::
|
||||||
|
|
||||||
@ -638,7 +638,7 @@ Testing helps ensuring your module works as expected given various setup. Find i
|
|||||||
|
|
||||||
::tip
|
::tip
|
||||||
We're still discussing and exploring how to ease unit and integration testing on Nuxt Modules.
|
We're still discussing and exploring how to ease unit and integration testing on Nuxt Modules.
|
||||||
|
:br :br
|
||||||
[Check out this RFC to join the conversation](https://github.com/nuxt/nuxt/discussions/18399).
|
[Check out this RFC to join the conversation](https://github.com/nuxt/nuxt/discussions/18399).
|
||||||
::
|
::
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ While Nuxt modules offer extensive functionality, sometimes a specific Vite plug
|
|||||||
|
|
||||||
First, we need to install the Vite plugin, for our example, we'll use `@rollup/plugin-yaml`:
|
First, we need to install the Vite plugin, for our example, we'll use `@rollup/plugin-yaml`:
|
||||||
|
|
||||||
::code-group
|
::package-managers
|
||||||
|
|
||||||
```bash [npm]
|
```bash [npm]
|
||||||
npm install @rollup/plugin-yaml
|
npm install @rollup/plugin-yaml
|
||||||
|
@ -124,6 +124,7 @@ When not using `external`, `<NuxtLink>` supports all Vue Router's [`RouterLink`
|
|||||||
- `noRel`: If set to `true`, no `rel` attribute will be added to the link
|
- `noRel`: If set to `true`, no `rel` attribute will be added to the link
|
||||||
- `external`: Forces the link to be rendered as an `a` tag instead of a Vue Router `RouterLink`.
|
- `external`: Forces the link to be rendered as an `a` tag instead of a Vue Router `RouterLink`.
|
||||||
- `prefetch`: When enabled will prefetch middleware, layouts and payloads (when using [payloadExtraction](/docs/api/nuxt-config#crossoriginprefetch)) of links in the viewport. Used by the experimental [crossOriginPrefetch](/docs/api/nuxt-config#crossoriginprefetch) config.
|
- `prefetch`: When enabled will prefetch middleware, layouts and payloads (when using [payloadExtraction](/docs/api/nuxt-config#crossoriginprefetch)) of links in the viewport. Used by the experimental [crossOriginPrefetch](/docs/api/nuxt-config#crossoriginprefetch) config.
|
||||||
|
- `prefetchOn`: Allows custom control of when to prefetch links. Possible options are `interaction` and `visibility` (default). You can also pass an object for full control, for example: `{ interaction: true, visibility: true }`. This prop is only used when `prefetch` is enabled (default) and `noPrefetch` is not set.
|
||||||
- `noPrefetch`: Disables prefetching.
|
- `noPrefetch`: Disables prefetching.
|
||||||
- `prefetchedClass`: A class to apply to links that have been prefetched.
|
- `prefetchedClass`: A class to apply to links that have been prefetched.
|
||||||
|
|
||||||
@ -185,8 +186,13 @@ interface NuxtLinkOptions {
|
|||||||
externalRelAttribute?: string;
|
externalRelAttribute?: string;
|
||||||
activeClass?: string;
|
activeClass?: string;
|
||||||
exactActiveClass?: string;
|
exactActiveClass?: string;
|
||||||
prefetchedClass?: string;
|
|
||||||
trailingSlash?: 'append' | 'remove'
|
trailingSlash?: 'append' | 'remove'
|
||||||
|
prefetch?: boolean
|
||||||
|
prefetchedClass?: string
|
||||||
|
prefetchOn?: Partial<{
|
||||||
|
visibility: boolean
|
||||||
|
interaction: boolean
|
||||||
|
}>
|
||||||
}
|
}
|
||||||
function defineNuxtLink(options: NuxtLinkOptions): Component {}
|
function defineNuxtLink(options: NuxtLinkOptions): Component {}
|
||||||
```
|
```
|
||||||
@ -195,7 +201,9 @@ function defineNuxtLink(options: NuxtLinkOptions): Component {}
|
|||||||
- `externalRelAttribute`: A default `rel` attribute value applied on external links. Defaults to `"noopener noreferrer"`. Set it to `""` to disable
|
- `externalRelAttribute`: A default `rel` attribute value applied on external links. Defaults to `"noopener noreferrer"`. Set it to `""` to disable
|
||||||
- `activeClass`: A default class to apply on active links. Works the same as [Vue Router's `linkActiveClass` option](https://router.vuejs.org/api/interfaces/RouterOptions.html#Properties-linkActiveClass). Defaults to Vue Router's default (`"router-link-active"`)
|
- `activeClass`: A default class to apply on active links. Works the same as [Vue Router's `linkActiveClass` option](https://router.vuejs.org/api/interfaces/RouterOptions.html#Properties-linkActiveClass). Defaults to Vue Router's default (`"router-link-active"`)
|
||||||
- `exactActiveClass`: A default class to apply on exact active links. Works the same as [Vue Router's `linkExactActiveClass` option](https://router.vuejs.org/api/interfaces/RouterOptions.html#Properties-linkExactActiveClass). Defaults to Vue Router's default (`"router-link-exact-active"`)
|
- `exactActiveClass`: A default class to apply on exact active links. Works the same as [Vue Router's `linkExactActiveClass` option](https://router.vuejs.org/api/interfaces/RouterOptions.html#Properties-linkExactActiveClass). Defaults to Vue Router's default (`"router-link-exact-active"`)
|
||||||
- `prefetchedClass`: A default class to apply to links that have been prefetched.
|
|
||||||
- `trailingSlash`: An option to either add or remove trailing slashes in the `href`. If unset or not matching the valid values `append` or `remove`, it will be ignored.
|
- `trailingSlash`: An option to either add or remove trailing slashes in the `href`. If unset or not matching the valid values `append` or `remove`, it will be ignored.
|
||||||
|
- `prefetch`: Whether or not to prefetch links by default.
|
||||||
|
- `prefetchOn`: Granular control of which prefetch strategies to apply by default.
|
||||||
|
- `prefetchedClass`: A default class to apply to links that have been prefetched.
|
||||||
|
|
||||||
:link-example{to="/docs/examples/routing/pages"}
|
:link-example{to="/docs/examples/routing/pages"}
|
||||||
|
@ -72,7 +72,7 @@ const { data: posts } = await useAsyncData(
|
|||||||
- `getCachedData`: Provide a function which returns cached data. A _null_ or _undefined_ return value will trigger a fetch. By default, this is: `key => nuxt.isHydrating ? nuxt.payload.data[key] : nuxt.static.data[key]`, which only caches data when `payloadExtraction` is enabled.
|
- `getCachedData`: Provide a function which returns cached data. A _null_ or _undefined_ return value will trigger a fetch. By default, this is: `key => nuxt.isHydrating ? nuxt.payload.data[key] : nuxt.static.data[key]`, which only caches data when `payloadExtraction` is enabled.
|
||||||
- `pick`: only pick specified keys in this array from the `handler` function result
|
- `pick`: only pick specified keys in this array from the `handler` function result
|
||||||
- `watch`: watch reactive sources to auto-refresh
|
- `watch`: watch reactive sources to auto-refresh
|
||||||
- `deep`: return data in a deep ref object (it is `true` by default). It can be set to `false` to return data in a shallow ref object, which can improve performance if your data does not need to be deeply reactive.
|
- `deep`: return data in a deep ref object. It is `false` by default to return data in a shallow ref object for performance.
|
||||||
- `dedupe`: avoid fetching same key more than once at a time (defaults to `cancel`). Possible options:
|
- `dedupe`: avoid fetching same key more than once at a time (defaults to `cancel`). Possible options:
|
||||||
- `cancel` - cancels existing requests when a new one is made
|
- `cancel` - cancels existing requests when a new one is made
|
||||||
- `defer` - does not make new requests at all if there is a pending request
|
- `defer` - does not make new requests at all if there is a pending request
|
||||||
|
@ -108,7 +108,7 @@ All fetch options can be given a `computed` or `ref` value. These will be watche
|
|||||||
- `getCachedData`: Provide a function which returns cached data. A _null_ or _undefined_ return value will trigger a fetch. By default, this is: `key => nuxt.isHydrating ? nuxt.payload.data[key] : nuxt.static.data[key]`, which only caches data when `payloadExtraction` is enabled.
|
- `getCachedData`: Provide a function which returns cached data. A _null_ or _undefined_ return value will trigger a fetch. By default, this is: `key => nuxt.isHydrating ? nuxt.payload.data[key] : nuxt.static.data[key]`, which only caches data when `payloadExtraction` is enabled.
|
||||||
- `pick`: only pick specified keys in this array from the `handler` function result
|
- `pick`: only pick specified keys in this array from the `handler` function result
|
||||||
- `watch`: watch an array of reactive sources and auto-refresh the fetch result when they change. Fetch options and URL are watched by default. You can completely ignore reactive sources by using `watch: false`. Together with `immediate: false`, this allows for a fully-manual `useFetch`. (You can [see an example here](/docs/getting-started/data-fetching#watch) of using `watch`.)
|
- `watch`: watch an array of reactive sources and auto-refresh the fetch result when they change. Fetch options and URL are watched by default. You can completely ignore reactive sources by using `watch: false`. Together with `immediate: false`, this allows for a fully-manual `useFetch`. (You can [see an example here](/docs/getting-started/data-fetching#watch) of using `watch`.)
|
||||||
- `deep`: return data in a deep ref object (it is `true` by default). It can be set to `false` to return data in a shallow ref object, which can improve performance if your data does not need to be deeply reactive.
|
- `deep`: return data in a deep ref object. It is `false` by default to return data in a shallow ref object for performance.
|
||||||
- `dedupe`: avoid fetching same key more than once at a time (defaults to `cancel`). Possible options:
|
- `dedupe`: avoid fetching same key more than once at a time (defaults to `cancel`). Possible options:
|
||||||
- `cancel` - cancels existing requests when a new one is made
|
- `cancel` - cancels existing requests when a new one is made
|
||||||
- `defer` - does not make new requests at all if there is a pending request
|
- `defer` - does not make new requests at all if there is a pending request
|
||||||
|
@ -4,7 +4,7 @@ description: 'Access runtime config variables with the useRuntimeConfig composab
|
|||||||
links:
|
links:
|
||||||
- label: Source
|
- label: Source
|
||||||
icon: i-simple-icons-github
|
icon: i-simple-icons-github
|
||||||
to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/composables/asyncData.ts
|
to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/nuxt.ts
|
||||||
size: xs
|
size: xs
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -28,16 +28,15 @@ Make sure your dev server (`nuxt dev`) isn't running, remove any package lock fi
|
|||||||
|
|
||||||
Then, reinstall your dependencies:
|
Then, reinstall your dependencies:
|
||||||
|
|
||||||
::code-group
|
::package-managers
|
||||||
|
|
||||||
```bash [yarn]
|
|
||||||
yarn install
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash [npm]
|
```bash [npm]
|
||||||
npm install
|
npm install
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```bash [yarn]
|
||||||
|
yarn install
|
||||||
|
```
|
||||||
::
|
::
|
||||||
|
|
||||||
::note
|
::note
|
||||||
@ -48,16 +47,16 @@ Once the installation is complete, make sure both development and production bui
|
|||||||
|
|
||||||
Install `@nuxt/bridge` and `nuxi` as development dependencies:
|
Install `@nuxt/bridge` and `nuxi` as development dependencies:
|
||||||
|
|
||||||
::code-group
|
::package-managers
|
||||||
|
|
||||||
```bash [Yarn]
|
|
||||||
yarn add --dev @nuxt/bridge nuxi
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash [npm]
|
```bash [npm]
|
||||||
npm install -D @nuxt/bridge nuxi
|
npm install -D @nuxt/bridge nuxi
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```bash [yarn]
|
||||||
|
yarn add --dev @nuxt/bridge nuxi
|
||||||
|
```
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
### Update `nuxt.config`
|
### Update `nuxt.config`
|
||||||
|
@ -27,16 +27,16 @@ You will also need to update your scripts within your `package.json` to reflect
|
|||||||
|
|
||||||
Install `nuxi` as a development dependency:
|
Install `nuxi` as a development dependency:
|
||||||
|
|
||||||
::code-group
|
::package-managers
|
||||||
|
|
||||||
```bash [yarn]
|
|
||||||
yarn add --dev nuxi
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash [npm]
|
```bash [npm]
|
||||||
npm install -D nuxi
|
npm install -D nuxi
|
||||||
```
|
```
|
||||||
|
|
||||||
|
```bash [yarn]
|
||||||
|
yarn add --dev nuxi
|
||||||
|
```
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
### Nuxi
|
### Nuxi
|
||||||
|
28
package.json
28
package.json
@ -39,17 +39,17 @@
|
|||||||
"@nuxt/ui-templates": "workspace:*",
|
"@nuxt/ui-templates": "workspace:*",
|
||||||
"@nuxt/vite-builder": "workspace:*",
|
"@nuxt/vite-builder": "workspace:*",
|
||||||
"@nuxt/webpack-builder": "workspace:*",
|
"@nuxt/webpack-builder": "workspace:*",
|
||||||
"@types/node": "20.14.15",
|
"@types/node": "20.16.1",
|
||||||
"c12": "2.0.0-beta.1",
|
"c12": "2.0.0-beta.1",
|
||||||
"h3": "npm:h3-nightly@2.0.0-1718872656.6765a6e",
|
"h3": "npm:h3-nightly@2.0.0-1718872656.6765a6e",
|
||||||
"jiti": "2.0.0-beta.3",
|
"jiti": "2.0.0-beta.3",
|
||||||
"magic-string": "^0.30.11",
|
"magic-string": "^0.30.11",
|
||||||
"nitro": "npm:nitro-nightly@3.0.0-beta-28665895.e727afda",
|
"nitro": "npm:nitro-nightly@3.0.0-beta-28665895.e727afda",
|
||||||
"nuxt": "workspace:*",
|
"nuxt": "workspace:*",
|
||||||
"rollup": "^4.20.0",
|
"rollup": "^4.21.0",
|
||||||
"typescript": "5.5.4",
|
"typescript": "5.5.4",
|
||||||
"unbuild": "3.0.0-rc.7",
|
"unbuild": "3.0.0-rc.7",
|
||||||
"vite": "5.4.0",
|
"vite": "5.4.1",
|
||||||
"vue": "3.5.0-beta.1",
|
"vue": "3.5.0-beta.1",
|
||||||
"@vue/compiler-core": "3.5.0-beta.1",
|
"@vue/compiler-core": "3.5.0-beta.1",
|
||||||
"@vue/compiler-dom": "3.5.0-beta.1",
|
"@vue/compiler-dom": "3.5.0-beta.1",
|
||||||
@ -59,30 +59,30 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "9.9.0",
|
"@eslint/js": "9.9.0",
|
||||||
"@nuxt/eslint-config": "0.5.0",
|
"@nuxt/eslint-config": "0.5.1",
|
||||||
"@nuxt/kit": "workspace:*",
|
"@nuxt/kit": "workspace:*",
|
||||||
"@nuxt/test-utils": "3.14.1",
|
"@nuxt/test-utils": "3.14.1",
|
||||||
"@nuxt/webpack-builder": "workspace:*",
|
"@nuxt/webpack-builder": "workspace:*",
|
||||||
"@testing-library/vue": "8.1.0",
|
"@testing-library/vue": "8.1.0",
|
||||||
"@types/eslint__js": "8.42.3",
|
"@types/eslint__js": "8.42.3",
|
||||||
"@types/node": "20.14.15",
|
"@types/node": "20.16.1",
|
||||||
"@types/semver": "7.5.8",
|
"@types/semver": "7.5.8",
|
||||||
"@unhead/schema": "1.9.16",
|
"@unhead/schema": "1.9.16",
|
||||||
"@vitejs/plugin-vue": "5.1.2",
|
"@vitejs/plugin-vue": "5.1.2",
|
||||||
"@vitest/coverage-v8": "2.0.5",
|
"@vitest/coverage-v8": "2.0.5",
|
||||||
"@vue/test-utils": "2.4.6",
|
"@vue/test-utils": "2.4.6",
|
||||||
"autoprefixer": "10.4.20",
|
"autoprefixer": "10.4.20",
|
||||||
"case-police": "0.6.1",
|
"case-police": "0.7.0",
|
||||||
"changelogen": "0.5.5",
|
"changelogen": "0.5.5",
|
||||||
"consola": "3.2.3",
|
"consola": "3.2.3",
|
||||||
"cssnano": "7.0.5",
|
"cssnano": "7.0.5",
|
||||||
"destr": "2.0.3",
|
"destr": "2.0.3",
|
||||||
"devalue": "5.0.0",
|
"devalue": "5.0.0",
|
||||||
"eslint": "9.9.0",
|
"eslint": "9.9.0",
|
||||||
"eslint-plugin-no-only-tests": "3.1.0",
|
"eslint-plugin-no-only-tests": "3.3.0",
|
||||||
"eslint-plugin-perfectionist": "3.1.3",
|
"eslint-plugin-perfectionist": "3.2.0",
|
||||||
"eslint-typegen": "0.3.0",
|
"eslint-typegen": "0.3.1",
|
||||||
"execa": "9.3.0",
|
"execa": "9.3.1",
|
||||||
"globby": "14.0.2",
|
"globby": "14.0.2",
|
||||||
"h3": "npm:h3-nightly@2.0.0-1718872656.6765a6e",
|
"h3": "npm:h3-nightly@2.0.0-1718872656.6765a6e",
|
||||||
"happy-dom": "14.12.3",
|
"happy-dom": "14.12.3",
|
||||||
@ -94,19 +94,19 @@
|
|||||||
"nuxt-content-twoslash": "0.1.1",
|
"nuxt-content-twoslash": "0.1.1",
|
||||||
"ofetch": "1.3.4",
|
"ofetch": "1.3.4",
|
||||||
"pathe": "1.1.2",
|
"pathe": "1.1.2",
|
||||||
"playwright-core": "1.46.0",
|
"playwright-core": "1.46.1",
|
||||||
"rimraf": "6.0.1",
|
"rimraf": "6.0.1",
|
||||||
"semver": "7.6.3",
|
"semver": "7.6.3",
|
||||||
"std-env": "3.7.0",
|
"std-env": "3.7.0",
|
||||||
"typescript": "5.5.4",
|
"typescript": "5.5.4",
|
||||||
"ufo": "1.5.4",
|
"ufo": "1.5.4",
|
||||||
"vitest": "2.0.5",
|
"vitest": "2.0.5",
|
||||||
"vitest-environment-nuxt": "1.0.0",
|
"vitest-environment-nuxt": "1.0.1",
|
||||||
"vue": "3.4.37",
|
"vue": "3.4.38",
|
||||||
"vue-router": "4.4.3",
|
"vue-router": "4.4.3",
|
||||||
"vue-tsc": "2.0.29"
|
"vue-tsc": "2.0.29"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@9.7.0",
|
"packageManager": "pnpm@9.7.1",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^16.10.0 || >=18.0.0"
|
"node": "^16.10.0 || >=18.0.0"
|
||||||
},
|
},
|
||||||
|
@ -52,7 +52,7 @@
|
|||||||
"@types/semver": "7.5.8",
|
"@types/semver": "7.5.8",
|
||||||
"nitro": "npm:nitro-nightly@3.0.0-beta-28665895.e727afda",
|
"nitro": "npm:nitro-nightly@3.0.0-beta-28665895.e727afda",
|
||||||
"unbuild": "3.0.0-rc.7",
|
"unbuild": "3.0.0-rc.7",
|
||||||
"vite": "5.4.0",
|
"vite": "5.4.1",
|
||||||
"vitest": "2.0.5",
|
"vitest": "2.0.5",
|
||||||
"webpack": "5.93.0"
|
"webpack": "5.93.0"
|
||||||
},
|
},
|
||||||
|
@ -68,7 +68,7 @@
|
|||||||
"@unhead/dom": "^1.9.16",
|
"@unhead/dom": "^1.9.16",
|
||||||
"@unhead/ssr": "^1.9.16",
|
"@unhead/ssr": "^1.9.16",
|
||||||
"@unhead/vue": "^1.9.16",
|
"@unhead/vue": "^1.9.16",
|
||||||
"@vue/shared": "^3.4.37",
|
"@vue/shared": "^3.4.38",
|
||||||
"acorn": "8.12.1",
|
"acorn": "8.12.1",
|
||||||
"c12": "^2.0.0-beta.1",
|
"c12": "^2.0.0-beta.1",
|
||||||
"chokidar": "^3.6.0",
|
"chokidar": "^3.6.0",
|
||||||
@ -79,7 +79,7 @@
|
|||||||
"destr": "^2.0.3",
|
"destr": "^2.0.3",
|
||||||
"devalue": "^5.0.0",
|
"devalue": "^5.0.0",
|
||||||
"errx": "^0.1.0",
|
"errx": "^0.1.0",
|
||||||
"esbuild": "^0.23.0",
|
"esbuild": "^0.23.1",
|
||||||
"escape-string-regexp": "^5.0.0",
|
"escape-string-regexp": "^5.0.0",
|
||||||
"estree-walker": "^3.0.3",
|
"estree-walker": "^3.0.3",
|
||||||
"globby": "^14.0.2",
|
"globby": "^14.0.2",
|
||||||
@ -110,11 +110,11 @@
|
|||||||
"unctx": "^2.3.1",
|
"unctx": "^2.3.1",
|
||||||
"unenv": "^1.10.0",
|
"unenv": "^1.10.0",
|
||||||
"unimport": "^3.10.0",
|
"unimport": "^3.10.0",
|
||||||
"unplugin": "^1.12.1",
|
"unplugin": "^1.12.2",
|
||||||
"unplugin-vue-router": "^0.10.3",
|
"unplugin-vue-router": "^0.10.7",
|
||||||
"unstorage": "^1.10.2",
|
"unstorage": "^1.10.2",
|
||||||
"untyped": "^1.4.2",
|
"untyped": "^1.4.2",
|
||||||
"vue": "^3.4.37",
|
"vue": "^3.4.38",
|
||||||
"vue-bundle-renderer": "^2.1.0",
|
"vue-bundle-renderer": "^2.1.0",
|
||||||
"vue-devtools-stub": "^0.1.0",
|
"vue-devtools-stub": "^0.1.0",
|
||||||
"vue-router": "^4.4.3"
|
"vue-router": "^4.4.3"
|
||||||
@ -125,9 +125,9 @@
|
|||||||
"@parcel/watcher": "2.4.1",
|
"@parcel/watcher": "2.4.1",
|
||||||
"@types/estree": "1.0.5",
|
"@types/estree": "1.0.5",
|
||||||
"@vitejs/plugin-vue": "5.1.2",
|
"@vitejs/plugin-vue": "5.1.2",
|
||||||
"@vue/compiler-sfc": "3.4.37",
|
"@vue/compiler-sfc": "3.4.38",
|
||||||
"unbuild": "3.0.0-rc.7",
|
"unbuild": "3.0.0-rc.7",
|
||||||
"vite": "5.4.0",
|
"vite": "5.4.1",
|
||||||
"vitest": "2.0.5"
|
"vitest": "2.0.5"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
|
@ -3,6 +3,7 @@ import type { ComponentInternalInstance, ComponentOptions, InjectionKey } from '
|
|||||||
import { isPromise } from '@vue/shared'
|
import { isPromise } from '@vue/shared'
|
||||||
import { useNuxtApp } from '../nuxt'
|
import { useNuxtApp } from '../nuxt'
|
||||||
import { getFragmentHTML } from './utils'
|
import { getFragmentHTML } from './utils'
|
||||||
|
import ServerPlaceholder from './server-placeholder'
|
||||||
|
|
||||||
export const clientOnlySymbol: InjectionKey<boolean> = Symbol.for('nuxt:client-only')
|
export const clientOnlySymbol: InjectionKey<boolean> = Symbol.for('nuxt:client-only')
|
||||||
|
|
||||||
@ -36,6 +37,9 @@ const cache = new WeakMap()
|
|||||||
|
|
||||||
/* @__NO_SIDE_EFFECTS__ */
|
/* @__NO_SIDE_EFFECTS__ */
|
||||||
export function createClientOnly<T extends ComponentOptions> (component: T) {
|
export function createClientOnly<T extends ComponentOptions> (component: T) {
|
||||||
|
if (import.meta.server) {
|
||||||
|
return ServerPlaceholder
|
||||||
|
}
|
||||||
if (cache.has(component)) {
|
if (cache.has(component)) {
|
||||||
return cache.get(component)
|
return cache.get(component)
|
||||||
}
|
}
|
||||||
@ -45,15 +49,14 @@ export function createClientOnly<T extends ComponentOptions> (component: T) {
|
|||||||
if (clone.render) {
|
if (clone.render) {
|
||||||
// override the component render (non script setup component) or dev mode
|
// override the component render (non script setup component) or dev mode
|
||||||
clone.render = (ctx: any, cache: any, $props: any, $setup: any, $data: any, $options: any) => {
|
clone.render = (ctx: any, cache: any, $props: any, $setup: any, $data: any, $options: any) => {
|
||||||
// import.meta.client for server-side treeshakking
|
if ($setup.mounted$ ?? ctx.mounted$) {
|
||||||
if (import.meta.client && ($setup.mounted$ ?? ctx.mounted$)) {
|
|
||||||
const res = component.render?.bind(ctx)(ctx, cache, $props, $setup, $data, $options)
|
const res = component.render?.bind(ctx)(ctx, cache, $props, $setup, $data, $options)
|
||||||
return (res.children === null || typeof res.children === 'string')
|
return (res.children === null || typeof res.children === 'string')
|
||||||
? cloneVNode(res)
|
? cloneVNode(res)
|
||||||
: h(res)
|
: h(res)
|
||||||
} else {
|
} else {
|
||||||
const fragment = getFragmentHTML(ctx._.vnode.el ?? null) ?? ['<div></div>']
|
const fragment = getFragmentHTML(ctx._.vnode.el ?? null) ?? ['<div></div>']
|
||||||
return import.meta.client ? createStaticVNode(fragment.join(''), fragment.length) : h('div', ctx.$attrs ?? ctx._.attrs)
|
return createStaticVNode(fragment.join(''), fragment.length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (clone.template) {
|
} else if (clone.template) {
|
||||||
@ -66,10 +69,10 @@ export function createClientOnly<T extends ComponentOptions> (component: T) {
|
|||||||
|
|
||||||
clone.setup = (props, ctx) => {
|
clone.setup = (props, ctx) => {
|
||||||
const nuxtApp = useNuxtApp()
|
const nuxtApp = useNuxtApp()
|
||||||
const mounted$ = ref(import.meta.client && nuxtApp.isHydrating === false)
|
const mounted$ = ref(nuxtApp.isHydrating === false)
|
||||||
const instance = getCurrentInstance()!
|
const instance = getCurrentInstance()!
|
||||||
|
|
||||||
if (import.meta.server || nuxtApp.isHydrating) {
|
if (nuxtApp.isHydrating) {
|
||||||
const attrs = { ...instance.attrs }
|
const attrs = { ...instance.attrs }
|
||||||
// remove existing directives during hydration
|
// remove existing directives during hydration
|
||||||
const directives = extractDirectives(instance)
|
const directives = extractDirectives(instance)
|
||||||
@ -97,14 +100,14 @@ export function createClientOnly<T extends ComponentOptions> (component: T) {
|
|||||||
return setupState
|
return setupState
|
||||||
}
|
}
|
||||||
return (...args: any[]) => {
|
return (...args: any[]) => {
|
||||||
if (import.meta.client && (mounted$.value || !nuxtApp.isHydrating)) {
|
if (mounted$.value || !nuxtApp.isHydrating) {
|
||||||
const res = setupState(...args)
|
const res = setupState(...args)
|
||||||
return (res.children === null || typeof res.children === 'string')
|
return (res.children === null || typeof res.children === 'string')
|
||||||
? cloneVNode(res)
|
? cloneVNode(res)
|
||||||
: h(res)
|
: h(res)
|
||||||
} else {
|
} else {
|
||||||
const fragment = getFragmentHTML(instance?.vnode.el ?? null) ?? ['<div></div>']
|
const fragment = getFragmentHTML(instance?.vnode.el ?? null) ?? ['<div></div>']
|
||||||
return import.meta.client ? createStaticVNode(fragment.join(''), fragment.length) : h('div', ctx.attrs)
|
return createStaticVNode(fragment.join(''), fragment.length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -115,9 +118,7 @@ export function createClientOnly<T extends ComponentOptions> (component: T) {
|
|||||||
return h(setupState(...args), ctx.attrs)
|
return h(setupState(...args), ctx.attrs)
|
||||||
}
|
}
|
||||||
const fragment = getFragmentHTML(instance?.vnode.el ?? null) ?? ['<div></div>']
|
const fragment = getFragmentHTML(instance?.vnode.el ?? null) ?? ['<div></div>']
|
||||||
return import.meta.client
|
return createStaticVNode(fragment.join(''), fragment.length)
|
||||||
? createStaticVNode(fragment.join(''), fragment.length) :
|
|
||||||
h('div', ctx.attrs)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Object.assign(setupState, { mounted$ })
|
return Object.assign(setupState, { mounted$ })
|
||||||
|
@ -59,6 +59,13 @@ export interface NuxtLinkProps extends Omit<RouterLinkProps, 'to'> {
|
|||||||
* When enabled will prefetch middleware, layouts and payloads of links in the viewport.
|
* When enabled will prefetch middleware, layouts and payloads of links in the viewport.
|
||||||
*/
|
*/
|
||||||
prefetch?: boolean
|
prefetch?: boolean
|
||||||
|
/**
|
||||||
|
* Allows controlling when to prefetch links. By default, prefetch is triggered only on visibility.
|
||||||
|
*/
|
||||||
|
prefetchOn?: 'visibility' | 'interaction' | Partial<{
|
||||||
|
visibility: boolean
|
||||||
|
interaction: boolean
|
||||||
|
}>
|
||||||
/**
|
/**
|
||||||
* Escape hatch to disable `prefetch` attribute.
|
* Escape hatch to disable `prefetch` attribute.
|
||||||
*/
|
*/
|
||||||
@ -71,7 +78,7 @@ export interface NuxtLinkProps extends Omit<RouterLinkProps, 'to'> {
|
|||||||
*/
|
*/
|
||||||
export interface NuxtLinkOptions extends
|
export interface NuxtLinkOptions extends
|
||||||
Partial<Pick<RouterLinkProps, 'activeClass' | 'exactActiveClass'>>,
|
Partial<Pick<RouterLinkProps, 'activeClass' | 'exactActiveClass'>>,
|
||||||
Partial<Pick<NuxtLinkProps, 'prefetchedClass'>> {
|
Partial<Pick<NuxtLinkProps, 'prefetch' | 'prefetchedClass'>> {
|
||||||
/**
|
/**
|
||||||
* The name of the component.
|
* The name of the component.
|
||||||
* @default "NuxtLink"
|
* @default "NuxtLink"
|
||||||
@ -86,6 +93,11 @@ export interface NuxtLinkOptions extends
|
|||||||
* If unset or not matching the valid values `append` or `remove`, it will be ignored.
|
* If unset or not matching the valid values `append` or `remove`, it will be ignored.
|
||||||
*/
|
*/
|
||||||
trailingSlash?: 'append' | 'remove'
|
trailingSlash?: 'append' | 'remove'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows controlling default setting for when to prefetch links. By default, prefetch is triggered only on visibility.
|
||||||
|
*/
|
||||||
|
prefetchOn?: Exclude<NuxtLinkProps['prefetchOn'], string>
|
||||||
}
|
}
|
||||||
|
|
||||||
/* @__NO_SIDE_EFFECTS__ */
|
/* @__NO_SIDE_EFFECTS__ */
|
||||||
@ -239,6 +251,14 @@ export function defineNuxtLink (options: NuxtLinkOptions) {
|
|||||||
default: undefined,
|
default: undefined,
|
||||||
required: false,
|
required: false,
|
||||||
},
|
},
|
||||||
|
prefetchOn: {
|
||||||
|
type: [String, Object] as PropType<NuxtLinkProps['prefetchOn']>,
|
||||||
|
default: options.prefetchOn || {
|
||||||
|
visibility: true,
|
||||||
|
interaction: false,
|
||||||
|
} satisfies NuxtLinkProps['prefetchOn'],
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
noPrefetch: {
|
noPrefetch: {
|
||||||
type: Boolean as PropType<NuxtLinkProps['noPrefetch']>,
|
type: Boolean as PropType<NuxtLinkProps['noPrefetch']>,
|
||||||
default: undefined,
|
default: undefined,
|
||||||
@ -299,10 +319,27 @@ export function defineNuxtLink (options: NuxtLinkOptions) {
|
|||||||
const el = import.meta.server ? undefined : ref<HTMLElement | null>(null)
|
const el = import.meta.server ? undefined : ref<HTMLElement | null>(null)
|
||||||
const elRef = import.meta.server ? undefined : (ref: any) => { el!.value = props.custom ? ref?.$el?.nextElementSibling : ref?.$el }
|
const elRef = import.meta.server ? undefined : (ref: any) => { el!.value = props.custom ? ref?.$el?.nextElementSibling : ref?.$el }
|
||||||
|
|
||||||
|
function shouldPrefetch (mode: 'visibility' | 'interaction') {
|
||||||
|
return !prefetched.value && (typeof props.prefetchOn === 'string' ? props.prefetchOn === mode : (props.prefetchOn?.[mode] ?? options.prefetchOn?.[mode])) && (props.prefetch ?? options.prefetch) !== false && props.noPrefetch !== true && props.target !== '_blank' && !isSlowConnection()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function prefetch (nuxtApp = useNuxtApp()) {
|
||||||
|
if (prefetched.value) { return }
|
||||||
|
|
||||||
|
prefetched.value = true
|
||||||
|
|
||||||
|
const path = typeof to.value === 'string'
|
||||||
|
? to.value
|
||||||
|
: isExternal.value ? resolveRouteObject(to.value) : router.resolve(to.value).fullPath
|
||||||
|
await Promise.all([
|
||||||
|
nuxtApp.hooks.callHook('link:prefetch', path).catch(() => {}),
|
||||||
|
!isExternal.value && !hasTarget.value && preloadRouteComponents(to.value as string, router).catch(() => {}),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
if (import.meta.client) {
|
if (import.meta.client) {
|
||||||
checkPropConflicts(props, 'prefetch', 'noPrefetch')
|
checkPropConflicts(props, 'prefetch', 'noPrefetch')
|
||||||
const shouldPrefetch = props.prefetch !== false && props.noPrefetch !== true && props.target !== '_blank' && !isSlowConnection()
|
if (shouldPrefetch('visibility')) {
|
||||||
if (shouldPrefetch) {
|
|
||||||
const nuxtApp = useNuxtApp()
|
const nuxtApp = useNuxtApp()
|
||||||
let idleId: number
|
let idleId: number
|
||||||
let unobserve: (() => void) | null = null
|
let unobserve: (() => void) | null = null
|
||||||
@ -314,15 +351,7 @@ export function defineNuxtLink (options: NuxtLinkOptions) {
|
|||||||
unobserve = observer!.observe(el.value as HTMLElement, async () => {
|
unobserve = observer!.observe(el.value as HTMLElement, async () => {
|
||||||
unobserve?.()
|
unobserve?.()
|
||||||
unobserve = null
|
unobserve = null
|
||||||
|
await prefetch(nuxtApp)
|
||||||
const path = typeof to.value === 'string'
|
|
||||||
? to.value
|
|
||||||
: isExternal.value ? resolveRouteObject(to.value) : router.resolve(to.value).fullPath
|
|
||||||
await Promise.all([
|
|
||||||
nuxtApp.hooks.callHook('link:prefetch', path).catch(() => {}),
|
|
||||||
!isExternal.value && !hasTarget.value && preloadRouteComponents(to.value as string, router).catch(() => {}),
|
|
||||||
])
|
|
||||||
prefetched.value = true
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -355,6 +384,8 @@ export function defineNuxtLink (options: NuxtLinkOptions) {
|
|||||||
replace: props.replace,
|
replace: props.replace,
|
||||||
ariaCurrentValue: props.ariaCurrentValue,
|
ariaCurrentValue: props.ariaCurrentValue,
|
||||||
custom: props.custom,
|
custom: props.custom,
|
||||||
|
onPointerenter: shouldPrefetch('interaction') ? prefetch.bind(null, undefined) : undefined,
|
||||||
|
onFocus: shouldPrefetch('interaction') ? prefetch.bind(null, undefined) : undefined,
|
||||||
}
|
}
|
||||||
|
|
||||||
// `custom` API cannot support fallthrough attributes as the slot
|
// `custom` API cannot support fallthrough attributes as the slot
|
||||||
|
@ -84,7 +84,7 @@ export interface AsyncDataOptions<
|
|||||||
*/
|
*/
|
||||||
immediate?: boolean
|
immediate?: boolean
|
||||||
/**
|
/**
|
||||||
* Return data in a deep ref object (it is true by default). It can be set to false to return data in a shallow ref object, which can improve performance if your data does not need to be deeply reactive.
|
* Return data in a deep ref object (it is false by default). It can be set to false to return data in a shallow ref object, which can improve performance if your data does not need to be deeply reactive.
|
||||||
*/
|
*/
|
||||||
deep?: boolean
|
deep?: boolean
|
||||||
/**
|
/**
|
||||||
@ -350,7 +350,7 @@ export function useAsyncData<
|
|||||||
if (import.meta.client) {
|
if (import.meta.client) {
|
||||||
// Setup hook callbacks once per instance
|
// Setup hook callbacks once per instance
|
||||||
const instance = getCurrentInstance()
|
const instance = getCurrentInstance()
|
||||||
if (import.meta.dev && !nuxtApp.isHydrating && (!instance || instance?.isMounted)) {
|
if (import.meta.dev && !nuxtApp.isHydrating && !nuxtApp._processingMiddleware /* internal flag */ && (!instance || instance?.isMounted)) {
|
||||||
// @ts-expect-error private property
|
// @ts-expect-error private property
|
||||||
console.warn(`[nuxt] [${options._functionName || 'useAsyncData'}] Component is already mounted, please use $fetch instead. See https://nuxt.com/docs/getting-started/data-fetching`)
|
console.warn(`[nuxt] [${options._functionName || 'useAsyncData'}] Component is already mounted, please use $fetch instead. See https://nuxt.com/docs/getting-started/data-fetching`)
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import { useRoute } from './router'
|
|||||||
import { getAppManifest, getRouteRules } from './manifest'
|
import { getAppManifest, getRouteRules } from './manifest'
|
||||||
|
|
||||||
// @ts-expect-error virtual import
|
// @ts-expect-error virtual import
|
||||||
import { appManifest, payloadExtraction, renderJsonPayloads } from '#build/nuxt.config.mjs'
|
import { appId, appManifest, multiApp, payloadExtraction, renderJsonPayloads } from '#build/nuxt.config.mjs'
|
||||||
|
|
||||||
interface LoadPayloadOptions {
|
interface LoadPayloadOptions {
|
||||||
fresh?: boolean
|
fresh?: boolean
|
||||||
@ -107,7 +107,7 @@ export async function getNuxtClientPayload () {
|
|||||||
return payloadCache
|
return payloadCache
|
||||||
}
|
}
|
||||||
|
|
||||||
const el = document.getElementById('__NUXT_DATA__')
|
const el = multiApp ? document.querySelector(`[data-nuxt-data="${appId}"]`) as HTMLElement : document.getElementById('__NUXT_DATA__')
|
||||||
if (!el) {
|
if (!el) {
|
||||||
return {} as Partial<NuxtPayload>
|
return {} as Partial<NuxtPayload>
|
||||||
}
|
}
|
||||||
@ -119,7 +119,7 @@ export async function getNuxtClientPayload () {
|
|||||||
payloadCache = {
|
payloadCache = {
|
||||||
...inlineData,
|
...inlineData,
|
||||||
...externalData,
|
...externalData,
|
||||||
...window.__NUXT__,
|
...(multiApp ? window.__NUXT__?.[appId] : window.__NUXT__),
|
||||||
}
|
}
|
||||||
|
|
||||||
if (payloadCache!.config?.public) {
|
if (payloadCache!.config?.public) {
|
||||||
|
@ -15,7 +15,7 @@ import plugins from '#build/plugins'
|
|||||||
// @ts-expect-error virtual file
|
// @ts-expect-error virtual file
|
||||||
import RootComponent from '#build/root-component.mjs'
|
import RootComponent from '#build/root-component.mjs'
|
||||||
// @ts-expect-error virtual file
|
// @ts-expect-error virtual file
|
||||||
import { vueAppRootContainer } from '#build/nuxt.config.mjs'
|
import { appId, multiApp, vueAppRootContainer } from '#build/nuxt.config.mjs'
|
||||||
|
|
||||||
let entry: (ssrContext?: CreateOptions['ssrContext']) => Promise<App<Element>>
|
let entry: (ssrContext?: CreateOptions['ssrContext']) => Promise<App<Element>>
|
||||||
|
|
||||||
@ -50,9 +50,10 @@ if (import.meta.client) {
|
|||||||
|
|
||||||
entry = async function initApp () {
|
entry = async function initApp () {
|
||||||
if (vueAppPromise) { return vueAppPromise }
|
if (vueAppPromise) { return vueAppPromise }
|
||||||
|
|
||||||
const isSSR = Boolean(
|
const isSSR = Boolean(
|
||||||
window.__NUXT__?.serverRendered ||
|
(multiApp ? window.__NUXT__?.[appId] : window.__NUXT__)?.serverRendered ??
|
||||||
document.getElementById('__NUXT_DATA__')?.dataset.ssr === 'true',
|
(multiApp ? document.querySelector(`[data-nuxt-data="${appId}"]`) as HTMLElement : document.getElementById('__NUXT_DATA__'))?.dataset.ssr === 'true',
|
||||||
)
|
)
|
||||||
const vueApp = isSSR ? createSSRApp(RootComponent) : createApp(RootComponent)
|
const vueApp = isSSR ? createSSRApp(RootComponent) : createApp(RootComponent)
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ import type { RouteAnnouncer } from '../app/composables/route-announcer'
|
|||||||
import type { ViewTransition } from './plugins/view-transitions.client'
|
import type { ViewTransition } from './plugins/view-transitions.client'
|
||||||
|
|
||||||
// @ts-expect-error virtual file
|
// @ts-expect-error virtual file
|
||||||
import { appId } from '#build/nuxt.config.mjs'
|
import { appId, multiApp } from '#build/nuxt.config.mjs'
|
||||||
|
|
||||||
import type { NuxtAppLiterals } from '#app'
|
import type { NuxtAppLiterals } from '#app'
|
||||||
|
|
||||||
@ -310,19 +310,22 @@ export function createNuxtApp (options: CreateOptions) {
|
|||||||
nuxtApp.payload.serverRendered = true
|
nuxtApp.payload.serverRendered = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (import.meta.client) {
|
||||||
|
const __NUXT__ = multiApp ? window.__NUXT__?.[nuxtApp._id] : window.__NUXT__
|
||||||
// TODO: remove/refactor in https://github.com/nuxt/nuxt/issues/25336
|
// TODO: remove/refactor in https://github.com/nuxt/nuxt/issues/25336
|
||||||
if (import.meta.client && window.__NUXT__) {
|
if (__NUXT__) {
|
||||||
for (const key in window.__NUXT__) {
|
for (const key in __NUXT__) {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'data':
|
case 'data':
|
||||||
case 'state':
|
case 'state':
|
||||||
case '_errors':
|
case '_errors':
|
||||||
// Preserve reactivity for non-rich payload support
|
// Preserve reactivity for non-rich payload support
|
||||||
Object.assign(nuxtApp.payload[key], window.__NUXT__[key])
|
Object.assign(nuxtApp.payload[key], __NUXT__[key])
|
||||||
break
|
break
|
||||||
|
|
||||||
default:
|
default:
|
||||||
nuxtApp.payload[key] = window.__NUXT__[key]
|
nuxtApp.payload[key] = __NUXT__[key]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,8 @@ export default defineNuxtPlugin(async (nuxtApp) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window !== 'undefined') {
|
||||||
const content = document.getElementById('__NUXT_LOGS__')?.textContent
|
const nuxtLogsElement = document.querySelector(`[data-nuxt-logs="${nuxtApp._name}"]`)
|
||||||
|
const content = nuxtLogsElement?.textContent
|
||||||
const logs = content ? parse(content, { ...devRevivers, ...nuxtApp._payloadRevivers }) as LogObject[] : []
|
const logs = content ? parse(content, { ...devRevivers, ...nuxtApp._payloadRevivers }) as LogObject[] : []
|
||||||
await nuxtApp.hooks.callHook('dev:ssr-logs', logs)
|
await nuxtApp.hooks.callHook('dev:ssr-logs', logs)
|
||||||
}
|
}
|
||||||
|
22
packages/nuxt/src/app/types/augments.d.ts
vendored
22
packages/nuxt/src/app/types/augments.d.ts
vendored
@ -26,7 +26,7 @@ declare global {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface Window {
|
interface Window {
|
||||||
__NUXT__?: Record<string, any>
|
__NUXT__?: Record<string, any> | Record<string, Record<string, any>>
|
||||||
useNuxtApp?: typeof useNuxtApp
|
useNuxtApp?: typeof useNuxtApp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,23 +51,3 @@ declare module 'vue' {
|
|||||||
head?(nuxtApp: NuxtApp): UseHeadInput
|
head?(nuxtApp: NuxtApp): UseHeadInput
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module '@vue/runtime-core' {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
interface App<HostElement> {
|
|
||||||
$nuxt: NuxtApp
|
|
||||||
}
|
|
||||||
interface ComponentCustomProperties {
|
|
||||||
$nuxt: NuxtApp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@vue/runtime-dom' {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
interface App<HostElement> {
|
|
||||||
$nuxt: NuxtApp
|
|
||||||
}
|
|
||||||
interface ComponentCustomProperties {
|
|
||||||
$nuxt: NuxtApp
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -128,14 +128,6 @@ interface _GlobalComponents {
|
|||||||
${componentTypes.map(([pascalName, type]) => ` 'LazyEvent${pascalName}': ${type} & DefineComponent<{hydrate?: Array<keyof HTMLElementEventMap>}>`).join('\n')}
|
${componentTypes.map(([pascalName, type]) => ` 'LazyEvent${pascalName}': ${type} & DefineComponent<{hydrate?: Array<keyof HTMLElementEventMap>}>`).join('\n')}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module '@vue/runtime-core' {
|
|
||||||
export interface GlobalComponents extends _GlobalComponents { }
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@vue/runtime-dom' {
|
|
||||||
export interface GlobalComponents extends _GlobalComponents { }
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'vue' {
|
declare module 'vue' {
|
||||||
export interface GlobalComponents extends _GlobalComponents { }
|
export interface GlobalComponents extends _GlobalComponents { }
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,8 @@ import type { NitroApp } from 'nitro/types'
|
|||||||
|
|
||||||
// @ts-expect-error virtual file
|
// @ts-expect-error virtual file
|
||||||
import { rootDir } from '#internal/dev-server-logs-options'
|
import { rootDir } from '#internal/dev-server-logs-options'
|
||||||
|
// @ts-expect-error virtual file
|
||||||
|
import { appId } from '#internal/nuxt.config.mjs'
|
||||||
|
|
||||||
const devReducers: Record<string, (data: any) => any> = {
|
const devReducers: Record<string, (data: any) => any> = {
|
||||||
VNode: data => isVNode(data) ? { type: data.type, props: data.props } : undefined,
|
VNode: data => isVNode(data) ? { type: data.type, props: data.props } : undefined,
|
||||||
@ -75,7 +77,7 @@ export default (nitroApp: NitroApp) => {
|
|||||||
const ctx = asyncContext.tryUse()
|
const ctx = asyncContext.tryUse()
|
||||||
if (!ctx) { return }
|
if (!ctx) { return }
|
||||||
try {
|
try {
|
||||||
htmlContext.bodyAppend.unshift(`<script type="application/json" id="__NUXT_LOGS__">${stringify(ctx.logs, { ...devReducers, ...ctx.event.context._payloadReducers })}</script>`)
|
htmlContext.bodyAppend.unshift(`<script type="application/json" data-nuxt-logs="${appId}">${stringify(ctx.logs, { ...devReducers, ...ctx.event.context._payloadReducers })}</script>`)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const shortError = e instanceof Error && 'toString' in e ? ` Received \`${e.toString()}\`.` : ''
|
const shortError = e instanceof Error && 'toString' in e ? ` Received \`${e.toString()}\`.` : ''
|
||||||
console.warn(`[nuxt] Failed to stringify dev server logs.${shortError} You can define your own reducer/reviver for rich types following the instructions in https://nuxt.com/docs/api/composables/use-nuxt-app#payload.`)
|
console.warn(`[nuxt] Failed to stringify dev server logs.${shortError} You can define your own reducer/reviver for rich types following the instructions in https://nuxt.com/docs/api/composables/use-nuxt-app#payload.`)
|
||||||
|
@ -31,7 +31,7 @@ import { renderSSRHeadOptions } from '#internal/unhead.config.mjs'
|
|||||||
|
|
||||||
import type { NuxtPayload, NuxtSSRContext } from '#app'
|
import type { NuxtPayload, NuxtSSRContext } from '#app'
|
||||||
// @ts-expect-error virtual file
|
// @ts-expect-error virtual file
|
||||||
import { appHead, appRootAttrs, appRootTag, appTeleportAttrs, appTeleportTag, componentIslands } from '#internal/nuxt.config.mjs'
|
import { appHead, appId, appRootAttrs, appRootTag, appTeleportAttrs, appTeleportTag, componentIslands, multiApp } from '#internal/nuxt.config.mjs'
|
||||||
// @ts-expect-error virtual file
|
// @ts-expect-error virtual file
|
||||||
import { buildAssetsURL, publicAssetsURL } from '#internal/nuxt/paths'
|
import { buildAssetsURL, publicAssetsURL } from '#internal/nuxt/paths'
|
||||||
|
|
||||||
@ -427,10 +427,10 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
|
|||||||
head.push({
|
head.push({
|
||||||
script: _PAYLOAD_EXTRACTION
|
script: _PAYLOAD_EXTRACTION
|
||||||
? process.env.NUXT_JSON_PAYLOADS
|
? process.env.NUXT_JSON_PAYLOADS
|
||||||
? renderPayloadJsonScript({ id: '__NUXT_DATA__', ssrContext, data: splitPayload(ssrContext).initial, src: payloadURL })
|
? renderPayloadJsonScript({ ssrContext, data: splitPayload(ssrContext).initial, src: payloadURL })
|
||||||
: renderPayloadScript({ ssrContext, data: splitPayload(ssrContext).initial, src: payloadURL })
|
: renderPayloadScript({ ssrContext, data: splitPayload(ssrContext).initial, src: payloadURL })
|
||||||
: process.env.NUXT_JSON_PAYLOADS
|
: process.env.NUXT_JSON_PAYLOADS
|
||||||
? renderPayloadJsonScript({ id: '__NUXT_DATA__', ssrContext, data: ssrContext.payload })
|
? renderPayloadJsonScript({ ssrContext, data: ssrContext.payload })
|
||||||
: renderPayloadScript({ ssrContext, data: ssrContext.payload }),
|
: renderPayloadScript({ ssrContext, data: ssrContext.payload }),
|
||||||
}, {
|
}, {
|
||||||
...headEntryOptions,
|
...headEntryOptions,
|
||||||
@ -586,21 +586,27 @@ function renderPayloadResponse (ssrContext: NuxtSSRContext) {
|
|||||||
} satisfies RenderResponse
|
} satisfies RenderResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderPayloadJsonScript (opts: { id: string, ssrContext: NuxtSSRContext, data?: any, src?: string }): Script[] {
|
function renderPayloadJsonScript (opts: { ssrContext: NuxtSSRContext, data?: any, src?: string }): Script[] {
|
||||||
const contents = opts.data ? stringify(opts.data, opts.ssrContext._payloadReducers) : ''
|
const contents = opts.data ? stringify(opts.data, opts.ssrContext._payloadReducers) : ''
|
||||||
const payload: Script = {
|
const payload: Script = {
|
||||||
'type': 'application/json',
|
'type': 'application/json',
|
||||||
'id': opts.id,
|
|
||||||
'innerHTML': contents,
|
'innerHTML': contents,
|
||||||
|
'data-nuxt-data': appId,
|
||||||
'data-ssr': !(process.env.NUXT_NO_SSR || opts.ssrContext.noSSR),
|
'data-ssr': !(process.env.NUXT_NO_SSR || opts.ssrContext.noSSR),
|
||||||
}
|
}
|
||||||
|
if (!multiApp) {
|
||||||
|
payload.id = '__NUXT_DATA__'
|
||||||
|
}
|
||||||
if (opts.src) {
|
if (opts.src) {
|
||||||
payload['data-src'] = opts.src
|
payload['data-src'] = opts.src
|
||||||
}
|
}
|
||||||
|
const config = uneval(opts.ssrContext.config)
|
||||||
return [
|
return [
|
||||||
payload,
|
payload,
|
||||||
{
|
{
|
||||||
innerHTML: `window.__NUXT__={};window.__NUXT__.config=${uneval(opts.ssrContext.config)}`,
|
innerHTML: multiApp
|
||||||
|
? `window.__NUXT__=window.__NUXT__||{};window.__NUXT__[${JSON.stringify(appId)}]={config:${config}}`
|
||||||
|
: `window.__NUXT__={};window.__NUXT__.config=${config}`,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -608,17 +614,22 @@ function renderPayloadJsonScript (opts: { id: string, ssrContext: NuxtSSRContext
|
|||||||
function renderPayloadScript (opts: { ssrContext: NuxtSSRContext, data?: any, src?: string }): Script[] {
|
function renderPayloadScript (opts: { ssrContext: NuxtSSRContext, data?: any, src?: string }): Script[] {
|
||||||
opts.data.config = opts.ssrContext.config
|
opts.data.config = opts.ssrContext.config
|
||||||
const _PAYLOAD_EXTRACTION = import.meta.prerender && process.env.NUXT_PAYLOAD_EXTRACTION && !opts.ssrContext.noSSR
|
const _PAYLOAD_EXTRACTION = import.meta.prerender && process.env.NUXT_PAYLOAD_EXTRACTION && !opts.ssrContext.noSSR
|
||||||
|
const nuxtData = devalue(opts.data)
|
||||||
if (_PAYLOAD_EXTRACTION) {
|
if (_PAYLOAD_EXTRACTION) {
|
||||||
|
const singleAppPayload = `import p from "${opts.src}";window.__NUXT__={...p,...(${nuxtData})}`
|
||||||
|
const multiAppPayload = `import p from "${opts.src}";window.__NUXT__=window.__NUXT__||{};window.__NUXT__[${JSON.stringify(appId)}]={...p,...(${nuxtData})}`
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
type: 'module',
|
type: 'module',
|
||||||
innerHTML: `import p from "${opts.src}";window.__NUXT__={...p,...(${devalue(opts.data)})}`,
|
innerHTML: multiApp ? multiAppPayload : singleAppPayload,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
const singleAppPayload = `window.__NUXT__=${nuxtData}`
|
||||||
|
const multiAppPayload = `window.__NUXT__=window.__NUXT__||{};window.__NUXT__[${JSON.stringify(appId)}]=${nuxtData}`
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
innerHTML: `window.__NUXT__=${devalue(opts.data)}`,
|
innerHTML: multiApp ? multiAppPayload : singleAppPayload,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -96,6 +96,8 @@ export const serverPluginTemplate: NuxtTemplate = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TS_RE = /\.[cm]?tsx?$/
|
||||||
|
|
||||||
export const pluginsDeclaration: NuxtTemplate = {
|
export const pluginsDeclaration: NuxtTemplate = {
|
||||||
filename: 'types/plugins.d.ts',
|
filename: 'types/plugins.d.ts',
|
||||||
getContents: async ({ nuxt, app }) => {
|
getContents: async ({ nuxt, app }) => {
|
||||||
@ -124,9 +126,14 @@ export const pluginsDeclaration: NuxtTemplate = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (exists(pluginPath)) {
|
if (exists(pluginPath)) {
|
||||||
|
if (TS_RE.test(pluginPath)) {
|
||||||
tsImports.push(relativePath.replace(EXTENSION_RE, ''))
|
tsImports.push(relativePath.replace(EXTENSION_RE, ''))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
tsImports.push(relativePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// No declaration found that TypeScript can use
|
||||||
}
|
}
|
||||||
|
|
||||||
return `// Generated by Nuxt'
|
return `// Generated by Nuxt'
|
||||||
@ -147,14 +154,6 @@ declare module '#app' {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module '@vue/runtime-core' {
|
|
||||||
interface ComponentCustomProperties extends NuxtAppInjections { }
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module '@vue/runtime-dom' {
|
|
||||||
interface ComponentCustomProperties extends NuxtAppInjections { }
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'vue' {
|
declare module 'vue' {
|
||||||
interface ComponentCustomProperties extends NuxtAppInjections { }
|
interface ComponentCustomProperties extends NuxtAppInjections { }
|
||||||
}
|
}
|
||||||
@ -350,9 +349,16 @@ declare module 'nitropack/types' {
|
|||||||
|
|
||||||
export const clientConfigTemplate: NuxtTemplate = {
|
export const clientConfigTemplate: NuxtTemplate = {
|
||||||
filename: 'nitro.client.mjs',
|
filename: 'nitro.client.mjs',
|
||||||
getContents: () => `
|
getContents: ({ nuxt }) => {
|
||||||
export const useRuntimeConfig = () => window?.__NUXT__?.config || window?.useNuxtApp?.().payload?.config || {}
|
const appId = JSON.stringify(nuxt.options.appId)
|
||||||
`,
|
return [
|
||||||
|
'export const useRuntimeConfig = () => ',
|
||||||
|
(!nuxt.options.future.multiApp
|
||||||
|
? 'window?.__NUXT__?.config || window?.useNuxtApp?.().payload?.config'
|
||||||
|
: `window?.__NUXT__?.[${appId}]?.config || window?.useNuxtApp?.(${appId}).payload?.config`)
|
||||||
|
|| {},
|
||||||
|
].join('\n')
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const appConfigDeclarationTemplate: NuxtTemplate = {
|
export const appConfigDeclarationTemplate: NuxtTemplate = {
|
||||||
@ -497,6 +503,7 @@ export const nuxtConfigTemplate: NuxtTemplate = {
|
|||||||
`export const viewTransition = ${ctx.nuxt.options.experimental.viewTransition}`,
|
`export const viewTransition = ${ctx.nuxt.options.experimental.viewTransition}`,
|
||||||
`export const appId = ${JSON.stringify(ctx.nuxt.options.appId)}`,
|
`export const appId = ${JSON.stringify(ctx.nuxt.options.appId)}`,
|
||||||
`export const outdatedBuildInterval = ${ctx.nuxt.options.experimental.checkOutdatedBuildInterval}`,
|
`export const outdatedBuildInterval = ${ctx.nuxt.options.experimental.checkOutdatedBuildInterval}`,
|
||||||
|
`export const multiApp = ${!!ctx.nuxt.options.future.multiApp}`,
|
||||||
].join('\n\n')
|
].join('\n\n')
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -41,9 +41,9 @@
|
|||||||
"@types/sass-loader": "8.0.9",
|
"@types/sass-loader": "8.0.9",
|
||||||
"@unhead/schema": "1.9.16",
|
"@unhead/schema": "1.9.16",
|
||||||
"@vitejs/plugin-vue": "5.1.2",
|
"@vitejs/plugin-vue": "5.1.2",
|
||||||
"@vitejs/plugin-vue-jsx": "4.0.0",
|
"@vitejs/plugin-vue-jsx": "4.0.1",
|
||||||
"@vue/compiler-core": "3.4.37",
|
"@vue/compiler-core": "3.4.38",
|
||||||
"@vue/compiler-sfc": "3.4.37",
|
"@vue/compiler-sfc": "3.4.38",
|
||||||
"@vue/language-core": "2.0.29",
|
"@vue/language-core": "2.0.29",
|
||||||
"c12": "2.0.0-beta.1",
|
"c12": "2.0.0-beta.1",
|
||||||
"esbuild-loader": "4.2.2",
|
"esbuild-loader": "4.2.2",
|
||||||
@ -54,13 +54,13 @@
|
|||||||
"unbuild": "3.0.0-rc.7",
|
"unbuild": "3.0.0-rc.7",
|
||||||
"unctx": "2.3.1",
|
"unctx": "2.3.1",
|
||||||
"unenv": "1.10.0",
|
"unenv": "1.10.0",
|
||||||
"vite": "5.4.0",
|
"vite": "5.4.1",
|
||||||
"vue": "3.4.37",
|
"vue": "3.4.38",
|
||||||
"vue-bundle-renderer": "2.1.0",
|
"vue-bundle-renderer": "2.1.0",
|
||||||
"vue-loader": "17.4.2",
|
"vue-loader": "17.4.2",
|
||||||
"vue-router": "4.4.3",
|
"vue-router": "4.4.3",
|
||||||
"webpack": "5.93.0",
|
"webpack": "5.93.0",
|
||||||
"webpack-dev-middleware": "7.3.0"
|
"webpack-dev-middleware": "7.4.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"compatx": "^0.1.8",
|
"compatx": "^0.1.8",
|
||||||
|
@ -175,7 +175,29 @@ export default defineUntypedSchema({
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
buildDir: {
|
buildDir: {
|
||||||
$resolve: async (val: string | undefined, get): Promise<string> => resolve(await get('rootDir') as string, val || '.nuxt'),
|
$resolve: async (val: string | undefined, get): Promise<string> => {
|
||||||
|
const rootDir = await get('rootDir') as string
|
||||||
|
|
||||||
|
if (val) {
|
||||||
|
return resolve(rootDir, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultBuildDir = resolve(rootDir, '.nuxt')
|
||||||
|
|
||||||
|
const isDev = await get('dev') as boolean
|
||||||
|
if (isDev) {
|
||||||
|
return defaultBuildDir
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: nuxi CLI should ensure .nuxt dir exists
|
||||||
|
if (!existsSync(defaultBuildDir)) {
|
||||||
|
// This is to ensure that types continue to work for CI builds
|
||||||
|
return defaultBuildDir
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: handle build caching + using buildId in directory
|
||||||
|
return resolve(rootDir, 'node_modules/.cache/nuxt/builds', 'production')
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -353,6 +353,10 @@ export default defineUntypedSchema({
|
|||||||
/** @type {typeof import('#app/components/nuxt-link')['NuxtLinkOptions']} */
|
/** @type {typeof import('#app/components/nuxt-link')['NuxtLinkOptions']} */
|
||||||
nuxtLink: {
|
nuxtLink: {
|
||||||
componentName: 'NuxtLink',
|
componentName: 'NuxtLink',
|
||||||
|
prefetch: true,
|
||||||
|
prefetchOn: {
|
||||||
|
visibility: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Options that apply to `useAsyncData` (and also therefore `useFetch`)
|
* Options that apply to `useAsyncData` (and also therefore `useFetch`)
|
||||||
|
@ -45,7 +45,6 @@ export default defineUntypedSchema({
|
|||||||
'vue',
|
'vue',
|
||||||
'@vue/runtime-core',
|
'@vue/runtime-core',
|
||||||
'@vue/compiler-sfc',
|
'@vue/compiler-sfc',
|
||||||
'@vue/runtime-dom',
|
|
||||||
'vue-router',
|
'vue-router',
|
||||||
'vue-router/auto-routes',
|
'vue-router/auto-routes',
|
||||||
'unplugin-vue-router/client',
|
'unplugin-vue-router/client',
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/html-minifier": "4.0.5",
|
"@types/html-minifier": "4.0.5",
|
||||||
"@unocss/reset": "0.62.1",
|
"@unocss/reset": "0.62.2",
|
||||||
"critters": "0.0.24",
|
"critters": "0.0.24",
|
||||||
"execa": "9.3.0",
|
"execa": "9.3.1",
|
||||||
"globby": "14.0.2",
|
"globby": "14.0.2",
|
||||||
"html-minifier": "4.0.0",
|
"html-minifier": "4.0.0",
|
||||||
"html-validate": "8.21.0",
|
"html-validate": "8.21.0",
|
||||||
@ -30,7 +30,7 @@
|
|||||||
"pathe": "1.1.2",
|
"pathe": "1.1.2",
|
||||||
"prettier": "3.3.3",
|
"prettier": "3.3.3",
|
||||||
"scule": "1.3.0",
|
"scule": "1.3.0",
|
||||||
"unocss": "0.62.1",
|
"unocss": "0.62.2",
|
||||||
"vite": "5.4.0"
|
"vite": "5.4.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,21 +27,21 @@
|
|||||||
"@nuxt/schema": "workspace:*",
|
"@nuxt/schema": "workspace:*",
|
||||||
"@types/clear": "0.1.4",
|
"@types/clear": "0.1.4",
|
||||||
"@types/estree": "1.0.5",
|
"@types/estree": "1.0.5",
|
||||||
"rollup": "4.20.0",
|
"rollup": "4.21.0",
|
||||||
"unbuild": "3.0.0-rc.7",
|
"unbuild": "3.0.0-rc.7",
|
||||||
"vue": "3.4.37"
|
"vue": "3.4.38"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nuxt/kit": "workspace:*",
|
"@nuxt/kit": "workspace:*",
|
||||||
"@rollup/plugin-replace": "^5.0.7",
|
"@rollup/plugin-replace": "^5.0.7",
|
||||||
"@vitejs/plugin-vue": "^5.1.2",
|
"@vitejs/plugin-vue": "^5.1.2",
|
||||||
"@vitejs/plugin-vue-jsx": "^4.0.0",
|
"@vitejs/plugin-vue-jsx": "^4.0.1",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"clear": "^0.1.0",
|
"clear": "^0.1.0",
|
||||||
"consola": "^3.2.3",
|
"consola": "^3.2.3",
|
||||||
"cssnano": "^7.0.5",
|
"cssnano": "^7.0.5",
|
||||||
"defu": "^6.1.4",
|
"defu": "^6.1.4",
|
||||||
"esbuild": "^0.23.0",
|
"esbuild": "^0.23.1",
|
||||||
"escape-string-regexp": "^5.0.0",
|
"escape-string-regexp": "^5.0.0",
|
||||||
"estree-walker": "^3.0.3",
|
"estree-walker": "^3.0.3",
|
||||||
"externality": "^1.0.2",
|
"externality": "^1.0.2",
|
||||||
@ -61,8 +61,8 @@
|
|||||||
"strip-literal": "^2.1.0",
|
"strip-literal": "^2.1.0",
|
||||||
"ufo": "^1.5.4",
|
"ufo": "^1.5.4",
|
||||||
"unenv": "^1.10.0",
|
"unenv": "^1.10.0",
|
||||||
"unplugin": "^1.12.1",
|
"unplugin": "^1.12.2",
|
||||||
"vite": "^5.4.0",
|
"vite": "^5.4.1",
|
||||||
"vite-node": "^2.0.5",
|
"vite-node": "^2.0.5",
|
||||||
"vite-plugin-checker": "^0.7.2",
|
"vite-plugin-checker": "^0.7.2",
|
||||||
"vue-bundle-renderer": "^2.1.0"
|
"vue-bundle-renderer": "^2.1.0"
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
"lodash-es": "4.17.21",
|
"lodash-es": "4.17.21",
|
||||||
"magic-string": "^0.30.11",
|
"magic-string": "^0.30.11",
|
||||||
"memfs": "^4.11.1",
|
"memfs": "^4.11.1",
|
||||||
"mini-css-extract-plugin": "^2.9.0",
|
"mini-css-extract-plugin": "^2.9.1",
|
||||||
"mlly": "^1.7.1",
|
"mlly": "^1.7.1",
|
||||||
"ohash": "^1.1.3",
|
"ohash": "^1.1.3",
|
||||||
"pathe": "^1.1.2",
|
"pathe": "^1.1.2",
|
||||||
@ -60,13 +60,13 @@
|
|||||||
"time-fix-plugin": "^2.0.7",
|
"time-fix-plugin": "^2.0.7",
|
||||||
"ufo": "^1.5.4",
|
"ufo": "^1.5.4",
|
||||||
"unenv": "^1.10.0",
|
"unenv": "^1.10.0",
|
||||||
"unplugin": "^1.12.1",
|
"unplugin": "^1.12.2",
|
||||||
"url-loader": "^4.1.1",
|
"url-loader": "^4.1.1",
|
||||||
"vue-bundle-renderer": "^2.1.0",
|
"vue-bundle-renderer": "^2.1.0",
|
||||||
"vue-loader": "^17.4.2",
|
"vue-loader": "^17.4.2",
|
||||||
"webpack": "^5.93.0",
|
"webpack": "^5.93.0",
|
||||||
"webpack-bundle-analyzer": "^4.10.2",
|
"webpack-bundle-analyzer": "^4.10.2",
|
||||||
"webpack-dev-middleware": "^7.3.0",
|
"webpack-dev-middleware": "^7.4.0",
|
||||||
"webpack-hot-middleware": "^2.26.1",
|
"webpack-hot-middleware": "^2.26.1",
|
||||||
"webpack-virtual-modules": "^0.6.2",
|
"webpack-virtual-modules": "^0.6.2",
|
||||||
"webpackbar": "^6.0.1"
|
"webpackbar": "^6.0.1"
|
||||||
@ -78,9 +78,9 @@
|
|||||||
"@types/pify": "5.0.4",
|
"@types/pify": "5.0.4",
|
||||||
"@types/webpack-bundle-analyzer": "4.7.0",
|
"@types/webpack-bundle-analyzer": "4.7.0",
|
||||||
"@types/webpack-hot-middleware": "2.25.9",
|
"@types/webpack-hot-middleware": "2.25.9",
|
||||||
"rollup": "4.20.0",
|
"rollup": "4.21.0",
|
||||||
"unbuild": "3.0.0-rc.7",
|
"unbuild": "3.0.0-rc.7",
|
||||||
"vue": "3.4.37"
|
"vue": "3.4.38"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"vue": "^3.3.4"
|
"vue": "^3.3.4"
|
||||||
|
1677
pnpm-lock.yaml
1677
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
1
test/fixtures/basic-types/nuxt.config.ts
vendored
1
test/fixtures/basic-types/nuxt.config.ts
vendored
@ -9,7 +9,6 @@ export default defineNuxtConfig({
|
|||||||
future: {
|
future: {
|
||||||
typescriptBundlerResolution: process.env.MODULE_RESOLUTION === 'bundler',
|
typescriptBundlerResolution: process.env.MODULE_RESOLUTION === 'bundler',
|
||||||
},
|
},
|
||||||
buildDir: process.env.NITRO_BUILD_DIR,
|
|
||||||
builder: process.env.TEST_BUILDER as 'webpack' | 'vite' ?? 'vite',
|
builder: process.env.TEST_BUILDER as 'webpack' | 'vite' ?? 'vite',
|
||||||
theme: './extends/bar',
|
theme: './extends/bar',
|
||||||
extends: [
|
extends: [
|
||||||
|
2
test/fixtures/basic/nuxt.config.ts
vendored
2
test/fixtures/basic/nuxt.config.ts
vendored
@ -31,7 +31,6 @@ export default defineNuxtConfig({
|
|||||||
include: ['keepalive-in-config', 'not-keepalive-in-nuxtpage'],
|
include: ['keepalive-in-config', 'not-keepalive-in-nuxtpage'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
buildDir: process.env.NITRO_BUILD_DIR,
|
|
||||||
builder: process.env.TEST_BUILDER as 'webpack' | 'vite' ?? 'vite',
|
builder: process.env.TEST_BUILDER as 'webpack' | 'vite' ?? 'vite',
|
||||||
appId: 'nuxt-app-basic',
|
appId: 'nuxt-app-basic',
|
||||||
build: {
|
build: {
|
||||||
@ -68,7 +67,6 @@ export default defineNuxtConfig({
|
|||||||
'/hydration/spa-redirection/**': { ssr: false },
|
'/hydration/spa-redirection/**': { ssr: false },
|
||||||
'/no-scripts': { experimentalNoScripts: true },
|
'/no-scripts': { experimentalNoScripts: true },
|
||||||
},
|
},
|
||||||
output: { dir: process.env.NITRO_OUTPUT_DIR },
|
|
||||||
prerender: {
|
prerender: {
|
||||||
routes: [
|
routes: [
|
||||||
'/random/a',
|
'/random/a',
|
||||||
|
@ -23,8 +23,6 @@ if (process.env.TEST_ENV !== 'built' && !isWindows) {
|
|||||||
setupTimeout: (isWindows ? 360 : 120) * 1000,
|
setupTimeout: (isWindows ? 360 : 120) * 1000,
|
||||||
nuxtConfig: {
|
nuxtConfig: {
|
||||||
builder: isWebpack ? 'webpack' : 'vite',
|
builder: isWebpack ? 'webpack' : 'vite',
|
||||||
buildDir: process.env.NITRO_BUILD_DIR,
|
|
||||||
nitro: { output: { dir: process.env.NITRO_OUTPUT_DIR } },
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
95
test/nuxt/components.test.ts
Normal file
95
test/nuxt/components.test.ts
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/// <reference path="../fixtures/basic/.nuxt/nuxt.d.ts" />
|
||||||
|
|
||||||
|
import { describe, expect, it, vi } from 'vitest'
|
||||||
|
import { mountSuspended } from '@nuxt/test-utils/runtime'
|
||||||
|
|
||||||
|
import { nuxtLinkDefaults } from '#build/nuxt.config.mjs'
|
||||||
|
|
||||||
|
describe('nuxt-link:prefetch', () => {
|
||||||
|
it('should prefetch on visibility by default', async () => {
|
||||||
|
const component = defineNuxtLink(nuxtLinkDefaults)
|
||||||
|
|
||||||
|
const { observer } = useMockObserver()
|
||||||
|
|
||||||
|
const nuxtApp = useNuxtApp()
|
||||||
|
nuxtApp.hooks.callHook = vi.fn(() => Promise.resolve())
|
||||||
|
|
||||||
|
await mountSuspended(component, { props: { to: '/to' } })
|
||||||
|
|
||||||
|
expect(nuxtApp.hooks.callHook).not.toHaveBeenCalled()
|
||||||
|
|
||||||
|
await observer.trigger()
|
||||||
|
expect(nuxtApp.hooks.callHook).toHaveBeenCalledTimes(1)
|
||||||
|
|
||||||
|
await observer.trigger()
|
||||||
|
expect(nuxtApp.hooks.callHook).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should prefetch with custom string `prefetchOn`', async () => {
|
||||||
|
const component = defineNuxtLink(nuxtLinkDefaults)
|
||||||
|
const nuxtApp = useNuxtApp()
|
||||||
|
nuxtApp.hooks.callHook = vi.fn(() => Promise.resolve())
|
||||||
|
|
||||||
|
const { observer } = useMockObserver()
|
||||||
|
const wrapper = await mountSuspended(component, { props: { to: '/to', prefetchOn: 'interaction' } })
|
||||||
|
|
||||||
|
await observer.trigger()
|
||||||
|
expect(nuxtApp.hooks.callHook).not.toHaveBeenCalled()
|
||||||
|
|
||||||
|
await wrapper.find('a').trigger('focus')
|
||||||
|
expect(nuxtApp.hooks.callHook).toHaveBeenCalledTimes(1)
|
||||||
|
|
||||||
|
await wrapper.find('a').trigger('focus')
|
||||||
|
expect(nuxtApp.hooks.callHook).toHaveBeenCalledTimes(1)
|
||||||
|
|
||||||
|
await wrapper.find('a').trigger('pointerenter')
|
||||||
|
expect(nuxtApp.hooks.callHook).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should prefetch with custom object `prefetchOn`', async () => {
|
||||||
|
const component = defineNuxtLink(nuxtLinkDefaults)
|
||||||
|
const nuxtApp = useNuxtApp()
|
||||||
|
nuxtApp.hooks.callHook = vi.fn(() => Promise.resolve())
|
||||||
|
|
||||||
|
const { observer } = useMockObserver()
|
||||||
|
await mountSuspended(component, { props: { to: '/to', prefetchOn: { interaction: true } } })
|
||||||
|
|
||||||
|
await observer.trigger()
|
||||||
|
expect(nuxtApp.hooks.callHook).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should prefetch with custom object `prefetchOn` overriding default', async () => {
|
||||||
|
const component = defineNuxtLink(nuxtLinkDefaults)
|
||||||
|
const nuxtApp = useNuxtApp()
|
||||||
|
nuxtApp.hooks.callHook = vi.fn(() => Promise.resolve())
|
||||||
|
|
||||||
|
const { observer } = useMockObserver()
|
||||||
|
await mountSuspended(component, { props: { to: '/to', prefetchOn: { interaction: true, visibility: false } } })
|
||||||
|
|
||||||
|
await observer.trigger()
|
||||||
|
expect(nuxtApp.hooks.callHook).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
function useMockObserver () {
|
||||||
|
let callback: (entries: Array<{ target: HTMLElement, isIntersecting: boolean }>) => unknown
|
||||||
|
let el: HTMLElement
|
||||||
|
const mockObserver = class IntersectionObserver {
|
||||||
|
el: HTMLElement
|
||||||
|
constructor (_callback?: (entries: Array<{ target: HTMLElement, isIntersecting: boolean }>) => unknown) {
|
||||||
|
callback ||= _callback
|
||||||
|
}
|
||||||
|
|
||||||
|
observe = (_el: HTMLElement) => { el = _el }
|
||||||
|
|
||||||
|
trigger = () => callback?.([{ target: el, isIntersecting: true }])
|
||||||
|
unobserve = () => {}
|
||||||
|
disconnect = () => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.IntersectionObserver = mockObserver as any
|
||||||
|
|
||||||
|
const observer = new mockObserver()
|
||||||
|
|
||||||
|
return { observer }
|
||||||
|
}
|
@ -14,8 +14,6 @@ await setup({
|
|||||||
setupTimeout: (isWindows ? 360 : 120) * 1000,
|
setupTimeout: (isWindows ? 360 : 120) * 1000,
|
||||||
nuxtConfig: {
|
nuxtConfig: {
|
||||||
builder: isWebpack ? 'webpack' : 'vite',
|
builder: isWebpack ? 'webpack' : 'vite',
|
||||||
buildDir: process.env.NITRO_BUILD_DIR,
|
|
||||||
nitro: { output: { dir: process.env.NITRO_OUTPUT_DIR } },
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -114,7 +114,9 @@ export function parseData (html: string) {
|
|||||||
attrs: {},
|
attrs: {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const { script, attrs = '' } = html.match(/<script type="application\/json" id="__NUXT_DATA__"(?<attrs>[^>]+)>(?<script>.*?)<\/script>/)?.groups || {}
|
|
||||||
|
const regexp = /<script type="application\/json" data-nuxt-data="[^"]+"(?<attrs>[^>]+)>(?<script>.*?)<\/script>/
|
||||||
|
const { script, attrs = '' } = html.match(regexp)?.groups || {}
|
||||||
const _attrs: Record<string, string> = {}
|
const _attrs: Record<string, string> = {}
|
||||||
for (const attr of attrs.matchAll(/( |^)(?<key>[\w-]+)="(?<value>[^"]+)"/g)) {
|
for (const attr of attrs.matchAll(/( |^)(?<key>[\w-]+)="(?<value>[^"]+)"/g)) {
|
||||||
_attrs[attr!.groups!.key!] = attr!.groups!.value!
|
_attrs[attr!.groups!.key!] = attr!.groups!.value!
|
||||||
|
Loading…
Reference in New Issue
Block a user