-## License
+## βοΈ License
[MIT](./LICENSE)
-
diff --git a/docs/1.getting-started/11.testing.md b/docs/1.getting-started/11.testing.md
index 2051ded616..729b830bea 100644
--- a/docs/1.getting-started/11.testing.md
+++ b/docs/1.getting-started/11.testing.md
@@ -15,8 +15,8 @@ Nuxt offers first-class support for end-to-end and unit testing of your Nuxt app
In order to allow you to manage your other testing dependencies, `@nuxt/test-utils` ships with various optional peer dependencies. For example:
- you can choose between `happy-dom` and `jsdom` for a runtime Nuxt environment
-- you can choose between `vitest` and `jest` for end-to-end test runners
-- `playwright-core` is only required if you wish to use the built-in browser testing utilities
+- 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)
::code-group
```bash [yarn]
@@ -88,6 +88,7 @@ export default defineVitestConfig({
// environmentOptions: {
// nuxt: {
// rootDir: fileURLToPath(new URL('./playground', import.meta.url)),
+ // domEnvironment: 'happy-dom', // 'happy-dom' (default) or 'jsdom'
// overrides: {
// // other Nuxt config you want to pass
// }
@@ -387,7 +388,7 @@ await setup({
## End-To-End Testing
-For end-to-end testing, we support [Vitest](https://github.com/vitest-dev/vitest) and [Jest](https://jestjs.io) as test runners.
+For end-to-end testing, we support [Vitest](https://github.com/vitest-dev/vitest), [Jest](https://jestjs.io), [Cucumber](https://cucumber.io/) and [Playwright](https://playwright.dev/) as test runners.
### Setup
@@ -453,7 +454,7 @@ Please use the options below for the `setup` method.
- `type`: The type of browser to launch - either `chromium`, `firefox` or `webkit`
- `launch`: `object` of options that will be passed to playwright when launching the browser. See [full API reference](https://playwright.dev/docs/api/class-browsertype#browser-type-launch).
- `runner`: Specify the runner for the test suite. Currently, [Vitest](https://vitest.dev) is recommended.
- - Type: `'vitest' | 'jest'`
+ - Type: `'vitest' | 'jest' | 'cucumber'`
- Default: `'vitest'`
### APIs
@@ -492,11 +493,11 @@ const pageUrl = url('/page')
### Testing in a Browser
-We provide built-in support using Playwright within `@nuxt/test-utils`, but you can also use other test runners for end-to-end browser testing.
+We provide built-in support using Playwright within `@nuxt/test-utils`, either programmatically or via the Playwright test runner.
#### `createPage(url)`
-You can create a configured Playwright browser instance, and (optionally) point it at a path from the running server. You can find out more about the API methods available from [in the Playwright documentation](https://playwright.dev/docs/api/class-page).
+Within `vitest`, `jest` or `cucumber`, you can create a configured Playwright browser instance with `createPage`, and (optionally) point it at a path from the running server. You can find out more about the API methods available from [in the Playwright documentation](https://playwright.dev/docs/api/class-page).
```ts twoslash
import { createPage } from '@nuxt/test-utils/e2e'
@@ -504,3 +505,70 @@ import { createPage } from '@nuxt/test-utils/e2e'
const page = await createPage('/page')
// you can access all the Playwright APIs from the `page` variable
```
+
+#### Testing with Playwright Test Runner
+
+We also provide first-class support for testing Nuxt within [the Playwright test runner](https://playwright.dev/docs/intro).
+
+::code-group
+```bash [yarn]
+yarn add --dev @playwright/test @nuxt/test-utils
+```
+```bash [npm]
+npm i --save-dev @playwright/test @nuxt/test-utils
+```
+```bash [pnpm]
+pnpm add -D @playwright/test @nuxt/test-utils
+```
+```bash [bun]
+bun add --dev @playwright/test @nuxt/test-utils
+```
+::
+
+You can provide global Nuxt configuration, with the same configuration details as the `setup()` function mentioned earlier in this section.
+
+```ts [playwright.config.ts]
+import { fileURLToPath } from 'node:url'
+import { defineConfig, devices } from '@playwright/test'
+import type { ConfigOptions } from '@nuxt/test-utils/playwright'
+
+export default defineConfig({
+ use: {
+ nuxt: {
+ rootDir: fileURLToPath(new URL('.', import.meta.url))
+ }
+ },
+ // ...
+})
+```
+
+::read-more{title="See full example config" to="https://github.com/nuxt/test-utils/blob/main/examples/app-playwright/playwright.config.ts" target="_blank"}
+::
+
+Your test file should then use `expect` and `test` directly from `@nuxt/test-utils/playwright`:
+
+```ts [tests/example.test.ts]
+import { expect, test } from '@nuxt/test-utils/playwright'
+
+test('test', async ({ page, goto }) => {
+ await goto('/', { waitUntil: 'hydration' })
+ await expect(page.getByRole('heading')).toHaveText('Welcome to Playwright!')
+})
+```
+
+You can alternatively configure your Nuxt server directly within your test file:
+
+```ts [tests/example.test.ts]
+import { expect, test } from '@nuxt/test-utils/playwright'
+
+test.use({
+ nuxt: {
+ rootDir: fileURLToPath(new URL('..', import.meta.url))
+ }
+})
+
+test('test', async ({ page, goto }) => {
+ await goto('/', { waitUntil: 'hydration' })
+ await expect(page.getByRole('heading')).toHaveText('Welcome to Playwright!')
+})
+```
diff --git a/docs/1.getting-started/2.installation.md b/docs/1.getting-started/2.installation.md
index f7a4d317ac..f89438e8f2 100644
--- a/docs/1.getting-started/2.installation.md
+++ b/docs/1.getting-started/2.installation.md
@@ -22,7 +22,7 @@ Start with one of our starters and themes directly by opening [nuxt.new](https:/
#### Prerequisites
- **Node.js** - [`v18.0.0`](https://nodejs.org/en) or newer
-- **Text editor** - We recommend [Visual Studio Code](https://code.visualstudio.com/) with the [Volar Extension](https://marketplace.visualstudio.com/items?itemName=Vue.volar)
+- **Text editor** - We recommend [Visual Studio Code](https://code.visualstudio.com/) with the [official Vue extension](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (previously known as Volar)
- **Terminal** - In order to run Nuxt commands
::note
@@ -30,17 +30,6 @@ Start with one of our starters and themes directly by opening [nuxt.new](https:/
:summary[Additional notes for an optimal setup:]
- **Node.js**: Make sure to use an even numbered version (18, 20, etc)
- **Nuxtr**: Install the community-developed [Nuxtr extension](https://marketplace.visualstudio.com/items?itemName=Nuxtr.nuxtr-vscode)
- - **Volar**: Either enable [**Take Over Mode**](https://vuejs.org/guide/typescript/overview.html#volar-takeover-mode) (recommended) or add the [TypeScript Vue Plugin](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin)
-
- If you have enabled **Take Over Mode** or installed the **TypeScript Vue Plugin (Volar)**, you can disable generating the shim for `*.vue` files in your [`nuxt.config.ts`](/docs/guide/directory-structure/nuxt-config) file:
-
- ```ts twoslash [nuxt.config.ts]
- export default defineNuxtConfig({
- typescript: {
- shim: false
- }
- })
- ```
::
::
diff --git a/docs/1.getting-started/4.styling.md b/docs/1.getting-started/4.styling.md
index b2437a9cef..4b2bd3be36 100644
--- a/docs/1.getting-started/4.styling.md
+++ b/docs/1.getting-started/4.styling.md
@@ -243,7 +243,7 @@ Nuxt uses Vite by default. If you wish to use webpack instead, refer to each pre
## Single File Components (SFC) Styling
-One of the best things about Vue and SFC is how great it is at naturally dealing with styling. You can directly write CSS or preprocessor code in the style block of your components file, therefore you will have fantastic developer experience without having to use something like CSS-in-JS. However if you wish to use CSS-in-JS, you can find 3rd party libraries and modules that support it, such as [pinceau](https://pinceau.dev).
+One of the best things about Vue and SFC is how great it is at naturally dealing with styling. You can directly write CSS or preprocessor code in the style block of your components file, therefore you will have fantastic developer experience without having to use something like CSS-in-JS. However if you wish to use CSS-in-JS, you can find 3rd party libraries and modules that support it, such as [pinceau](https://github.com/Tahul/pinceau).
You can refer to the [Vue docs](https://vuejs.org/api/sfc-css-features.html) for a comprehensive reference about styling components in SFC.
@@ -421,7 +421,7 @@ For proper syntax highlighting in SFC, you can use the postcss lang attribute.
```vue
```
@@ -430,7 +430,7 @@ By default, Nuxt comes with the following plugins already pre-configured:
- [postcss-import](https://github.com/postcss/postcss-import): Improves the `@import` rule
- [postcss-url](https://github.com/postcss/postcss-url): Transforms `url()` statements
- [autoprefixer](https://github.com/postcss/autoprefixer): Automatically adds vendor prefixes
-- [cssnano](https://cssnano.co): Minification and purge
+- [cssnano](https://cssnano.github.io/cssnano): Minification and purge
## Leveraging Layouts For Multiple Styles
@@ -458,14 +458,14 @@ Use different styles for different layouts.
Nuxt isn't opinionated when it comes to styling and provides you with a wide variety of options. You can use any styling tool that you want, such as popular libraries like [UnoCSS](https://unocss.dev) or [Tailwind CSS](https://tailwindcss.com).
-The community and the Nuxt team have developed plenty of Nuxt modules to makes the integration easier.
+The community and the Nuxt team have developed plenty of Nuxt modules to make the integration easier.
You can discover them on the [modules section](/modules) of the website.
Here are a few modules to help you get started:
- [UnoCSS](/modules/unocss): Instant on-demand atomic CSS engine
- [Tailwind CSS](/modules/tailwindcss): Utility-first CSS framework
- [Fontaine](https://github.com/nuxt-modules/fontaine): Font metric fallback
-- [Pinceau](https://pinceau.dev): Adaptable styling framework
+- [Pinceau](https://github.com/Tahul/pinceau): Adaptable styling framework
- [Nuxt UI](https://ui.nuxt.com): A UI Library for Modern Web Apps
- [Panda CSS](https://panda-css.com/docs/installation/nuxt): CSS-in-JS engine that generates atomic CSS at build time
diff --git a/docs/1.getting-started/5.seo-meta.md b/docs/1.getting-started/5.seo-meta.md
index e77839558d..a1ebb2f457 100644
--- a/docs/1.getting-started/5.seo-meta.md
+++ b/docs/1.getting-started/5.seo-meta.md
@@ -6,7 +6,7 @@ navigation.icon: i-ph-file-search-duotone
## Defaults
-Out-of-the-box, Nuxt provides sane defaults, which you can override if needed.
+Out-of-the-box, Nuxt provides sensible defaults, which you can override if needed.
```ts twoslash [nuxt.config.ts]
export default defineNuxtConfig({
@@ -174,7 +174,7 @@ You can use the `titleTemplate` option to provide a dynamic template for customi
The `titleTemplate` can either be a string, where `%s` is replaced with the title, or a function.
-If you want to use a function (for full control), then this cannot be set in your `nuxt.config`, and it is recommended instead to set it within your `app.vue` file, where it will apply to all pages on your site:
+If you want to use a function (for full control), then this cannot be set in your `nuxt.config`. It is recommended instead to set it within your `app.vue` file where it will apply to all pages on your site:
::code-group
diff --git a/docs/1.getting-started/6.data-fetching.md b/docs/1.getting-started/6.data-fetching.md
index 3e1cf5cd02..b6b52457c9 100644
--- a/docs/1.getting-started/6.data-fetching.md
+++ b/docs/1.getting-started/6.data-fetching.md
@@ -60,7 +60,7 @@ This composable is a wrapper around the [`useAsyncData`](/docs/api/composables/u
## `$fetch`
-Nuxt includes the `ofetch` library, and is auto-imported as the `$fetch` alias globally across your application. It's what `useFetch` uses behind the scenes.
+Nuxt includes the [ofetch](https://github.com/unjs/ofetch) library, and is auto-imported as the `$fetch` alias globally across your application. It's what `useFetch` uses behind the scenes.
```vue twoslash [pages/todos.vue]
+```
+
#### Watch
To re-run your fetching function each time other reactive values in your application change, use the `watch` option. You can use it for one or multiple _watchable_ elements.
diff --git a/docs/1.getting-started/7.state-management.md b/docs/1.getting-started/7.state-management.md
index 1f58ce72c5..d9edf3f161 100644
--- a/docs/1.getting-started/7.state-management.md
+++ b/docs/1.getting-started/7.state-management.md
@@ -130,12 +130,12 @@ export const useLocale = () => {
export const useDefaultLocale = (fallback = 'en-US') => {
const locale = ref(fallback)
- if (process.server) {
+ if (import.meta.server) {
const reqLocale = useRequestHeaders()['accept-language']?.split(',')[0]
if (reqLocale) {
locale.value = reqLocale
}
- } else if (process.client) {
+ } else if (import.meta.client) {
const navLang = navigator.language
if (navLang) {
locale.value = navLang
@@ -192,7 +192,6 @@ const date = useLocaleDate(new Date('2016-10-26'))
By using [auto-imported composables](/docs/guide/directory-structure/composables) we can define global type-safe states and import them across the app.
```ts twoslash [composables/states.ts]
-export const useCounter = () => useState('counter', () => 0)
export const useColor = () => useState('color', () => 'pink')
```
diff --git a/docs/1.getting-started/8.error-handling.md b/docs/1.getting-started/8.error-handling.md
index 7ede474f2f..e3b944dbc6 100644
--- a/docs/1.getting-started/8.error-handling.md
+++ b/docs/1.getting-started/8.error-handling.md
@@ -7,15 +7,15 @@ navigation.icon: i-ph-bug-beetle-duotone
Nuxt 3 is a full-stack framework, which means there are several sources of unpreventable user runtime errors that can happen in different contexts:
- Errors during the Vue rendering lifecycle (SSR & CSR)
-- Errors during Nitro server lifecycle ([`server/`](/docs/guide/directory-structure/server) directory)
- Server and client startup errors (SSR + CSR)
+- Errors during Nitro server lifecycle ([`server/`](/docs/guide/directory-structure/server) directory)
- Errors downloading JS chunks
::tip
**SSR** stands for **Server-Side Rendering** and **CSR** for **Client-Side Rendering**.
::
-## Vue Rendering Lifecycle
+## Vue Errors
You can hook into Vue errors using [`onErrorCaptured`](https://vuejs.org/api/composition-api-lifecycle.html#onerrorcaptured).
@@ -51,7 +51,7 @@ This includes:
- mounting the app (on client-side), though you should handle this case with `onErrorCaptured` or with `vue:error`
- processing the `app:mounted` hook
-## Nitro Server Lifecycle
+## Nitro Server Errors
You cannot currently define a server-side handler for these errors, but can render an error page, see the [Render an Error Page](#error-page) section.
diff --git a/docs/1.getting-started/8.server.md b/docs/1.getting-started/8.server.md
index 94e2da9e7c..49e0f21464 100644
--- a/docs/1.getting-started/8.server.md
+++ b/docs/1.getting-started/8.server.md
@@ -83,9 +83,9 @@ export default defineNuxtConfig({
Learn about all available route rules are available to customize the rendering mode of your routes.
::
-In addition, there are some route rules (for example, `ssr` and `experimentalNoScripts`) that are Nuxt specific to change the behavior when rendering your pages to HTML.
+In addition, there are some route rules (for example, `ssr`, `appMiddleware`, and `experimentalNoScripts`) that are Nuxt specific to change the behavior when rendering your pages to HTML.
-Some route rules (`redirect` and `prerender`) also affect client-side behavior.
+Some route rules (`appMiddleware`, `redirect` and `prerender`) also affect client-side behavior.
Nitro is used to build the app for server side rendering, as well as pre-rendering.
diff --git a/docs/1.getting-started/9.layers.md b/docs/1.getting-started/9.layers.md
index ed61136af1..1ae3f05d79 100644
--- a/docs/1.getting-started/9.layers.md
+++ b/docs/1.getting-started/9.layers.md
@@ -14,12 +14,13 @@ One of the core features of Nuxt 3 is the layers and extending support. You can
- Create Nuxt module presets
- Share standard setup across projects
- Create Nuxt themes
+- Enhance code organization by implementing a modular architecture and support Domain-Driven Design (DDD) pattern in large scale projects.
## Usage
You can extend a layer by adding the [extends](/docs/api/nuxt-config#extends) property to the [`nuxt.config.ts`](/docs/guide/directory-structure/nuxt-config) file.
-```ts twoslash [nuxt.config.ts]
+```ts [nuxt.config.ts]
export default defineNuxtConfig({
extends: [
'../base', // Extend from a local layer
@@ -29,6 +30,19 @@ export default defineNuxtConfig({
})
```
+You can also pass an authentication token if you are extending from a private GitHub repository:
+
+```ts [nuxt.config.ts]
+export default defineNuxtConfig({
+ extends: [
+ // per layer configuration
+ ['github:my-themes/private-awesome', { auth: process.env.GITHUB_TOKEN }]
+ ]
+})
+```
+
+Nuxt uses [unjs/c12](https://c12.unjs.io) and [unjs/giget](https://giget.unjs.io) for extending remote layers. Check the documentation for more information and all available options.
+
::read-more{to="/docs/guide/going-further/layers"}
Read more about layers in the **Layer Author Guide**.
::
diff --git a/docs/2.guide/1.concepts/1.auto-imports.md b/docs/2.guide/1.concepts/1.auto-imports.md
index b26265d3c6..0fd8a3b63f 100644
--- a/docs/2.guide/1.concepts/1.auto-imports.md
+++ b/docs/2.guide/1.concepts/1.auto-imports.md
@@ -84,7 +84,7 @@ export const useMyComposable = () => {
```ts twoslash [composables/example.ts]
export const useMyComposable = () => {
// Because your composable is called in the right place in the lifecycle,
- // useRuntimeConfig will also work
+ // useRuntimeConfig will work here
const config = useRuntimeConfig()
// ...
diff --git a/docs/2.guide/1.concepts/3.rendering.md b/docs/2.guide/1.concepts/3.rendering.md
index 3c4fa6ca56..4adf1baaab 100644
--- a/docs/2.guide/1.concepts/3.rendering.md
+++ b/docs/2.guide/1.concepts/3.rendering.md
@@ -109,10 +109,11 @@ The different properties you can use are the following:
- `ssr: boolean`{lang=ts} - Disables server-side rendering for sections of your app and make them SPA-only with `ssr: false`
- `cors: boolean`{lang=ts} - Automatically adds cors headers with `cors: true` - you can customize the output by overriding with `headers`
- `headers: object`{lang=ts} - Add specific headers to sections of your site - for example, your assets
-- `swr: number|boolean`{lang=ts} - Add cache headers to the server response and cache it on the server or reverse proxy for a configurable TTL (time to live). The `node-server` preset of Nitro is able to cache the full response. When the TTL expired, the cached response will be sent while the page will be regenerated in the background. If true is used, a `stale-while-revalidate` header is added without a MaxAge.
-- `isr: number|boolean`{lang=ts} - The behavior is the same as `swr` except that we are able to add the response to the CDN cache on platforms that support this (currently Netlify or Vercel). If `true` is used, the content persists until the next deploy inside the CDN.
-- `prerender:boolean`{lang=ts} - Prerenders routes at build time and includes them in your build as static assets
+- `swr: number | boolean`{lang=ts} - Add cache headers to the server response and cache it on the server or reverse proxy for a configurable TTL (time to live). The `node-server` preset of Nitro is able to cache the full response. When the TTL expired, the cached response will be sent while the page will be regenerated in the background. If true is used, a `stale-while-revalidate` header is added without a MaxAge.
+- `isr: number | boolean`{lang=ts} - The behavior is the same as `swr` except that we are able to add the response to the CDN cache on platforms that support this (currently Netlify or Vercel). If `true` is used, the content persists until the next deploy inside the CDN.
+- `prerender: boolean`{lang=ts} - Prerenders routes at build time and includes them in your build as static assets
- `experimentalNoScripts: boolean`{lang=ts} - Disables rendering of Nuxt scripts and JS resource hints for sections of your site.
+- `appMiddleware: string | string[] | Record`{lang=ts} - Allows you to define middleware that should or should not run for page paths within the Vue app part of your application (that is, not your Nitro routes)
Whenever possible, route rules will be automatically applied to the deployment platform's native rules for optimal performances (Netlify and Vercel are currently supported).
diff --git a/docs/2.guide/1.concepts/8.typescript.md b/docs/2.guide/1.concepts/8.typescript.md
index e2718dc55f..afc7ae5a05 100644
--- a/docs/2.guide/1.concepts/8.typescript.md
+++ b/docs/2.guide/1.concepts/8.typescript.md
@@ -9,22 +9,26 @@ 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:
+::alert{type="warning"}
+You may experience issues with the latest `vue-tsc` and `vite-plugin-checker`, used internally when type checking. For now, you may need to stay on v1 of `vue-tsc`, and follow these upstream issues for updates: [fi3ework/vite-plugin-checker#306](https://github.com/fi3ework/vite-plugin-checker/issues/306) and [vuejs/language-tools#3969](https://github.com/vuejs/language-tools/issues/3969).
+::
+
::code-group
```bash [yarn]
- yarn add --dev vue-tsc typescript
+ yarn add --dev vue-tsc@^1 typescript
```
```bash [npm]
- npm install --save-dev vue-tsc typescript
+ npm install --save-dev vue-tsc@^1 typescript
```
```bash [pnpm]
- pnpm add -D vue-tsc typescript
+ pnpm add -D vue-tsc@^1 typescript
```
```bash [bun]
- bun add -D vue-tsc typescript
+ bun add -D vue-tsc@^1 typescript
```
::
diff --git a/docs/2.guide/2.directory-structure/1.components.md b/docs/2.guide/2.directory-structure/1.components.md
index 929d2b6a42..0685a3389c 100644
--- a/docs/2.guide/2.directory-structure/1.components.md
+++ b/docs/2.guide/2.directory-structure/1.components.md
@@ -244,6 +244,10 @@ This feature only works with Nuxt auto-imports and `#components` imports. Explic
`.client` components are rendered only after being mounted. To access the rendered template using `onMounted()`, add `await nextTick()` in the callback of the `onMounted()` hook.
::
+::read-more{to="/docs/api/components/client-only"}
+You can also achieve a similar result with the `` component.
+::
+
## Server Components
Server components allow server-rendering individual components within your client-side apps. It's possible to use server components within Nuxt, even if you are generating a static site. That makes it possible to build complex sites that mix dynamic components, server-rendered HTML and even static chunks of markup.
@@ -295,6 +299,14 @@ Now you can register server-only components with the `.server` suffix and use th
Server-only components use [``](/docs/api/components/nuxt-island) under the hood, meaning that `lazy` prop and `#fallback` slot are both passed down to it.
+::alert{type=warning}
+Server components (and islands) must have a single root element. (HTML comments are considered elements as well.)
+::
+
+::alert{type=warning}
+Most features for server-only components and island components, such as slots and client components, are only available for single file components.
+::
+
#### Client components within server components
::alert{type=info}
@@ -314,7 +326,7 @@ You can partially hydrate a component by setting a `nuxt-client` attribute on th
```
::alert{type=info}
-This only works within a server component.Β Slots for client components are not available yet.
+This only works within a server component.Β Slots for client components are working only with `experimental.componentIsland.selectiveClient` set to `'deep'` and since they are rendered server-side, they are not interactive once client-side.
::
#### Server Component Context
@@ -353,89 +365,12 @@ In this case, the `.server` + `.client` components are two 'halves' of a compone
```
-## `` Component
+## Built-In Nuxt Components
-Nuxt provides the [``](/docs/api/components/client-only) component for purposely rendering a component only on client side.
+There are a number of components that Nuxt provides, including `` and ``. You can read more about them in the API documentation.
-```vue [pages/example.vue]
-
-
-
-
-
-
-
-
-
-```
-
-Use a slot as fallback until `` is mounted on client side.
-
-```vue [pages/example.vue]
-
-
-
-
-
-
-
-
-
-
Loading comments...
-
-
-
-
-```
-
-
-
-
-## `` Component
-
-Nuxt provides the `` component to render a component only during development.
-
-The content will not be included in production builds and tree-shaken.
-
-```vue [pages/example.vue]
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-```
-
-## `` Component
-
-Nuxt provides the `` component to render its content on the client if any of its children trigger an error in SSR.
-You can specify a `fallbackTag` to make it render a specific tag if it fails to render on the server.
-
-```vue [pages/example.vue]
-
-
-
-
-
-
-
-
-
-
-```
## Library Authors
diff --git a/docs/2.guide/2.directory-structure/1.middleware.md b/docs/2.guide/2.directory-structure/1.middleware.md
index 22c63eb24a..e4e97484d3 100644
--- a/docs/2.guide/2.directory-structure/1.middleware.md
+++ b/docs/2.guide/2.directory-structure/1.middleware.md
@@ -125,12 +125,12 @@ However, if you want to avoid this behaviour you can do so:
```ts twoslash [middleware/example.ts]
export default defineNuxtRouteMiddleware(to => {
// skip middleware on server
- if (process.server) return
+ if (import.meta.server) return
// skip middleware on client side entirely
- if (process.client) return
+ if (import.meta.client) return
// or only skip middleware on initial client load
const nuxtApp = useNuxtApp()
- if (process.client && nuxtApp.isHydrating && nuxtApp.payload.serverRendered) return
+ if (import.meta.client && nuxtApp.isHydrating && nuxtApp.payload.serverRendered) return
})
```
diff --git a/docs/2.guide/2.directory-structure/1.modules.md b/docs/2.guide/2.directory-structure/1.modules.md
index b98df654e6..2664e5601e 100644
--- a/docs/2.guide/2.directory-structure/1.modules.md
+++ b/docs/2.guide/2.directory-structure/1.modules.md
@@ -56,3 +56,7 @@ modules/
```
:read-more{to="/docs/guide/going-further/modules"}
+
+::tip{icon="i-ph-video-duotone" to="https://vueschool.io/lessons/creating-your-first-module-from-scratch" target="_blank"}
+Watch Vue School video about Nuxt private modules.
+::
diff --git a/docs/2.guide/2.directory-structure/1.pages.md b/docs/2.guide/2.directory-structure/1.pages.md
index 2332295f8a..6ebd687bb1 100644
--- a/docs/2.guide/2.directory-structure/1.pages.md
+++ b/docs/2.guide/2.directory-structure/1.pages.md
@@ -57,7 +57,7 @@ If you are using [`app.vue`](/docs/guide/directory-structure/app), make sure to
```
-Pages **must have a single root element** to allow [route transitions](/docs/getting-started/transitions) between pages, HTML comments are considered elements as well.
+Pages **must have a single root element** to allow [route transitions](/docs/getting-started/transitions) between pages. HTML comments are considered elements as well.
This means that when the route is server-rendered, or statically generated, you will be able to see its contents correctly, but when you navigate towards that route during client-side navigation the transition between routes will fail and you'll see that the route will not be rendered.
@@ -357,12 +357,16 @@ function navigate(){
```
+## Client-Only Pages
+
+You can define a page as [client only](/docs/guide/directory-structure/components#client-components) by giving it a `.client.vue` suffix. None of the content of this page will be rendered on the server.
+
## Server-Only Pages
You can define a page as [server only](/docs/guide/directory-structure/components#server-components) by giving it a `.server.vue` suffix. While you will be able to navigate to the page using client-side navigation, controlled by `vue-router`, it will be rendered with a server component automatically, meaning the code required to render the page will not be in your client-side bundle.
-::note
-You will also need to enable `experimental.componentIslands` in order to make this possible.
+::alert{type=warning}
+Server-only pages must have a single root element. (HTML comments are considered elements as well.)
::
## Custom Routing
diff --git a/docs/2.guide/2.directory-structure/1.plugins.md b/docs/2.guide/2.directory-structure/1.plugins.md
index 995e6212d1..4de600585d 100644
--- a/docs/2.guide/2.directory-structure/1.plugins.md
+++ b/docs/2.guide/2.directory-structure/1.plugins.md
@@ -78,7 +78,7 @@ export default defineNuxtPlugin({
::note
If you are using the object-syntax, the properties may be statically analyzed in future to produce a more optimized build. So you should not define them at runtime. :br
-For example, setting `enforce: process.server ? 'pre' : 'post'` would defeat any future optimization Nuxt is able to do for your plugins.
+For example, setting `enforce: import.meta.server ? 'pre' : 'post'` would defeat any future optimization Nuxt is able to do for your plugins.
::
## Registration Order
diff --git a/docs/2.guide/2.directory-structure/3.app-config.md b/docs/2.guide/2.directory-structure/3.app-config.md
index d8eb2ce4be..93c15381f8 100644
--- a/docs/2.guide/2.directory-structure/3.app-config.md
+++ b/docs/2.guide/2.directory-structure/3.app-config.md
@@ -99,7 +99,7 @@ Nuxt uses a custom merging strategy for the `AppConfig` within [the layers](/doc
This strategy is implemented using a [Function Merger](https://github.com/unjs/defu#function-merger), which allows defining a custom merging strategy for every key in `app.config` that has an array as value.
::note
-The Function Merger should only be used in the base `app.config` of your application.
+The function merger can only be used in the extended layers and not the main `app.config` in project.
::
Here's an example of how you can use:
diff --git a/docs/2.guide/3.going-further/10.runtime-config.md b/docs/2.guide/3.going-further/10.runtime-config.md
index f4ca19cd94..e84823704c 100644
--- a/docs/2.guide/3.going-further/10.runtime-config.md
+++ b/docs/2.guide/3.going-further/10.runtime-config.md
@@ -98,7 +98,7 @@ The behavior is different between the client-side and server-side:
const config = useRuntimeConfig()
console.log('Runtime config:', config)
-if (process.server) {
+if (import.meta.server) {
console.log('API secret:', config.apiSecret)
}
@@ -164,3 +164,7 @@ declare module 'nuxt/schema' {
// It is always important to ensure you import/export something when augmenting a type
export {}
```
+
+::note
+`nuxt/schema` is provided as a convenience for end-users to access the version of the schema used by Nuxt in their project. Module authors should instead augment `@nuxt/schema`.
+::
diff --git a/docs/2.guide/3.going-further/3.modules.md b/docs/2.guide/3.going-further/3.modules.md
index f7eae0f03f..3eb0d0d424 100644
--- a/docs/2.guide/3.going-further/3.modules.md
+++ b/docs/2.guide/3.going-further/3.modules.md
@@ -30,6 +30,10 @@ This will create a `my-module` project with all the boilerplate necessary to dev
Learn how to perform basic tasks with the module starter.
+::tip{icon="i-ph-video-duotone" to="https://vueschool.io/lessons/navigating-the-official-starter-template" target="_blank"}
+Watch Vue School video about Nuxt module starter template.
+::
+
#### How to Develop
While your module source code lives inside the `src` directory, in most cases, to develop a module, you need a Nuxt application. That's what the `playground` directory is about. It's a Nuxt application you can tinker with that is already configured to run with your module.
@@ -255,6 +259,10 @@ export default defineNuxtModule({
When you need to handle more complex configuration alterations, you should consider using [defu](https://github.com/unjs/defu).
+::tip{icon="i-ph-video-duotone" to="https://vueschool.io/lessons/extending-and-altering-nuxt-configuration-and-options" target="_blank"}
+Watch Vue School video about altering Nuxt configuration.
+::
+
#### Exposing Options to Runtime
Because modules aren't part of the application runtime, their options aren't either. However, in many cases, you might need access to some of these module options within your runtime code. We recommend exposing the needed config using Nuxt's [`runtimeConfig`](/docs/api/nuxt-config#runtimeconfig).
@@ -288,6 +296,10 @@ Be careful not to expose any sensitive module configuration on the public runtim
:read-more{to="/docs/guide/going-further/runtime-config"}
+::tip{icon="i-ph-video-duotone" to="https://vueschool.io/lessons/passing-and-exposing-module-options" target="_blank"}
+Watch Vue School video about passing and exposing Nuxt module options.
+::
+
#### Injecting Plugins With `addPlugin`
Plugins are a common way for a module to add runtime logic. You can use the `addPlugin` utility to register them from your module.
@@ -511,6 +523,10 @@ export default defineNuxtModule({
:read-more{to="/docs/api/advanced/hooks"}
+::tip{icon="i-ph-video-duotone" to="https://vueschool.io/lessons/nuxt-lifecycle-hooks" target="_blank"}
+Watch Vue School video about using Nuxt lifecycle hooks in modules.
+::
+
::note
**Module cleanup**
:br
@@ -733,6 +749,10 @@ The module starter comes with a default set of tools and configurations (e.g. ES
[Nuxt Module ecosystem](/modules) represents more than 15 million monthly NPM downloads and provides extended functionalities and integrations with all sort of tools. You can be part of this ecosystem!
+::tip{icon="i-ph-video-duotone" to="https://vueschool.io/lessons/exploring-nuxt-modules-ecosystem-and-module-types" target="_blank"}
+Watch Vue School video about Nuxt module types.
+::
+
### Module Types
**Official modules** are modules prefixed (scoped) with `@nuxt/` (e.g. [`@nuxt/content`](https://content.nuxtjs.org)). They are made and maintained actively by the Nuxt team. Like with the framework, contributions from the community are more than welcome to help make them better!
diff --git a/docs/2.guide/3.going-further/8.custom-routing.md b/docs/2.guide/3.going-further/8.custom-routing.md
index b8f39b048d..b3e408c2a3 100644
--- a/docs/2.guide/3.going-further/8.custom-routing.md
+++ b/docs/2.guide/3.going-further/8.custom-routing.md
@@ -105,7 +105,7 @@ export default defineNuxtConfig({
const resolver = createResolver(import.meta.url)
// add a route
files.push({
- path: resolver.resolve('./runtime/app/router-options')
+ path: resolver.resolve('./runtime/app/router-options'),
optional: true
})
}
@@ -172,6 +172,6 @@ import { createMemoryHistory } from 'vue-router'
export default {
// https://router.vuejs.org/api/interfaces/routeroptions.html
- history: base => process.client ? createMemoryHistory(base) : null /* default */
+ history: base => import.meta.client ? createMemoryHistory(base) : null /* default */
}
```
diff --git a/docs/2.guide/3.going-further/9.debugging.md b/docs/2.guide/3.going-further/9.debugging.md
index 0771c6d959..59558ba67d 100644
--- a/docs/2.guide/3.going-further/9.debugging.md
+++ b/docs/2.guide/3.going-further/9.debugging.md
@@ -38,6 +38,10 @@ It is possible to debug your Nuxt app in your IDE while you are developing it.
You may need to update the config below with a path to your web browser. For more information, visit the [VS Code documentation about debug configuration](https://go.microsoft.com/fwlink/?linkid=830387).
+::important
+If you use `pnpm`, you will need to have `nuxi` installed as a devDependency for the configuration below to work.
+::
+
```json5
{
// Use IntelliSense to learn about possible attributes.
diff --git a/docs/3.api/1.components/1.client-only.md b/docs/3.api/1.components/1.client-only.md
index 481ab8ab9c..86e56d2547 100644
--- a/docs/3.api/1.components/1.client-only.md
+++ b/docs/3.api/1.components/1.client-only.md
@@ -8,7 +8,11 @@ links:
size: xs
---
-The `` component renders its slot only in client-side. To import a component only on the client, register the component in a client-side only plugin.
+The `` component is used for purposely rendering a component only on client side.
+
+::note
+The content of the default slot will be tree-shaken out of the server build. (This does mean that any CSS used by components within it may not be inlined when rendering the initial HTML.)
+::
## Props
@@ -19,6 +23,7 @@ The `` component renders its slot only in client-side. To import a c
+
@@ -28,14 +33,16 @@ The `` component renders its slot only in client-side. To import a c
## Slots
-- `#fallback`: specify a content to be displayed server-side.
+- `#fallback`: specify a content to be rendered on the server and displayed until `` is mounted in the browser.
-```vue
+```vue [pages/example.vue]
-
-
+
+
+
+
Loading comments...
diff --git a/docs/3.api/1.components/1.dev-only.md b/docs/3.api/1.components/1.dev-only.md
new file mode 100644
index 0000000000..a65b5cbc56
--- /dev/null
+++ b/docs/3.api/1.components/1.dev-only.md
@@ -0,0 +1,51 @@
+---
+title: ''
+description: Render components only during development with the component.
+links:
+ - label: Source
+ icon: i-simple-icons-github
+ to: https://github.com/nuxt/nuxt/blob/main/packages/nuxt/src/app/components/dev-only.ts
+ size: xs
+---
+
+Nuxt provides the `` component to render a component only during development.
+
+The content will not be included in production builds.
+
+```vue [pages/example.vue]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+## Slots
+
+- `#fallback`: if you ever require to have a replacement during production.
+
+```vue
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
diff --git a/docs/3.api/1.components/1.nuxt-client-fallback.md b/docs/3.api/1.components/1.nuxt-client-fallback.md
index 1f07dd09fa..22d9d6b6f0 100644
--- a/docs/3.api/1.components/1.nuxt-client-fallback.md
+++ b/docs/3.api/1.components/1.nuxt-client-fallback.md
@@ -12,10 +12,25 @@ links:
size: xs
---
+Nuxt provides the `` component to render its content on the client if any of its children trigger an error in SSR.
+
::note{to="/docs/guide/going-further/experimental-features#clientfallback"}
This component is experimental and in order to use it you must enable the `experimental.clientFallback` option in your `nuxt.config`.
::
+```vue [pages/example.vue]
+
+
+
+
+
+
+
+
+
+
+```
+
## Events
- `@ssr-error`: Event emitted when a child triggers an error in SSR. Note that this will only be triggered on the server.
@@ -30,7 +45,7 @@ This component is experimental and in order to use it you must enable the `exper
## Props
-- `placeholderTag` | `fallbackTag`: Specify a fallback tag to be rendered if the slot fails to render.
+- `placeholderTag` | `fallbackTag`: Specify a fallback tag to be rendered if the slot fails to render on the server.
- **type**: `string`
- **default**: `div`
- `placeholder` | `fallback`: Specify fallback content to be rendered if the slot fails to render.
diff --git a/docs/3.api/1.components/3.nuxt-layout.md b/docs/3.api/1.components/3.nuxt-layout.md
index cc8bf04191..1ff8168ade 100644
--- a/docs/3.api/1.components/3.nuxt-layout.md
+++ b/docs/3.api/1.components/3.nuxt-layout.md
@@ -55,6 +55,10 @@ Please note the layout name is normalized to kebab-case, so if your layout file
Read more about dynamic layouts.
::
+- `fallback`: If an invalid layout is passed to the `name` prop, no layout will be rendered. Specify a `fallback` layout to be rendered in this scenario. It **must** match the name of the corresponding layout file in the [`layouts/`](/docs/guide/directory-structure/layouts) directory.
+ - **type**: `string`
+ - **default**: `null`
+
## Additional Props
`NuxtLayout` also accepts any additional props that you may need to pass to the layout. These custom props are then made accessible as attributes.
@@ -83,6 +87,8 @@ console.log(layoutCustomProps.title) // I am a custom layout
`` renders incoming content via ``, which is then wrapped around Vueβs `` component to activate layout transition. For this to work as expected, it is recommended that `` is **not** the root element of the page component.
+::code-group
+
```vue [pages/index.vue]
@@ -93,13 +99,27 @@ console.log(layoutCustomProps.title) // I am a custom layout
```
+```vue [layouts/custom.vue]
+
+
+
+
+
+
+
+```
+
+::
+
:read-more{to="/docs/getting-started/transitions"}
## Layout's Ref
To get the ref of a layout component, access it through `ref.value.layoutRef`.
-````vue [app.vue]
+::code-group
+
+```vue [app.vue]
-
+
+ default layout
+
-````
+```
+
+```vue [layouts/default.vue]
+
+
+
+
+ default layout
+
+
+
+```
+
+::
:read-more{to="/docs/guide/directory-structure/layouts"}
diff --git a/docs/3.api/1.components/8.nuxt-island.md b/docs/3.api/1.components/8.nuxt-island.md
index a7c3dfc99f..cd715534f2 100644
--- a/docs/3.api/1.components/8.nuxt-island.md
+++ b/docs/3.api/1.components/8.nuxt-island.md
@@ -12,10 +12,6 @@ When rendering an island component, the content of the island component is stati
Changing the island component props triggers a refetch of the island component to re-render it again.
-::read-more{to="/docs/guide/going-further/experimental-features#componentislands" icon="i-ph-star-duotone"}
-This component is experimental and in order to use it you must enable the `experimental.componentIslands` option in your `nuxt.config`.
-::
-
::note
Global styles of your application are sent with the response.
::
@@ -60,3 +56,11 @@ Some slots are reserved to `NuxtIsland` for special cases.
- `refresh()`
- **type**: `() => Promise`
- **description**: force refetch the server component by refetching it.
+
+## Events
+
+- `error`
+ - **parameters**:
+ - **error**:
+ - **type**: `unknown`
+ - **description**: emitted when when `NuxtIsland` fails to fetch the new island.
diff --git a/docs/3.api/2.composables/use-async-data.md b/docs/3.api/2.composables/use-async-data.md
index 43b2bc4e24..da3cb8f39c 100644
--- a/docs/3.api/2.composables/use-async-data.md
+++ b/docs/3.api/2.composables/use-async-data.md
@@ -119,10 +119,10 @@ type AsyncDataOptions = {
deep?: boolean
dedupe?: 'cancel' | 'defer'
default?: () => DataT | Ref | null
- transform?: (input: DataT) => DataT
+ transform?: (input: DataT) => DataT | Promise
pick?: string[]
watch?: WatchSource[]
- getCachedData?: (key: string) => DataT
+ getCachedData?: (key: string, nuxtApp: NuxtApp) => DataT
}
type AsyncData = {
@@ -130,6 +130,7 @@ type AsyncData = {
pending: Ref
refresh: (opts?: AsyncDataExecuteOptions) => Promise
execute: (opts?: AsyncDataExecuteOptions) => Promise
+ clear: () => void
error: Ref
status: Ref
};
diff --git a/docs/3.api/2.composables/use-fetch.md b/docs/3.api/2.composables/use-fetch.md
index 96bfa3850e..bd4d30d647 100644
--- a/docs/3.api/2.composables/use-fetch.md
+++ b/docs/3.api/2.composables/use-fetch.md
@@ -144,11 +144,11 @@ type UseFetchOptions = {
server?: boolean
lazy?: boolean
immediate?: boolean
- getCachedData?: (key: string) => DataT
+ getCachedData?: (key: string, nuxtApp: NuxtApp) => DataT
deep?: boolean
dedupe?: 'cancel' | 'defer'
default?: () => DataT
- transform?: (input: DataT) => DataT
+ transform?: (input: DataT) => DataT | Promise
pick?: string[]
watch?: WatchSource[] | false
}
@@ -158,6 +158,7 @@ type AsyncData = {
pending: Ref
refresh: (opts?: AsyncDataExecuteOptions) => Promise
execute: (opts?: AsyncDataExecuteOptions) => Promise
+ clear: () => void
error: Ref
status: Ref
}
diff --git a/docs/3.api/2.composables/use-id.md b/docs/3.api/2.composables/use-id.md
index 9cd649696b..ecadfa8f94 100644
--- a/docs/3.api/2.composables/use-id.md
+++ b/docs/3.api/2.composables/use-id.md
@@ -4,7 +4,7 @@ description: Generate an SSR-friendly unique identifier that can be passed to ac
---
::important
-This composable is available since [Nuxt v3.10](/v3-10#ssr-safe-accessible-unique-id-creation).
+This composable is available since [Nuxt v3.10](/blog/v3-10#ssr-safe-accessible-unique-id-creation).
::
`useId` generates an SSR-friendly unique identifier that can be passed to accessibility attributes.
@@ -19,11 +19,15 @@ const id = useId()
-
+
```
+::note
+`useId` must be used in a component with a single root element, as it uses this root element's attributes to pass the id from server to client.
+::
+
## Parameters
`useId` does not take any parameters.
diff --git a/docs/3.api/2.composables/use-loading-indicator.md b/docs/3.api/2.composables/use-loading-indicator.md
index a451518d71..2e4a5bb97b 100644
--- a/docs/3.api/2.composables/use-loading-indicator.md
+++ b/docs/3.api/2.composables/use-loading-indicator.md
@@ -39,7 +39,7 @@ Set `isLoading` to true and start to increase the `progress` value.
### `finish()`
-Set the `progress` value to `100`, stop all timers and intervals then reset the loading state `500` ms later.
+Set the `progress` value to `100`, stop all timers and intervals then reset the loading state `500` ms later. `finish` accepts a `{ force: true }` option to skip the interval before the state is reset.
### `clear()`
diff --git a/docs/3.api/2.composables/use-nuxt-app.md b/docs/3.api/2.composables/use-nuxt-app.md
index 20fcefccd7..29a920cdb1 100644
--- a/docs/3.api/2.composables/use-nuxt-app.md
+++ b/docs/3.api/2.composables/use-nuxt-app.md
@@ -51,7 +51,7 @@ export default defineNuxtPlugin((nuxtApp) => {
})
nuxtApp.hook('vue:error', (..._args) => {
console.log('vue:error')
- // if (process.client) {
+ // if (import.meta.client) {
// console.log(..._args)
// }
})
@@ -120,7 +120,7 @@ Nuxt exposes the following properties through `ssrContext`:
export const useColor = () => useState('color', () => 'pink')
export default defineNuxtPlugin((nuxtApp) => {
- if (process.server) {
+ if (import.meta.server) {
const color = useColor()
}
})
@@ -128,9 +128,9 @@ Nuxt exposes the following properties through `ssrContext`:
It is also possible to use more advanced types, such as `ref`, `reactive`, `shallowRef`, `shallowReactive` and `NuxtError`.
- Since [Nuxt v3.4](https://nuxt.com/blog/v3-4#payload-enhancements), it is possible to define your own serializer/deserializer for types that are not supported by Nuxt.
+ Since [Nuxt v3.4](https://nuxt.com/blog/v3-4#payload-enhancements), it is possible to define your own reducer/reviver for types that are not supported by Nuxt.
- In the example below, we define a serializer for the [Luxon](https://moment.github.io/luxon/#/) DateTime class.
+ In the example below, we define a reducer (or a serializer) and a reviver (or deserializer) for the [Luxon](https://moment.github.io/luxon/#/) DateTime class, using a payload plugin.
```ts [plugins/date-time-payload.ts]
/**
@@ -159,7 +159,7 @@ export default defineComponent({
setup (_props, { slots, emit }) {
const nuxtApp = useNuxtApp()
onErrorCaptured((err) => {
- if (process.client && !nuxtApp.isHydrating) {
+ if (import.meta.client && !nuxtApp.isHydrating) {
// ...
}
})
diff --git a/docs/3.api/2.composables/use-preview-mode.md b/docs/3.api/2.composables/use-preview-mode.md
new file mode 100644
index 0000000000..360350f19e
--- /dev/null
+++ b/docs/3.api/2.composables/use-preview-mode.md
@@ -0,0 +1,82 @@
+---
+title: "usePreviewMode"
+description: "Use usePreviewMode to check and control preview mode in Nuxt"
+---
+
+# `usePreviewMode`
+
+You can use the built-in `usePreviewMode` composable to access and control preview state in Nuxt. If the composable detects preview mode it will automatically force any updates necessary for [`useAsyncData`](/docs/api/composables/use-async-data) and [`useFetch`](/docs/api/composables/use-fetch) to rerender preview content.
+
+```js
+const { enabled, state } = usePreviewMode()
+```
+
+## Options
+
+### Custom `enable` check
+
+You can specify a custom way to enable preview mode. By default the `usePreviewMode` composable will enable preview mode if there is a `preview` param in url that is equal to `true` (for example, `http://localhost:3000?preview=true`). You can wrap the `usePreviewMode` into custom composable, to keep options consistent across usages and prevent any errors.
+
+```js
+export function useMyPreviewMode () {
+ return usePreviewMode({
+ shouldEnable: () => {
+ return !!route.query.customPreview
+ }
+ });
+}
+```
+
+### Modify default state
+
+`usePreviewMode` will try to store the value of a `token` param from url in state. You can modify this state and it will be available for all [`usePreviewMode`](/docs/api/composables/use-preview-mode) calls.
+
+```js
+const data1 = ref('data1')
+
+const { enabled, state } = usePreviewMode({
+ getState: (currentState) => {
+ return { data1, data2: 'data2' }
+ }
+})
+```
+
+::note
+The `getState` function will append returned values to current state, so be careful not to accidentally overwrite important state.
+::
+
+## Example
+
+```vue [pages/some-page.vue]
+
+
+
+