Merge branch 'main' into docs/kit

This commit is contained in:
Andrey Yolkin 2023-08-29 15:45:27 +03:00 committed by GitHub
commit 5048c576a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 903 additions and 658 deletions

View File

@ -134,6 +134,10 @@ if (route.params.group === 'admins' && !route.params.id) {
</script>
```
::alert{type="info"}
Named parent routes will take priority over nested dynamic routes. For the `/foo/hello` route, `~/pages/foo.vue` will take priority over `~/pages/foo/[slug].vue` . Use `~/pages/foo/index.vue` and `~/pages/foo/[slug].vue` to match `/foo` and `/foo/hello` with different pages,.
::
## Catch-all Route
If you need a catch-all route, you create it by using a file named like `[...slug].vue`. This will match _all_ routes under that path.

View File

@ -1,6 +1,6 @@
# Overview
Experience Nuxt 3 features on existing Nuxt 2 projects.
Reduce the differences with Nuxt 3 and reduce the burden of migration to Nuxt 3.
::alert
If you're starting a fresh Nuxt 3 project, please skip this section and go to [Nuxt 3 Installation](/docs/getting-started/introduction).
@ -12,9 +12,11 @@ Nuxt Bridge provides identical features to Nuxt 3 ([docs](/docs/guide/concepts/a
Bridge is a forward-compatibility layer that allows you to experience many of the new Nuxt 3 features by simply installing and enabling a Nuxt module.
Using Nuxt Bridge, you can make sure your project is (almost) ready for Nuxt 3 and have the best developer experience without needing a major rewrite or risk breaking changes.
Using Nuxt Bridge, you can make sure your project is (almost) ready for Nuxt 3 and you can gradually proceed with the transition to Nuxt 3.
## Upgrade Nuxt 2
## First Step
### Upgrade Nuxt 2
Make sure your dev server (`nuxt dev`) isn't running, remove any package lock files (`package-lock.json` and `yarn.lock`), and install the latest Nuxt 2 version:
@ -41,7 +43,7 @@ npm install
Once the installation is complete, make sure both development and production builds are working as expected before proceeding.
::
## Install Nuxt Bridge
### Install Nuxt Bridge
Install `@nuxt/bridge-edge` as a development dependency:
@ -57,57 +59,7 @@ npm install -D @nuxt/bridge@npm:@nuxt/bridge-edge
::
## Update Your Scripts
You will also need to update your scripts within your `package.json` to reflect the fact that Nuxt will now produce a Nitro server as build output.
### Nuxi
Nuxt 3 introduced the new Nuxt CLI command [`nuxi`](/docs/api/commands/add). Update your scripts as follows to leverage the better support from Nuxt Bridge:
```diff
{
"scripts": {
- "dev": "nuxt",
+ "dev": "nuxi dev",
- "build": "nuxt build",
+ "build": "nuxi build",
- "start": "nuxt start",
+ "start": "nuxi preview"
}
}
```
::alert
If `nitro: false`, use the `nuxt` command.
::
### Static Target
If you have set `target: 'static'` in your `nuxt.config` then you need to ensure that you update your build script to be `nuxi generate`.
```json [package.json]
{
"scripts": {
"build": "nuxi generate"
}
}
```
### Server Target
For all other situations, you can use the `nuxi build` command.
```json [package.json]
{
"scripts": {
"build": "nuxi build",
"start": "nuxi preview"
}
}
```
## Update `nuxt.config`
### Update `nuxt.config`
Please make sure to avoid any CommonJS syntax such as `module.exports`, `require` or `require.resolve` in your config file. It will soon be deprecated and unsupported.
@ -117,227 +69,35 @@ You can use static `import`, dynamic `import()` and `export default` instead. Us
import { defineNuxtConfig } from '@nuxt/bridge'
export default defineNuxtConfig({
// Your existing configuration
bridge: false
})
```
## Update `tsconfig.json`
Try running `nuxt dev` once here. You will see that the application works as before.
If you are using TypeScript, you can edit your `tsconfig.json` to benefit from auto-generated Nuxt types:
(If 'bridge' is set to false, your application will operate without any changes as before.)
```diff [tsconfig.json]
{
+ "extends": "./.nuxt/tsconfig.json",
"compilerOptions": {
...
}
}
```
## Upgrade Steps
::alert
As `.nuxt/tsconfig.json` is generated and not checked into version control, you'll need to generate that file before running your tests. Add `nuxi prepare` as a step before your tests, otherwise you'll see `TS5083: Cannot read file '~/.nuxt/tsconfig.json'`
::
::alert
You may also need to add `@vue/runtime-dom` as a devDependency if you are struggling to get template type inference working with [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar).
::
::alert
Keep in mind that all options extended from `./.nuxt/tsconfig.json` will be overwritten by the options defined in your `tsconfig.json`.
Overwriting options such as `"compilerOptions.paths"` with your own configuration will lead TypeScript to not factor in the module resolutions from `./.nuxt/tsconfig.json`. This can lead to module resolutions such as `#imports` not being recognized.
With Nuxt Bridge, the migration to Nuxt 3 can proceed in steps.
The below `Upgrade Steps` does not need to be done all at once.
In case you need to extend options provided by `./.nuxt/tsconfig.json` further, you can use the `alias` property within your `nuxt.config`. `nuxi` will pick them up and extend `./.nuxt/tsconfig.json` accordingly.
::
- [TypeScript](/docs/bridge/typescript)
## Update Runtime Config
- [Migrate Legacy Composition API](/docs/bridge/bridge-composition-api)
Nuxt 3 approaches runtime config differently than Nuxt 2, using a new combined `runtimeConfig` option.
- [Plugins and Middleware](/docs/bridge/plugins-and-middleware)
First, you'll need to combine your `publicRuntimeConfig` and `privateRuntimeConfig` properties into a new one called `runtimeConfig`, with the public config within a key called `public`.
- [Migrate New Composition API](/docs/bridge/nuxt3-compatible-api)
```diff
// nuxt.config.js
- privateRuntimeConfig: {
- apiKey: process.env.NUXT_API_KEY || 'super-secret-key'
- },
- publicRuntimeConfig: {
- websiteURL: 'https://public-data.com'
- }
+ runtimeConfig: {
+ apiKey: process.env.NUXT_API_KEY || 'super-secret-key',
+ public: {
+ websiteURL: 'https://public-data.com'
+ }
+ }
```
- [Meta Tags](/docs/bridge/meta)
This also means that when you need to access public runtime config, it's behind a property called `public`. If you use public runtime config, you'll need to update your code.
- [Runtime Config](/docs/bridge/runtime-config)
```diff
// MyWidget.vue
- <div>Website: {{ $config.websiteURL }}</div>
+ <div>Website: {{ $config.public.websiteURL }}</div>
```
- [Nitro](/docs/bridge/nitro)
## Migrate Composition API
- [Vite](/docs/bridge/vite)
If you were using `@vue/composition-api` or `@nuxtjs/composition-api`, please read the [composition api migration guide](/docs/bridge/bridge-composition-api).
### Migrate from CommonJS to ESM
## Migrate from CommonJS to ESM
Nuxt 3 natively supports TypeScript and ECMAScript Modules. Please check [Native ES Modules](/docs/guide/concepts/esm) for more info and upgrading.
## Remove Incompatible and Obsolete Modules
- Remove `@nuxt/content` (1.x). A rewrite for Nuxt 3 [is available](https://content.nuxtjs.org/) (2.x)
- Remove `nuxt-vite`: Bridge enables same functionality
- Remove `@nuxt/typescript-build`: Bridge enables same functionality
- Remove `@nuxt/typescript-runtime` and `nuxt-ts`: Nuxt 2 has built-in runtime support
- Remove `@nuxt/nitro`: Bridge injects same functionality
- Remove `@vue/composition-api` from your dependencies ([migration guide](/docs/bridge/bridge-composition-api)).
- Remove `@nuxtjs/composition-api` from your dependencies (and from your modules in `nuxt.config`) ([migration guide](/docs/bridge/bridge-composition-api)).
## Exclude Built Nitro Folder From Git
Add the folder `.output` to the `.gitignore` file.
## Ensure Everything Goes Well
✔️ Try with `nuxi dev` and `nuxi build` (or `nuxi generate`) to see if everything goes well.
🐛 Is something wrong? Please let us know by creating an issue. Also, you can easily disable the bridge in the meantime:
```ts [nuxt.config.js|ts]
import { defineNuxtConfig } from '@nuxt/bridge'
export default defineNuxtConfig({
bridge: false // Temporarily disable bridge integration
})
```
## New Plugins Format (Optional)
You can now migrate to the Nuxt 3 plugins API, which is slightly different in format from Nuxt 2.
Plugins now take only one argument (`nuxtApp`). You can find out more in [the docs](/docs/guide/directory-structure/plugins).
```js
export default defineNuxtPlugin(nuxtApp => {
nuxtApp.provide('injected', () => 'my injected function')
// now available on `nuxtApp.$injected`
})
```
::alert
If you want to use the new Nuxt composables (such as [`useNuxtApp`](/docs/api/composables/use-nuxt-app) or `useRuntimeConfig`) within your plugins, you will need to use the `defineNuxtPlugin` helper for those plugins.
::
::alert{type=warning}
Although a compatibility interface is provided via `nuxtApp.vueApp` you should avoid registering plugins, directives, mixins or components this way without adding your own logic to ensure they are not installed more than once, or this may cause a memory leak.
::
## New Middleware Format (Optional)
You can now migrate to the Nuxt 3 middleware API, which is slightly different in format from Nuxt 2.
Middleware now take only two argument (`to`, `from`). You can find out more in [the docs](/docs/guide/directory-structure/middleware).
```js
export default defineNuxtRouteMiddleware((to) => {
if (to.path !== '/') {
return navigateTo('/')
}
})
```
::alert{type=warning}
Use of `defineNuxtRouteMiddleware` is not supported outside of the middleware directory.
::
::alert{type=warning}
Nuxt Bridge does not support `definePageMeta`.
::
## New `useHead` (Optional)
Nuxt Bridge provides a new Nuxt 3 meta API that can be accessed with a new [`useHead`](/docs/api/composables/use-head) composable.
```vue
<script setup lang="ts">
useHead({
title: 'My Nuxt App',
})
</script>
```
You will also need to enable this feature explicitly in your `nuxt.config`:
```js
import { defineNuxtConfig } from '@nuxt/bridge'
export default defineNuxtConfig({
bridge: {
meta: true
}
})
```
::alert
This [`useHead`](/docs/api/composables/use-head) composable uses `@vueuse/head` under the hood (rather than `vue-meta`) to manipulate your `<head>`. You need to add `@vueuse/head` to your package.json file for it to work properly.
::
::alert{type=warning}
We recommend not using the native Nuxt 2 `head()` properties in addition to [`useHead`](/docs/api/composables/use-head) , as they may conflict.
::
For more information on how to use this composable, see [the docs](/docs/getting-started/seo-meta).
## Feature Flags
You can optionally disable some features from bridge or opt-in to less stable ones. In normal circumstances, it is always best to stick with defaults!
You can check [bridge/src/module.ts](https://github.com/nuxt/bridge/blob/main/packages/bridge/src/module.ts) for latest defaults.
```ts [nuxt.config.js|ts]
import { defineNuxtConfig } from '@nuxt/bridge'
export default defineNuxtConfig({
bridge: {
// -- Opt-in features --
// Use Vite as the bundler instead of webpack 4
// vite: true,
// Enable Nuxt 3 compatible useHead
// meta: true,
// -- Default features --
// Use legacy server instead of Nitro
// nitro: false,
// Disable Nuxt 3 compatible `nuxtApp` interface
// app: false,
// Disable Composition API support
// capi: false,
// ... or just disable legacy Composition API support
// capi: {
// legacy: false
// },
// Do not transpile modules
// transpile: false,
// Disable <script setup> support
// scriptSetup: false,
// Disable composables auto importing
// imports: false,
// Do not warn about module incompatibilities
// constraints: false
},
vite: {
// Config for Vite
}
})
```

View File

@ -0,0 +1,83 @@
# Configuration
## Feature Flags
You can optionally disable some features from bridge or opt-in to less stable ones. In normal circumstances, it is always best to stick with defaults!
You can check [bridge/src/module.ts](https://github.com/nuxt/bridge/blob/main/packages/bridge/src/module.ts) for latest defaults.
```ts [nuxt.config.js|ts]
import { defineNuxtConfig } from '@nuxt/bridge'
export default defineNuxtConfig({
bridge: {
// -- Opt-in features --
// Use Vite as the bundler instead of webpack 4
// vite: true,
// Enable Nuxt 3 compatible useHead
// meta: true,
// -- Default features --
// Use legacy server instead of Nitro
// nitro: false,
// Disable Nuxt 3 compatible `nuxtApp` interface
// app: false,
// Disable Composition API support
// capi: false,
// ... or just disable legacy Composition API support
// capi: {
// legacy: false
// },
// Do not transpile modules
// transpile: false,
// Disable <script setup> support
// scriptSetup: false,
// Disable composables auto importing
// imports: false,
// Do not warn about module incompatibilities
// constraints: false
},
vite: {
// Config for Vite
}
})
```
## Migration of each option
### router.base
```diff
export default defineNuxtConfig({
- router: {
- base: '/my-app/'
- }
+ app: {
+ baseURL: '/my-app/'
+ }
})
```
### build.publicPath
```diff
export default defineNuxtConfig({
- build: {
- publicPath: 'https://my-cdn.net'
- }
+ app: {
+ cdnURL: 'https://my-cdn.net'
+ }
})
```

View File

@ -0,0 +1,32 @@
# TypeScript
## Remove Modules
- Remove `@nuxt/typescript-build`: Bridge enables same functionality
- Remove `@nuxt/typescript-runtime` and `nuxt-ts`: Nuxt 2 has built-in runtime support
## Update `tsconfig.json`
If you are using TypeScript, you can edit your `tsconfig.json` to benefit from auto-generated Nuxt types:
```diff [tsconfig.json]
{
+ "extends": "./.nuxt/tsconfig.json",
"compilerOptions": {
...
}
}
```
::alert
As `.nuxt/tsconfig.json` is generated and not checked into version control, you'll need to generate that file before running your tests. Add `nuxi prepare` as a step before your tests, otherwise you'll see `TS5083: Cannot read file '~/.nuxt/tsconfig.json'`
::
::alert
You may also need to add `@vue/runtime-dom` as a devDependency if you are struggling to get template type inference working with [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar).
::
::alert
Keep in mind that all options extended from `./.nuxt/tsconfig.json` will be overwritten by the options defined in your `tsconfig.json`.
Overwriting options such as `"compilerOptions.paths"` with your own configuration will lead TypeScript to not factor in the module resolutions from `./.nuxt/tsconfig.json`. This can lead to module resolutions such as `#imports` not being recognized.
In case you need to extend options provided by `./.nuxt/tsconfig.json` further, you can use the `alias` property within your `nuxt.config`. `nuxi` will pick them up and extend `./.nuxt/tsconfig.json` accordingly.
::

View File

@ -0,0 +1,122 @@
# Legacy Composition API
Nuxt Bridge provides access to Composition API syntax. It is specifically designed to be aligned with Nuxt 3. Because of this, there are a few extra steps to take when enabling Nuxt Bridge, if you have been using the Composition API previously.
## Remove Modules
- Remove `@vue/composition-api` from your dependencies.
- Remove `@nuxtjs/composition-api` from your dependencies (and from your modules in `nuxt.config`).
## Using `@vue/composition-api`
If you have been using just `@vue/composition-api` and not `@nuxtjs/composition-api`, then things are very straightforward.
1. First, remove the plugin where you are manually registering the Composition API. Nuxt Bridge will handle this for you.
```diff
- import Vue from 'vue'
- import VueCompositionApi from '@vue/composition-api'
-
- Vue.use(VueCompositionApi)
```
2. Otherwise, there is nothing you need to do. However, if you want, you can remove your explicit imports from `@vue/composition-api` and rely on Nuxt Bridge auto-importing them for you.
## Migrating from `@nuxtjs/composition-api`
Nuxt Bridge implements the Composition API slightly differently from `@nuxtjs/composition-api` and provides different composables (designed to be aligned with the composables that Nuxt 3 provides).
Because some composables have been removed and don't yet have a replacement, this will be a slightly more complicated process.
### Remove `@nuxtjs/composition-api/module` from your buildModules
You don't have to immediately update your imports yet - Nuxt Bridge will automatically provide a 'shim' for most imports you currently have, to give you time to migrate to the new, Nuxt 3-compatible composables, with the following exceptions:
- `withContext` has been removed. See [below](/docs/bridge/nuxt3-compatible-api#usecontext-and-withcontext).
- `useStatic` has been removed. There is no current replacement. Feel free to raise a discussion if you have a use case for this.
- `reqRef` and `reqSsrRef`, which were deprecated, have now been removed entirely. Follow the instructions below regarding [ssrRef](/docs/bridge/nuxt3-compatible-api#ssrref-and-shallowssrref) to replace this.
### Set `bridge.capi`
```ts
import { defineNuxtConfig } from '@nuxt/bridge'
export default defineNuxtConfig({
bridge: {
capi: true
}
})
```
For each other composable you are using from `@nuxtjs/composition-api`, follow the steps below.
### useFetch
`$fetchState` and `$fetch` have been removed.
```diff
const {
- $fetch,
- $fetchState,
+ fetch,
+ fetchState,
} = useFetch(() => { posts.value = await $fetch('/api/posts') })
```
### `defineNuxtMiddleware`
This was a type-helper stub function that is now removed.
Remove the `defineNuxtMiddleware` wrapper:
```diff
- import { defineNuxtMiddleware } from '@nuxtjs/composition-api`
- export default defineNuxtMiddleware((ctx) => {})
+ export default (ctx) => {}
```
For typescript support, you can use `@nuxt/types`:
```ts
import type { Middleware } from '@nuxt/types'
export default <Middleware> function (ctx) { }
```
### `defineNuxtPlugin`
This was a type-helper stub function that is now removed.
You may also keep using Nuxt 2-style plugins, by removing the function (as with [defineNuxtMiddleware](#definenuxtmiddleware)).
Remove the `defineNuxtPlugin` wrapper:
```diff
- import { defineNuxtPlugin } from '@nuxtjs/composition-api'
- export default defineNuxtPlugin((ctx, inject) => {})
+ export default (ctx, inject) => {}
```
For typescript support, you can use `@nuxt/types`:
```ts
import type { Plugin } from '@nuxt/types'
export default <Plugin> function (ctx, inject) {}
```
### `useRouter` and `useRoute`
Nuxt Bridge provides direct replacements for these composables via [`useRouter`](/docs/api/composables/use-router) and `useRoute`.
The only key difference is that [`useRoute`](/docs/api/composables/use-route) no longer returns a computed property.
```diff
- import { useRouter, useRoute } from '@nuxtjs/composition-api'
const router = useRouter()
const route = useRoute()
- console.log(route.value.path)
+ console.log(route.path)
```

View File

@ -0,0 +1,44 @@
# Plugins and Middleware
## New Plugins Format
You can now migrate to the Nuxt 3 plugins API, which is slightly different in format from Nuxt 2.
Plugins now take only one argument (`nuxtApp`). You can find out more in [the docs](/docs/guide/directory-structure/plugins).
```js
export default defineNuxtPlugin(nuxtApp => {
nuxtApp.provide('injected', () => 'my injected function')
// now available on `nuxtApp.$injected`
})
```
::alert
If you want to use the new Nuxt composables (such as [`useNuxtApp`](/docs/api/composables/use-nuxt-app) or `useRuntimeConfig`) within your plugins, you will need to use the `defineNuxtPlugin` helper for those plugins.
::
::alert{type=warning}
Although a compatibility interface is provided via `nuxtApp.vueApp` you should avoid registering plugins, directives, mixins or components this way without adding your own logic to ensure they are not installed more than once, or this may cause a memory leak.
::
## New Middleware Format
You can now migrate to the Nuxt 3 middleware API, which is slightly different in format from Nuxt 2.
Middleware now take only two argument (`to`, `from`). You can find out more in [the docs](/docs/guide/directory-structure/middleware).
```js
export default defineNuxtRouteMiddleware((to) => {
if (to.path !== '/') {
return navigateTo('/')
}
})
```
::alert{type=warning}
Use of `defineNuxtRouteMiddleware` is not supported outside of the middleware directory.
::
::alert{type=warning}
Nuxt Bridge does not support `definePageMeta`.
::

View File

@ -1,112 +1,10 @@
# Composition API
# New Composition API
Nuxt Bridge provides access to Composition API syntax. It is specifically designed to be aligned with Nuxt 3. Because of this, there are a few extra steps to take when enabling Nuxt Bridge, if you have been using the Composition API previously.
Nuxt Bridge implements composables compatible with Nuxt 3.
## Using `@vue/composition-api`
By migrating from `@nuxtjs/composition-api` to the Nuxt 3 compatible API, there will be less rewriting when migrating to Nuxt 3.
If you have been using just `@vue/composition-api` and not `@nuxtjs/composition-api`, then things are very straightforward.
1. First, remove the plugin where you are manually registering the Composition API. Nuxt Bridge will handle this for you.
```diff
- import Vue from 'vue'
- import VueCompositionApi from '@vue/composition-api'
-
- Vue.use(VueCompositionApi)
```
2. Otherwise, there is nothing you need to do. However, if you want, you can remove your explicit imports from `@vue/composition-api` and rely on Nuxt Bridge auto-importing them for you.
## Migrating from `@nuxtjs/composition-api`
Nuxt Bridge implements the Composition API slightly differently from `@nuxtjs/composition-api` and provides different composables (designed to be aligned with the composables that Nuxt 3 provides).
Because some composables have been removed and don't yet have a replacement, this will be a slightly more complicated process.
1. Remove `@nuxtjs/composition-api` from your project dependencies, and remove `@nuxtjs/composition-api/module` from your buildModules.
You don't have to immediately update your imports yet - Nuxt Bridge will automatically provide a 'shim' for most imports you currently have, to give you time to migrate to the new, Nuxt 3-compatible composables, with the following exceptions:
* `withContext` has been removed. See [below](#usecontext-and-withcontext).
* `useStatic` has been removed. There is no current replacement. Feel free to raise a discussion if you have a use case for this.
* `reqRef` and `reqSsrRef`, which were deprecated, have now been removed entirely. Follow the instructions below regarding [ssrRef](#ssrref-and-shallowssrref) to replace this.
2. Remove any explicit imports of the basic Vue Composition API composables.
::alert{type=info}
Nuxt Bridge [auto-imports](/docs/guide/concepts/auto-imports) Vue composables, you don't have to explicitly import them.
::
```diff
- import { ref, useContext } from '@nuxtjs/composition-api'
```
3. For each other composable you are using from `@nuxtjs/composition-api`, follow the steps below.
### `defineNuxtMiddleware`
This was a type-helper stub function that is now removed.
Remove the `defineNuxtMiddleware` wrapper:
```diff
- import { defineNuxtMiddleware } from '@nuxtjs/composition-api`
- export default defineNuxtMiddleware((ctx) => {})
+ export default (ctx) => {}
```
For typescript support, you can use `@nuxt/types`:
```ts
import type { Middleware } from '@nuxt/types'
export default <Middleware> function (ctx) { }
```
### `defineNuxtPlugin`
This was a type-helper stub function that is now removed.
You may also keep using Nuxt 2-style plugins, by removing the function (as with [defineNuxtMiddleware](#definenuxtmiddleware)).
Remove the `defineNuxtPlugin` wrapper:
```diff
- import { defineNuxtPlugin } from '@nuxtjs/composition-api'
- export default defineNuxtPlugin((ctx, inject) => {})
+ export default (ctx, inject) => {}
```
For typescript support, you can use `@nuxt/types`:
```ts
import type { Plugin } from '@nuxt/types'
export default <Plugin> function (ctx, inject) {}
```
::alert
You may wish to [migrate your plugins to Nuxt 3-style plugins](/docs/bridge/overview#new-plugins-format-optional) as a next (optional) step.
::
### `onGlobalSetup`
This function has been removed, but its use cases can be met by using [`useNuxtApp`](/docs/api/composables/use-nuxt-app) or [`useState`](/docs/api/composables/use-state) within `defineNuxtPlugin`. You can also run any custom code within the `setup()` function of a layout.
```diff
- import { onGlobalSetup } from '@nuxtjs/composition-api'
- export default () => {
- onGlobalSetup(() => {
+ export default defineNuxtPlugin((nuxtApp) => {
+ nuxtApp.hook('vue:setup', () => {
// ...
})
- }
+ })
```
### `ssrRef` and `shallowSsrRef`
## `ssrRef` and `shallowSsrRef`
These two functions have been replaced with a new composable that works very similarly under the hood: `useState`.
@ -127,27 +25,28 @@ Because the state is keyed, you can access the same state from multiple location
You can read more about how to use this composable in [the Nuxt 3 docs](/docs/api/composables/use-state).
### `ssrPromise`
## `ssrPromise`
This function has been removed, and you will need to find an alternative implementation if you were using it. If you have a use case for `ssrPromise`, please let us know via a discussion.
### `useRouter` and `useRoute`
## `onGlobalSetup`
Nuxt Bridge provides direct replacements for these composables via [`useRouter`](/docs/api/composables/use-router) and `useRoute`.
The only key difference is that [`useRoute`](/docs/api/composables/use-route) no longer returns a computed property.
This function has been removed, but its use cases can be met by using [`useNuxtApp`](/docs/api/composables/use-nuxt-app) or [`useState`](/docs/api/composables/use-state) within `defineNuxtPlugin`. You can also run any custom code within the `setup()` function of a layout.
```diff
- import { useRouter, useRoute } from '@nuxtjs/composition-api'
- import { onGlobalSetup } from '@nuxtjs/composition-api'
const router = useRouter()
const route = useRoute()
- console.log(route.value.path)
+ console.log(route.path)
- export default () => {
- onGlobalSetup(() => {
+ export default defineNuxtPlugin((nuxtApp) => {
+ nuxtApp.hook('vue:setup', () => {
// ...
})
- }
+ })
```
### `useStore`
## `useStore`
In order to access Vuex store instance, you can use `useNuxtApp().$store`.
@ -156,7 +55,7 @@ In order to access Vuex store instance, you can use `useNuxtApp().$store`.
+ const { $store } = useNuxtApp()
```
### `useContext` and `withContext`
## `useContext` and `withContext`
You can access injected helpers using `useNuxtApp`.
@ -169,7 +68,7 @@ You can access injected helpers using `useNuxtApp`.
`useNuxtApp()` also provides a key called `nuxt2Context` which contains all the same properties you would normally access from Nuxt 2 context, but it's advised _not_ to use this directly, as it won't exist in Nuxt 3. Instead, see if there is another way to access what you need. (If not, please raise a feature request or discussion.)
::
### `wrapProperty`
## `wrapProperty`
This helper function is not provided any more but you can replace it with the following code:
@ -180,7 +79,7 @@ const wrapProperty = (property, makeComputed = true) => () => {
}
```
### `useAsync` and `useFetch`
## `useAsync` and `useFetch`
These two composables can be replaced with `useLazyAsyncData` and `useLazyFetch`, which are documented [in the Nuxt 3 docs](/docs/getting-started/data-fetching). Just like the previous `@nuxtjs/composition-api` composables, these composables do not block route navigation on the client-side (hence the 'lazy' part of the name).
@ -188,6 +87,10 @@ These two composables can be replaced with `useLazyAsyncData` and `useLazyFetch`
Note that the API is entirely different, despite similar sounding names. Importantly, you should not attempt to change the value of other variables outside the composable (as you may have been doing with the previous `useFetch`).
::
::alert{type=warning}
The `useLazyFetch` must have been configured for [Nitro](/docs/bridge/nitro).
::
Migrating to the new composables from `useAsync`:
```diff
@ -268,6 +171,33 @@ export default defineNuxtConfig({
})
```
This [`useHead`](/docs/api/composables/use-head) composable uses `@vueuse/head` under the hood (rather than `vue-meta`) to manipulate your `<head>`. Accordingly, it is recommended not to use both the native Nuxt 2 `head()` properties as well as [`useHead`](/docs/api/composables/use-head) , as they may conflict.
This [`useHead`](/docs/api/composables/use-head) composable uses `@unhead/vue` under the hood (rather than `vue-meta`) to manipulate your `<head>`. Accordingly, it is recommended not to use both the native Nuxt 2 `head()` properties as well as [`useHead`](/docs/api/composables/use-head) , as they may conflict.
For more information on how to use this composable, see [the Nuxt 3 docs](/docs/getting-started/seo-meta).
### Explicit Imports
Nuxt exposes every auto-import with the `#imports` alias that can be used to make the import explicit if needed:
```vue
<script setup lang="ts">
import { ref, computed } from '#imports'
const count = ref(1)
const double = computed(() => count.value * 2)
</script>
```
### Disabling Auto-imports
If you want to disable auto-importing composables and utilities, you can set `imports.autoImport` to `false` in the `nuxt.config` file.
```ts [nuxt.config.ts]
export default defineNuxtConfig({
imports: {
autoImport: false
}
})
```
This will disable auto-imports completely but it's still possible to use [explicit imports](#explicit-imports) from `#imports`.

109
docs/6.bridge/6.meta.md Normal file
View File

@ -0,0 +1,109 @@
# Meta Tags
If you need to access the component state with `head`, you should migrate to using [`useHead`](/docs/api/composables/use-head) .
If you need to use the Options API, there is a `head()` method you can use when you use `defineNuxtComponent`.
## Migration
### Set `bridge.meta`
```js
import { defineNuxtConfig } from '@nuxt/bridge'
export default defineNuxtConfig({
bridge: {
meta: true
}
})
```
### Update head properties
In your `nuxt.config`, rename `head` to `meta`. (Note that objects no longer have a `hid` key for deduplication.)
::code-group
```ts [Nuxt 2]
export default {
head: {
titleTemplate: '%s - Nuxt',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: 'Meta description' }
]
}
}
```
```ts [Nuxt 3]
export default defineNuxtConfig({
app: {
head: {
titleTemplate: '%s - Nuxt',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ name: 'description', content: 'Meta description' }
]
}
}
})
```
::
## `useHead` Composables
Nuxt Bridge provides a new Nuxt 3 meta API that can be accessed with a new [`useHead`](/docs/api/composables/use-head) composable.
```vue
<script setup lang="ts">
useHead({
title: 'My Nuxt App',
})
</script>
```
::alert
This [`useHead`](/docs/api/composables/use-head) composable uses `@unhead/vue` under the hood (rather than `vue-meta`) to manipulate your `<head>`.
::
::alert{type=warning}
We recommend not using the native Nuxt 2 `head()` properties in addition to [`useHead`](/docs/api/composables/use-head) , as they may conflict.
::
For more information on how to use this composable, see [the docs](/docs/getting-started/seo-meta).
## Options API
```vue
<script>
// if using options API `head` method you must use `defineNuxtComponent`
export default defineNuxtComponent({
head (nuxtApp) {
// `head` receives the nuxt app but cannot access the component instance
return {
meta: [{
name: 'description',
content: 'This is my page description.'
}]
}
}
})
</script>
```
## Title Template
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 `/layouts` directory.
```vue [layouts/default.vue]
<script setup lang="ts">
useHead({
titleTemplate: (titleChunk) => {
return titleChunk ? `${titleChunk} - Site Title` : 'Site Title';
}
})
</script>
```

View File

@ -0,0 +1,31 @@
# Runtime Config
## Update Runtime Config
Nuxt 3 approaches runtime config differently than Nuxt 2, using a new combined `runtimeConfig` option.
First, you'll need to combine your `publicRuntimeConfig` and `privateRuntimeConfig` properties into a new one called `runtimeConfig`, with the public config within a key called `public`.
```diff
// nuxt.config.js
- privateRuntimeConfig: {
- apiKey: process.env.NUXT_API_KEY || 'super-secret-key'
- },
- publicRuntimeConfig: {
- websiteURL: 'https://public-data.com'
- }
+ runtimeConfig: {
+ apiKey: process.env.NUXT_API_KEY || 'super-secret-key',
+ public: {
+ websiteURL: 'https://public-data.com'
+ }
+ }
```
This also means that when you need to access public runtime config, it's behind a property called `public`. If you use public runtime config, you'll need to update your code.
```diff
// MyWidget.vue
- <div>Website: {{ $config.websiteURL }}</div>
+ <div>Website: {{ $config.public.websiteURL }}</div>
```

75
docs/6.bridge/8.nitro.md Normal file
View File

@ -0,0 +1,75 @@
# Nitro
## Remove Modules
- Remove `@nuxt/nitro`: Bridge injects same functionality
## Update Config
```ts [nuxt.config.js|ts]
import { defineNuxtConfig } from '@nuxt/bridge'
export default defineNuxtConfig({
bridge: {
nitro: true
}
})
```
## Update Your Scripts
You will also need to update your scripts within your `package.json` to reflect the fact that Nuxt will now produce a Nitro server as build output.
### Nuxi
Nuxt 3 introduced the new Nuxt CLI command [`nuxi`](/docs/api/commands/add). Update your scripts as follows to leverage the better support from Nuxt Bridge:
```diff
{
"scripts": {
- "dev": "nuxt",
+ "dev": "nuxi dev",
- "build": "nuxt build",
+ "build": "nuxi build",
- "start": "nuxt start",
+ "start": "nuxi preview"
}
}
```
::alert
If `nitro: false`, use the `nuxt` command.
::
### Static Target
If you have set `target: 'static'` in your `nuxt.config` then you need to ensure that you update your build script to be `nuxi generate`.
```json [package.json]
{
"scripts": {
"build": "nuxi generate"
}
}
```
### Server Target
For all other situations, you can use the `nuxi build` command.
```json [package.json]
{
"scripts": {
"build": "nuxi build",
"start": "nuxi preview"
}
}
```
## Exclude Built Nitro Folder From Git
Add the folder `.output` to the `.gitignore` file.
## Ensure Everything Goes Well
✔️ Try with `nuxi dev` and `nuxi build` (or `nuxi generate`) to see if everything goes well.

34
docs/6.bridge/9.vite.md Normal file
View File

@ -0,0 +1,34 @@
# Vite
::alert{type=warning}
When using `vite`, [nitro](/docs/bridge/nitro) must have been configured.
::
## Remove Modules
- Remove `nuxt-vite`: Bridge enables same functionality
## Update Config
```ts [nuxt.config.js|ts]
import { defineNuxtConfig } from '@nuxt/bridge'
export default defineNuxtConfig({
bridge: {
vite: true,
nitro: true
}
})
```
## Configuration
```ts [nuxt.config.js|ts]
import { defineNuxtConfig } from '@nuxt/bridge'
export default defineNuxtConfig({
vite: {
// Config for Vite
}
})
```

View File

@ -52,19 +52,19 @@
"cheerio": "1.0.0-rc.12",
"consola": "3.2.3",
"devalue": "4.3.2",
"eslint": "8.47.0",
"eslint": "8.48.0",
"eslint-plugin-import": "2.28.1",
"eslint-plugin-jsdoc": "41.1.2",
"eslint-plugin-no-only-tests": "3.1.0",
"execa": "7.2.0",
"fs-extra": "11.1.1",
"globby": "13.2.2",
"h3": "1.8.0",
"h3": "1.8.1",
"happy-dom": "10.11.0",
"jiti": "1.19.3",
"markdownlint-cli": "^0.33.0",
"nitropack": "2.6.0",
"nuxi": "npm:nuxi-ng@0.3.0-1692970235.c259efa",
"nitropack": "2.6.2",
"nuxi": "3.7.2",
"nuxt": "workspace:*",
"nuxt-vitest": "0.10.2",
"ofetch": "1.3.3",

View File

@ -1,6 +1,6 @@
{
"name": "@nuxt/kit",
"version": "3.6.5",
"version": "3.7.0",
"repository": "nuxt/nuxt",
"license": "MIT",
"type": "module",
@ -29,7 +29,7 @@
"ignore": "^5.2.4",
"jiti": "^1.19.3",
"knitwork": "^1.0.0",
"mlly": "^1.4.0",
"mlly": "^1.4.1",
"pathe": "^1.1.1",
"pkg-types": "^1.0.3",
"scule": "^1.0.0",
@ -44,7 +44,7 @@
"@types/lodash-es": "4.17.8",
"@types/semver": "7.5.0",
"lodash-es": "4.17.21",
"nitropack": "2.6.0",
"nitropack": "2.6.2",
"unbuild": "latest",
"vite": "4.4.9",
"vitest": "0.33.0",

View File

@ -1,6 +1,6 @@
{
"name": "nuxt",
"version": "3.6.5",
"version": "3.7.0",
"repository": "nuxt/nuxt",
"license": "MIT",
"type": "module",
@ -58,9 +58,9 @@
"@nuxt/telemetry": "^2.4.1",
"@nuxt/ui-templates": "^1.3.1",
"@nuxt/vite-builder": "workspace:../vite",
"@unhead/dom": "^1.3.7",
"@unhead/ssr": "^1.3.7",
"@unhead/vue": "^1.3.7",
"@unhead/dom": "^1.3.9",
"@unhead/ssr": "^1.3.9",
"@unhead/vue": "^1.3.9",
"@vue/shared": "^3.3.4",
"acorn": "8.10.0",
"c12": "^1.4.2",
@ -74,15 +74,15 @@
"estree-walker": "^3.0.3",
"fs-extra": "^11.1.1",
"globby": "^13.2.2",
"h3": "^1.8.0",
"h3": "^1.8.1",
"hookable": "^5.5.3",
"jiti": "^1.19.3",
"klona": "^2.0.6",
"knitwork": "^1.0.0",
"magic-string": "^0.30.3",
"mlly": "^1.4.0",
"nitropack": "^2.6.0",
"nuxi": "npm:nuxi-ng@0.3.0-1692970235.c259efa",
"mlly": "^1.4.1",
"nitropack": "^2.6.2",
"nuxi": "^3.7.2",
"nypm": "^0.3.1",
"ofetch": "^1.3.3",
"ohash": "^1.1.3",
@ -97,7 +97,7 @@
"ultrahtml": "^1.3.0",
"uncrypto": "^0.1.3",
"unctx": "^2.3.1",
"unenv": "^1.7.3",
"unenv": "^1.7.4",
"unimport": "^3.2.0",
"unplugin": "^1.4.0",
"unplugin-vue-router": "^0.6.4",

View File

@ -171,7 +171,7 @@ export default defineComponent({
if (import.meta.client && !nuxtApp.isHydrating && props.lazy) {
fetchComponent()
} else if (import.meta.server || !nuxtApp.isHydrating) {
} else if (import.meta.server || !nuxtApp.isHydrating || !nuxtApp.payload.serverRendered) {
await fetchComponent()
}

View File

@ -81,7 +81,7 @@ export default defineComponent({
}
}
}) as unknown as DefineComponent<{
name?: unknown extends PageMeta['layout'] ? MaybeRef<string | false> : PageMeta['layout']
name?: (unknown extends PageMeta['layout'] ? MaybeRef<string | false> : PageMeta['layout']) | undefined;
}>
const LayoutProvider = defineComponent({

View File

@ -47,7 +47,7 @@ export function createTransformPlugin (nuxt: Nuxt, getComponents: getComponentsT
name: 'nuxt:components:imports',
transformInclude (id) {
id = normalize(id)
return id.startsWith('virtual:') || id.startsWith(nuxt.options.buildDir) || !isIgnored(id)
return id.startsWith('virtual:') || id.startsWith('\0virtual:') || id.startsWith(nuxt.options.buildDir) || !isIgnored(id)
},
async transform (code, id) {
// Virtual component wrapper

View File

@ -8,6 +8,7 @@ import escapeRE from 'escape-string-regexp'
import fse from 'fs-extra'
import { withoutLeadingSlash } from 'ufo'
/* eslint-disable import/no-restricted-paths */
import defu from 'defu'
import pagesModule from '../pages/module'
import metaModule from '../head/module'
import componentsModule from '../components/module'
@ -283,6 +284,12 @@ async function initNuxt (nuxt: Nuxt) {
priority: 10, // built-in that we do not expect the user to override
filePath: resolve(nuxt.options.appDir, 'components/nuxt-island')
})
if (!nuxt.options.ssr) {
nuxt.options.ssr = true
nuxt.options.nitro.routeRules ||= {}
nuxt.options.nitro.routeRules['/**'] = defu(nuxt.options.nitro.routeRules['/**'], { ssr: false })
}
}
// Add experimental cross-origin prefetch support using Speculation Rules API

View File

@ -7,11 +7,12 @@ import type { Nuxt } from '@nuxt/schema'
import { pkgDir } from '../../dirs'
export function resolveDeepImportsPlugin (nuxt: Nuxt): Plugin {
const exclude: string[] = ['virtual:', '\0virtual:', '/__skip_vite']
return {
name: 'nuxt:resolve-bare-imports',
enforce: 'post',
async resolveId (id, importer, options) {
if (!importer || isAbsolute(id) || !isAbsolute(importer) || id.startsWith('virtual:') || id.startsWith('/__skip_vite')) {
if (!importer || isAbsolute(id) || !isAbsolute(importer) || exclude.some(e => id.startsWith(e))) {
return
}
id = normalize(id)

View File

@ -259,7 +259,7 @@ export default defineRenderHandler(async (event): Promise<Partial<RenderResponse
noSSR:
!!(process.env.NUXT_NO_SSR) ||
event.context.nuxt?.noSSR ||
routeOptions.ssr === false ||
(routeOptions.ssr === false && !islandContext) ||
(import.meta.prerender ? PRERENDER_NO_SSR_ROUTES.has(url) : false),
head,
error: !!ssrError,

View File

@ -1,6 +1,6 @@
{
"name": "@nuxt/schema",
"version": "3.6.5",
"version": "3.7.0",
"repository": "nuxt/nuxt",
"license": "MIT",
"type": "module",
@ -16,6 +16,7 @@
"types": "./dist/builder-env.d.ts",
"import": "./dist/builder-env.mjs"
},
"./schema/config.schema.json": "./schema/config.schema.json",
"./package.json": "./package.json"
},
"files": [
@ -31,14 +32,14 @@
"@types/file-loader": "5.0.1",
"@types/pug": "2.0.6",
"@types/sass-loader": "8.0.5",
"@unhead/schema": "1.3.7",
"@unhead/schema": "1.3.9",
"@vitejs/plugin-vue": "4.3.3",
"@vitejs/plugin-vue-jsx": "3.0.2",
"@vue/compiler-core": "3.3.4",
"esbuild-loader": "4.0.1",
"h3": "1.8.0",
"h3": "1.8.1",
"ignore": "5.2.4",
"nitropack": "2.6.0",
"nitropack": "2.6.2",
"unbuild": "latest",
"unctx": "2.3.1",
"vite": "4.4.9",

View File

@ -1,6 +1,6 @@
{
"name": "@nuxt/test-utils",
"version": "3.6.5",
"version": "3.7.0",
"repository": "nuxt/nuxt",
"license": "MIT",
"type": "module",
@ -27,7 +27,7 @@
"consola": "^3.2.3",
"defu": "^6.1.2",
"execa": "^7.2.0",
"get-port-please": "^3.0.1",
"get-port-please": "^3.0.2",
"ofetch": "^1.3.3",
"pathe": "^1.1.1",
"ufo": "^1.3.0"

View File

@ -1,6 +1,6 @@
{
"name": "@nuxt/vite-builder",
"version": "3.6.5",
"version": "3.7.0",
"repository": "nuxt/nuxt",
"license": "MIT",
"type": "module",
@ -40,11 +40,11 @@
"estree-walker": "^3.0.3",
"externality": "^1.0.2",
"fs-extra": "^11.1.1",
"get-port-please": "^3.0.1",
"h3": "^1.8.0",
"get-port-please": "^3.0.2",
"h3": "^1.8.1",
"knitwork": "^1.0.0",
"magic-string": "^0.30.3",
"mlly": "^1.4.0",
"mlly": "^1.4.1",
"ohash": "^1.1.3",
"pathe": "^1.1.1",
"perfect-debounce": "^1.0.0",

View File

@ -1,6 +1,6 @@
{
"name": "@nuxt/webpack-builder",
"version": "3.6.5",
"version": "3.7.0",
"repository": "nuxt/nuxt",
"license": "MIT",
"type": "module",
@ -32,13 +32,13 @@
"file-loader": "^6.2.0",
"fork-ts-checker-webpack-plugin": "^8.0.0",
"fs-extra": "^11.1.1",
"h3": "^1.8.0",
"h3": "^1.8.1",
"hash-sum": "^2.0.0",
"lodash-es": "^4.17.21",
"magic-string": "^0.30.3",
"memfs": "^4.2.1",
"mini-css-extract-plugin": "^2.7.6",
"mlly": "^1.4.0",
"mlly": "^1.4.1",
"ohash": "^1.1.3",
"pathe": "^1.1.1",
"pify": "^6.1.0",

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,9 @@ fi
# Release packages
for p in packages/* ; do
if [[ $p == "packages/nuxi" ]] ; then
continue
fi
pushd $p
echo "Publishing $p"
cp ../../LICENSE .

View File

@ -10,6 +10,9 @@ pnpm build
# Release packages
for PKG in packages/* ; do
if [[ $PKG == "packages/nuxi" ]] ; then
continue
fi
pushd $PKG
TAG="latest"
if [ "$PKG" == "packages/nuxt" ]; then

View File

@ -10,6 +10,9 @@ pnpm build
# Release packages
for PKG in packages/* ; do
if [[ $PKG == "packages/nuxi" ]] ; then
continue
fi
pushd $PKG
TAG="latest"
echo "⚡ Publishing $PKG with tag $TAG"

View File

@ -19,7 +19,7 @@ describe.skipIf(process.env.SKIP_BUNDLE_SIZE === 'true' || process.env.ECOSYSTEM
for (const outputDir of ['.output', '.output-inline']) {
it('default client bundle size', async () => {
const clientStats = await analyzeSizes('**/*.js', join(rootDir, outputDir, 'public'))
expect.soft(roundToKilobytes(clientStats.totalBytes)).toMatchInlineSnapshot('"96.6k"')
expect.soft(roundToKilobytes(clientStats.totalBytes)).toMatchInlineSnapshot('"96.9k"')
expect(clientStats.files.map(f => f.replace(/\..*\.js/, '.js'))).toMatchInlineSnapshot(`
[
"_nuxt/entry.js",
@ -32,7 +32,7 @@ describe.skipIf(process.env.SKIP_BUNDLE_SIZE === 'true' || process.env.ECOSYSTEM
const serverDir = join(rootDir, '.output/server')
const serverStats = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir)
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot('"297k"')
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot('"300k"')
const modules = await analyzeSizes('node_modules/**/*', serverDir)
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot('"1822k"')
@ -71,10 +71,10 @@ describe.skipIf(process.env.SKIP_BUNDLE_SIZE === 'true' || process.env.ECOSYSTEM
const serverDir = join(rootDir, '.output-inline/server')
const serverStats = await analyzeSizes(['**/*.mjs', '!node_modules'], serverDir)
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot('"603k"')
expect.soft(roundToKilobytes(serverStats.totalBytes)).toMatchInlineSnapshot('"606k"')
const modules = await analyzeSizes('node_modules/**/*', serverDir)
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot('"70.5k"')
expect.soft(roundToKilobytes(modules.totalBytes)).toMatchInlineSnapshot('"70.6k"')
const packages = modules.files
.filter(m => m.endsWith('package.json'))

View File

@ -7,7 +7,7 @@ import type { AppConfig, RuntimeValue } from 'nuxt/schema'
import { defineNuxtConfig } from 'nuxt/config'
import { callWithNuxt, isVue3 } from '#app'
import type { NavigateToOptions } from '#app/composables/router'
import { NuxtLink, NuxtPage, WithTypes } from '#components'
import { NuxtLayout, NuxtLink, NuxtPage, WithTypes } from '#components'
import { useRouter } from '#imports'
interface TestResponse { message: string }
@ -207,6 +207,13 @@ describe('layouts', () => {
// @ts-expect-error Invalid layout
definePageMeta({ layout: 'invalid-layout' })
})
it('allows typing layouts', () => {
h(NuxtLayout, { name: 'custom' })
// @ts-expect-error Invalid layout
h(NuxtLayout, { name: 'invalid-layout' })
})
})
describe('modules', () => {