docs: update migration guide for nuxt 3 (#3819)

Co-authored-by: Dan Pastori <dan@521dimensions.com>
Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
Co-authored-by: pooya parsa <pyapar@gmail.com>
This commit is contained in:
Daniel Roe 2022-03-30 18:32:30 +01:00 committed by GitHub
parent 96ad9cfe97
commit 1a39eff502
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 824 additions and 141 deletions

View File

@ -1,4 +1,4 @@
# Bridge
# Migrating to Bridge
Experience Nuxt 3 features on existing Nuxt 2 projects.
@ -241,7 +241,7 @@ export default defineNuxtConfig({
// -- Opt-in features --
// Use Vite as the bundler instead of Webpack 4
// Use Vite as the bundler instead of webpack 4
// vite: true,
// Enable Nuxt 3 compatible useMeta

View File

@ -1,132 +0,0 @@
# Migration
Nuxt 3 migration guide. Work in progress 🚧
## Nuxt 2 to Nuxt 3
At the moment, there is no Nuxt 2 to Nuxt 3 migration guide nor is it recommended due to potentially more changes coming.
We are working to provide a stable migration guide and tooling to make it as smooth as possible. Please check [Bridge](/getting-started/bridge) for the alternative.
Some features have been dropped from Nuxt 2, some are yet to be implemented for Nuxt 3 and some are new in Nuxt 3 (and Bridge).
Noticeable and/or breaking changes for Nuxt 3 other than the requirements of Nuxt Bridge are:
::list{type=warning}
- Vue app templates are rewritten
- Vue upgraded to `3.x`
- Using `<Suspense>` for async data fetching
- Webpack `5.x` (if not using `vite`)
- Components discovery is rewritten
- Introduced main [`app.vue` component](/docs/directory-structure/app)
- Introduced new [`layouts` system](/docs/directory-structure/layouts)
- The [`pages/` directory](/docs/directory-structure/pages) conventions changed
::
The below table highlights an overall feature comparison:
Feature / Version | Nuxt 2 | Nuxt 3 | Changes required | More information
--------------------------|---------|----------|---------------------------------|------------------
Vue Version | 2 | 3 | Yes |
`app.vue` | ❌ | ✅ | - |
Suspense | ❌ | ✅ | - |
Assets | ✅ | ✅ | No |
Components | ✅ | ✅ | No |
Layouts | ✅ | ✅ | Yes |
Middleware | ✅ | ✅ | Yes |
Pages | ✅ | ✅ | Yes |
Pages: Dynamic Params | ✅ | ✅ | Yes |
Pages: _.vue | ✅ | ✅ | Yes (new naming system) |
Plugins | ✅ | ✅ | Yes (compatible by default) |
Transitions | ✅ | ✅ | ? |
Options API: `asyncData` | ✅ | ✅ | Yes (use `defineNuxtComponent`) |
Options API: `fetch` | ✅ | ❌ | Use `asyncData` instead |
Error Pages | ✅ | 🚧 | Yes | [Handling runtime errors](https://github.com/nuxt/framework/discussions/559)
Store | ✅ | 🚧 | Yes | [Global store support](https://github.com/nuxt/framework/discussions/571)
Static builds | ✅ | 🚧 | | [Route Caching rules (Hybrid)](https://github.com/nuxt/framework/discussions/560)
### Module Compatibility
All Nuxt 2 modules should be forward compatible with Nuxt 3 as long as they migrate to bridge or if they are already following guidelines.
All (upcoming) modules made with `@nuxt/kit` should be backward compatible with Nuxt 2 projects (even without bridge) as long as they are not depending on a Nuxt 3 / Bridge-only feature.
### Plugin Compatibility
Most Nuxt 2 plugins should be forward compatible with Nuxt 3 with a magical compat layer we inject.
Nuxt 3 plugins are **not** backward compatible with Nuxt 2.
### Vue Compatibility
For plugins using composition API or components, it needs exclusive Vue 2 or Vue 3 support.
By using [vue-demi](https://github.com/vueuse/vue-demi) they should be compatible with both Nuxt 2 and 3.
## Module Migration
When Nuxt 3 users add your module, a compatible module container layer from `@nuxt/kit` is **automatically injected**, so as long as your code is following the guidelines below, it should continue working as-is.
### Test with `@nuxt/bridge`
Migrating to `@nuxt/bridge` is the first and most important step for supporting Nuxt 3.
If you have a fixture or example in your module, add `@nuxt/bridge` package to its config (see [example](/getting-started/bridge#update-nuxtconfig))
### Migrate from CommonJS to ESM
Nuxt 3 natively supports TypeScript and ECMAScript Modules. Please check [Native ES Modules](/concepts/esm) for more info and upgrading.
### Ensure plugins default export
If you inject a Nuxt plugin that does not have `export default` (such as global Vue plugins), ensure you add `export default () => { }` to the end of it.
::code-group
```js [Before]
// ~/plugins/vuelidate.js
import Vue from 'vue'
import Vuelidate from 'vuelidate'
Vue.use(Vuelidate)
```
```js [After]
// ~/plugins/vuelidate.js
import Vue from 'vue'
import Vuelidate from 'vuelidate'
Vue.use(Vuelidate)
export default () => { }
```
::
### Avoid runtime modules
With Nuxt 3, Nuxt is now a build-time-only dependency, which means that modules shouldn't attempt to hook into the Nuxt runtime.
Your module should work even if it's only added to [`buildModules`](/docs/directory-structure/nuxt.config#buildmodules) (instead of `modules`). For example:
- Avoid updating `process.env` within a Nuxt module and reading by a nuxt plugin; use [`runtimeConfig`](/docs/directory-structure/nuxt.config#publicruntimeconfig) instead.
- (*) Avoid depending on runtime hooks like `vue-renderer:*` for production
- (*) Avoid adding `serverMiddleware` by importing them inside the module. Instead, add them by referencing a file path so that they are independent of the module's context
(*) Unless it is for `nuxt dev` purpose only and guarded with `if (nuxt.options.dev) { }`.
::alert{type=info icon=🔎}
Continue reading about Nuxt 3 modules in the [Modules guide](/docs/advanced/modules).
::
### Use TypeScript (optional)
While it is not essential, most of the Nuxt ecosystem is shifting to use TypeScript, so it is highly recommended to consider migration.
::alert{icon=💡}
You can start migration by renaming `.js` files, to `.ts`. TypeScript is designed to be progressive!
::
::alert{icon=💡}
You can use TypeScript syntax for Nuxt 2 and 3 modules and plugins without any extra dependencies.
::

View File

@ -8,7 +8,7 @@ To understand what is Nuxt, we need to understand what we need to create a moder
::list{type=success}
- A JavaScript framework to bring reactivity and web components, we chose [Vue.js](https://v3.vuejs.org).
- A bundler to support hot module replacement in development and bundle your code for production, we support both [Webpack 5](https://webpack.js.org/) and [Vite](https://vitejs.dev/).
- A bundler to support hot module replacement in development and bundle your code for production, we support both [webpack 5](https://webpack.js.org/) and [Vite](https://vitejs.dev/).
- A transpiler in order to write the latest JavaScript syntax while supporting legacy browsers, we use [esbuild](https://esbuild.github.io) for that.
- A server for serving your application in development, but also to support [server-side rendering](https://vuejs.org/api/ssr.html#server-side-rendering-api) or API routes, Nuxt uses [h3](https://github.com/unjs/h3) for deployment versatility such as serverless, workers, Node.js and unmatched performance.
- A routing library to handle client-side navigation, we chose [vue-router](https://router.vuejs.org/).
@ -47,4 +47,4 @@ Ready to try? Head over the [Installation section](/getting-started/installation
### Are you *courageously* Nuxt?
Take a stab at an open [issue](https://github.com/nuxt/framework/issues). This is actually the best way to learn Nuxt, by actually diving into the code. You may even bring an approach or alternative solution that makes Nuxt even better! So, what are you waiting for? Let's go!
Take a stab at an open [issue](https://github.com/nuxt/framework/issues). This is actually the best way to learn Nuxt, by actually diving into the code. You may even bring an approach or alternative solution that makes Nuxt even better! So, what are you waiting for? Let's go!

View File

@ -100,7 +100,7 @@ Used with the `setup` keyword in the `<script>` definition, here is the above co
The goal of Nuxt 3 is to provide a great developer experience around the composition API.
- Use auto-imported [Reactivity functions](https://vuejs.org/api/reactivity-core.html) from Vue and Nuxt 3 [built-in composables](https://v3.nuxtjs.org/docs/usage/data-fetching).
- Use auto-imported [Reactivity functions](https://vuejs.org/api/reactivity-core.html) from Vue and Nuxt 3 [built-in composables](/docs/usage/data-fetching).
- Write your own auto-imported reusable functions in the `composables/` directory.
### Typescript support

View File

@ -57,7 +57,7 @@ Universal rendering is very versatile and can fit almost any use-case, and is es
Client-side and universal rendering are different strategies to display an interface in a browser.
By default, Nuxt uses **universal rendering** to provide a better User experience, performance and optimize search engine indexation, but you can switch rendering modes in [one line of configuration](https://v3.nuxtjs.org/docs/directory-structure/nuxt.config#ssr).
By default, Nuxt uses **universal rendering** to provide a better User experience, performance and optimize search engine indexation, but you can switch rendering modes in [one line of configuration](/docs/directory-structure/nuxt.config#ssr).
## Coming in Nuxt 3
@ -75,6 +75,6 @@ At the moment, every page (or **route**) of a Nuxt application must use the same
Traditionally, server-side and universal rendering was only possible using Node.js. Nuxt 3 takes it to another level by directly rendering code in CDN edge workers, reducing latency and costs.
Nitro is the new [server engine](https://v3.nuxtjs.org/concepts/server-engine) that powers Nuxt 3. It offers cross-platform support for Node.js, Deno, Workers, and more. Nitro's design is platform-agnostic and allows rendering a Nuxt application at the edge, closer to your users, allowing replication and further optimizations.
Nitro is the new [server engine](/concepts/server-engine) that powers Nuxt 3. It offers cross-platform support for Node.js, Deno, Workers, and more. Nitro's design is platform-agnostic and allows rendering a Nuxt application at the edge, closer to your users, allowing replication and further optimizations.
[Deploy your Nuxt 3 application on serverless providers](https://v3.nuxtjs.org/docs/deployment/presets)
[Deploy your Nuxt 3 application on serverless providers](/docs/deployment/presets)

View File

@ -6,7 +6,7 @@ head.title: Assets directory
# Assets directory
The `assets/` directory is used to add all the website assets that the build tool (Webpack or Vite) will process.
The `assets/` directory is used to add all the website assets that the build tool (webpack or Vite) will process.
The directory usually contains the following types of files:

View File

@ -0,0 +1,21 @@
# Overview
<!-- ::alert{type=info}
Nuxt 3 is now in release candidate stage. The main goal of the release candidate stage is to **increase the adoption rate of Nuxt 3** and **increase stability**. However, it is still in continued development. Read more about [Nuxt 3 release candidate status](https://github.com/nuxt/framework/discussions/3447).
:: -->
::alert{type=info}
This migration guide is under progress to align with the development of Nuxt 3.
::
Nuxt 3 is a complete rewrite of Nuxt 2, and also based on a new set of underlying technologies. That means there will be significant changes when migrating a Nuxt 2 app to Nuxt 3, although you can expect migration to become more straightforward as we move toward a stable release.
Some of these significant changes include:
1. Moving from Vue 2 to Vue 3, including defaulting to the composition API and script setup.
1. Moving from webpack 4 and Babel to Vite or webpack 5 and esbuild.
1. Moving from a runtime Nuxt dependency to a minimal, standalone server compiled with nitropack.
::alert{type=info}
If you need to remain on Nuxt 2, but want to benefit from Nuxt 3 features in Nuxt 2, you can alternatively check out [how to get started with Bridge](/getting-started/bridge).
::

View File

@ -0,0 +1,23 @@
# Build Tooling
We use the following build tools by default:
- [Vite](https://vitejs.dev/) or [webpack](https://webpack.js.org/)
- [Rollup](https://rollupjs.org/)
- [PostCSS](https://postcss.org/)
- [esbuild](https://esbuild.github.io/)
For this reason, most of your previous `build` configuration in `nuxt.config` will now be ignored, including any custom babel configuration.
If you need to configure any of Nuxt's build tools, you can do so in your `nuxt.config`, using the new top-level `vite`, `webpack` and `postcss` keys.
In addition, Nuxt ships with TypeScript support. [Find out more](/docs/concepts/typescript).
## Steps
1. Remove `@nuxt/typescript-build` and `@nuxt/typescript-runtime` from your dependencies and modules.
1. Remove any unused babel dependencies from your project.
1. Remove any explicit core-js dependencies.
1. Migrate `require` to `import`.
<!-- TODO: Enabling webpack builder -->

View File

@ -0,0 +1,12 @@
# Server
In a built Nuxt 3 application, there is no runtime Nuxt dependency. That means your site will be highly performant, and ultra-slim. But it also means you can no longer hook into runtime Nuxt server hooks.
[Read more about the Nitro server engine](/docs/concepts/server-engine).
## Steps
1. Remove the `render` key in your `nuxt.config`.
1. Any files in `~/server/api` and `~/server/middleware` will be automatically registered; you can remove them from your `serverMiddleware` array.
1. Update any other items in your `serverMiddleware` array to point to files or npm packages directly, rather than using inline functions.
1. If you are adding any server hooks, such as `server:` or `vue-renderer:` you will need to remove these and wait for [nitropack](https://github.com/unjs/nitropack) support for runtime hooks and plugins.

View File

@ -0,0 +1,97 @@
---
title: Configuration
---
# Project Configuration
## `nuxt.config`
The starting point for your Nuxt app remains your `nuxt.config` file.
::alert{icon=📦}
Nuxt configuration will be loaded using [`unjs/jiti`](https://github.com/unjs/jiti) and [`unjs/c12`](https://github.com/unjs/c12).
::
### Migration
You should migrate to the new `defineNuxtConfig` function that provides a typed configuration schema.
::code-group
```ts [Nuxt 2]
export default {
// ...
}
```
```ts [Nuxt 3]
import { defineNuxtConfig } from 'nuxt3'
export default defineNuxtConfig({
// ...
})
```
#### ESM Syntax
Nuxt 3 is an [ESM native framework](/concepts/esm). Although [`unjs/jiti`](https://github.com/unjs/jiti) provides semi compatibility when loading `nuxt.config` file, avoid any usage of `require` and `module.exports` in this file.
1. Change `module.exports` to `export default`
1. Change `const lib = require('lib')` to `import lib from 'lib'`
#### Async Configuration
In order to make Nuxt loading behavior more predictable, async config syntax is deprecated. Consider using Nuxt hooks for async operations.
#### Dotenv
Nuxt has built-in support for loading `.env` files. Avoid directly importing it from `nuxt.config`.
## Modules
Nuxt and Nuxt Modules are now build-time-only.
### Migration
1. Move all your `buildModules` into `modules`.
2. Check for Nuxt 3 compatibility of modules.
::alert
If you are a module author, you can check out [more information about module compatibility](/docs/migration/module-authors) and [our module author guide](/docs/advanced/modules).
::
## TypeScript
It will be much easier to migrate your application if you use Nuxt's TypeScript integration. This does not mean you need to write your application in TypeScript, just that Nuxt will provide automatic type hints for your editor.
You can read more about Nuxt's TypeScript support [in the docs](/docs/concepts/typescript).
::alert{icon=📦}
Nuxt can type-check your app using [`vue-tsc`](https://github.com/johnsoncodehk/volar/tree/master/packages/vue-tsc) with `nuxi typecheck` command.
::
### Migration
1. Create a `tsconfig.json` with the following content:
```json
{
"extends": "./.nuxt/tsconfig.json"
}
```
1. Run `npx nuxi prepare` to generate `.nuxt/tsconfig.json`.
1. Install Volar following the instructions in the [docs](/docs/getting-started/introduction).
## Vue changes
There are a number of changes to what is recommended Vue best practice, as well as a number of breaking changes between Vue 2 and 3.
It is recommended to read the [Vue 3 migration guide](https://v3-migration.vuejs.org/) and in particular the [breaking changes list](https://v3-migration.vuejs.org/breaking-changes/).
It is not currently possible to use the Vue 3 migration build with Nuxt 3 RC.
## Vuex
Nuxt no longer provides a Vuex integration. Instead, the official Vue recommendation is to use `pinia`, which has built-in Nuxt support via a Nuxt module. [Find out more about pinia here](https://pinia.vuejs.org/).
If you want to keep using Vuex, you can manually migrate to Vuex 4 following [these steps](https://vuex.vuejs.org/guide/migrating-to-4-0-from-3-x.html).

View File

@ -0,0 +1,89 @@
# Modules
## Module Compatibility
Nuxt 3 has a basic backward compatibility layer for Nuxt 2 modules using `@nuxt/kit` auto wrappers. But there are usually steps to follow to make modules compatible with Nuxt 3 and sometimes, using Nuxt Bridge is required for cross-version compatibility.
We have prepared a [Dedicated Guide](/docs/advanced/modules) for authoring Nuxt 3 ready modules using `@nuxt/kit`. Currently best migration path is to follow it and rewrite your modules. Rest of this guide includes preparation steps if you prefer to avoid a full rewrite yet making modules compatibile with Nuxt 3.
::alert
You can check for a list of Nuxt 3 ready modules from [Nuxt Modules](https://modules.nuxtjs.org/?version=3.x).
::
### Plugin Compatibility
Nuxt 3 plugins are **not** fully backward compatible with Nuxt 2.
### Vue Compatibility
Plugins or components using the composition API need exclusive Vue 2 or Vue 3 support.
By using [vue-demi](https://github.com/vueuse/vue-demi) they should be compatible with both Nuxt 2 and 3.
## Module Migration
When Nuxt 3 users add your module, a compatible module container layer from `@nuxt/kit` is **automatically injected**, so as long as your code is following the guidelines below, it should continue working as-is.
### Test with `@nuxt/bridge`
Migrating to `@nuxt/bridge` is the first and most important step for supporting Nuxt 3.
If you have a fixture or example in your module, add `@nuxt/bridge` package to its config (see [example](/getting-started/bridge#update-nuxtconfig))
### Migrate from CommonJS to ESM
Nuxt 3 natively supports TypeScript and ECMAScript Modules. Please check [Native ES Modules](/concepts/esm) for more info and upgrading.
### Ensure plugins default export
If you inject a Nuxt plugin that does not have `export default` (such as global Vue plugins), ensure you add `export default () => { }` to the end of it.
::code-group
```js [Before]
// ~/plugins/vuelidate.js
import Vue from 'vue'
import Vuelidate from 'vuelidate'
Vue.use(Vuelidate)
```
```js [After]
// ~/plugins/vuelidate.js
import Vue from 'vue'
import Vuelidate from 'vuelidate'
Vue.use(Vuelidate)
export default () => { }
```
::
### Avoid runtime modules
With Nuxt 3, Nuxt is now a build-time-only dependency, which means that modules shouldn't attempt to hook into the Nuxt runtime.
Your module should work even if it's only added to [`buildModules`](/docs/directory-structure/nuxt.config#buildmodules) (instead of `modules`). For example:
- Avoid updating `process.env` within a Nuxt module and reading by a nuxt plugin; use [`runtimeConfig`](/docs/directory-structure/nuxt.config#publicruntimeconfig) instead.
- (*) Avoid depending on runtime hooks like `vue-renderer:*` for production
- (*) Avoid adding `serverMiddleware` by importing them inside the module. Instead, add them by referencing a file path so that they are independent of the module's context
(*) Unless it is for `nuxt dev` purpose only and guarded with `if (nuxt.options.dev) { }`.
::alert{type=info icon=🔎}
Continue reading about Nuxt 3 modules in the [Modules guide](/docs/advanced/modules).
::
### Use TypeScript (optional)
While it is not essential, most of the Nuxt ecosystem is shifting to use TypeScript, so it is highly recommended to consider migration.
::alert{icon=💡}
You can start migration by renaming `.js` files, to `.ts`. TypeScript is designed to be progressive!
::
::alert{icon=💡}
You can use TypeScript syntax for Nuxt 2 and 3 modules and plugins without any extra dependencies.
::

View File

@ -0,0 +1,17 @@
# Auto Imports
Nuxt 3 adopts a minimal friction approach, meaning wherever possible components and composables are auto-imported.
::alert{type=info}
In the rest of the migration documentation, you will notice that key Nuxt and Vue utilities do not have explicit imports. This is not a typo; Nuxt will automatically import them for you, and you should get full type hinting if you have followed [the instructions](/docs/migration/configuration#typescript) to use Nuxt's TypeScript support.
::
[Read more about auto imports](/concepts/auto-imports)
## Migration
1. If you have been using `@nuxt/components` in Nuxt 2, you can remove `components: true` in your `nuxt.config`. If you had a more complex setup, then note that the component options have changed somewhat. See the [components documentation](/docs/directory-structure/components) for more information.
::alert{type=info}
You can look at `.nuxt/types/components.d.ts` and `.nuxt/types/auto-imports.d.ts` to see how Nuxt has resolved your components and composable auto-imports.
::

View File

@ -0,0 +1,106 @@
# Meta Tags
Nuxt 3 provides several different ways to manage your meta tags.
1. Through your `nuxt.config`.
1. Through the `useMeta` [composable](/docs/usage/meta-tags#usemeta-composable)
1. Through [global meta components](/docs/usage/meta-tags#meta-components)
You can customize `title`, `base`, `script`, `style`, `meta`, `link`, `htmlAttrs` and `bodyAttrs`.
::alert{icon=📦}
Nuxt currently uses [`vueuse/head`](https://github.com/vueuse/head) to manage your meta tags, but implementation details may change.
::
[Read more about meta tags](/docs/usage/meta-tags).
## Migration
1. In your `nuxt.config`, rename `head` to `meta`. Consider moving this shared meta configuration into your `app.vue` instead. (Note that objects no longer have a `hid` key for deduplication.)
1. In your components, rename your `head` option to `meta`. If you need to access the component state, you should migrate to using `useMeta`. You might also consider using the built-in meta-components.
### Example: `useMeta`
::code-group
```vue [Nuxt 2]
<script>
export default {
data: () => ({
title: 'My App',
description: 'My App Description'
})
head () {
return {
title: this.title,
meta: [{
hid: 'description',
name: 'description',
content: this.description
}]
}
}
}
</script>
```
```vue [Nuxt 3]
<script setup>
const title = ref('My App')
const description = ref('My App Description')
// This will be reactive even you change title/description above
useMeta({
title,
meta: [{
name: 'description',
content: description
}]
})
</script>
```
::
### Example: built-in meta-components
Nuxt 3 also provides meta components that you can use to accomplish the same task. While these components look similar to HTML tags, they are provided by Nuxt and have similar functionality.
::code-group
```vue [Nuxt 2]
<script>
export default {
head () {
return {
title: 'My App',
meta: [{
hid: 'description',
name: 'description',
content: 'My App Description'
}]
}
}
}
</script>
```
```vue [Nuxt 3]
<template>
<div>
<Head>
<Title>My App</Title>
<Meta name="description" content="My app description"/>
</Head>
<!-- -->
</div>
</template>
```
::
::alert{icon=👉}
1. Make sure you use capital letters for these component names to distinguish them from native HTML elements (`<Title>` rather than `<title>`).
1. You can place these components anywhere in your template for your page.
::

View File

@ -0,0 +1,73 @@
# Plugins and Middleware
## Plugins
Plugins now have a different format, and take only one argument (`nuxtApp`). Read more in [the docs](/docs/directory-structure/plugins).
::code-group
```js [Nuxt 2]
export default (ctx, inject) => {
inject('injected', () => 'my injected function')
})
```
```ts [Nuxt 3]
export default defineNuxtPlugin(nuxtApp => {
// now available on `nuxtApp.$injected`
nuxtApp.provide('injected', () => 'my injected function')
// You can alternatively use this format, which comes with automatic type support
return {
provide: {
injected: () => 'my injected function'
}
}
})
```
::
::alert{icon=👉}
You can read more about the format of `nuxtApp` in [the docs](/docs/usage/nuxt-app).
::
### Migration
1. Migrate your plugins to use the `defineNuxtPlugin` helper function.
1. Remove any entries in your `nuxt.config` plugins array that are located in your `plugins/` folder. All files in this directory at the top level (and any index files in any subdirectories) will be automatically registered. Instead of setting `mode` to `client` or `server`, you can indicate this in the file name. For example, `~/plugins/my-plugin.client.ts` will only be loaded on client-side.
## Route middleware
Route middleware has a different format.
::code-group
```js [Nuxt 2]
export default function ({ store, redirect }) {
// If the user is not authenticated
if (!store.state.authenticated) {
return redirect('/login')
}
}
```
```ts [Nuxt 3]
export default defineNuxtRouteMiddleware((to, from) => {
const auth = useState('auth')
if (!auth.value.authenticated) {
return navigateTo('/login')
}
})
```
::
Much like Nuxt 2, route middleware placed in your `~/middleware` folder is automatically registered. You can then specify it by name in a component. However, this is done with `definePageMeta` rather than as a component option.
`navigateTo` is one of a number of route helper functions, which you can read more about in [the documentation about route middleware](/docs/directory-structure/middleware).
### Migration
1. Migrate your route middleware to use the `defineNuxtRouteMiddleware` helper function.
1. Any global middleware (such as in your `nuxt.config`) can be placed in your `~/middleware` folder with a `.global` extension, for example `~/middleware/auth.global.ts`.

View File

@ -0,0 +1,174 @@
# Pages and Layouts
## `app.vue`
Nuxt 3 provides a central entrypoint to your app via `~/app.vue`. If you don't have an `app.vue` file in your source directory, Nuxt will use its own default version.
This file is a great place to put any custom code that needs to be run once when your app starts up, as well as any components that are present on every page of your app. For example, if you only have one layout, you can move this to `app.vue` instead.
[Read more about `app.vue`](/docs/directory-structure/app).
### Migration
1. Consider creating an `app.vue` file and including any logic that needs to run once at the top-level of your app. You can check out [an example here](/docs/directory-structure/app).
## Layouts
If you are using layouts in your app for multiple pages, there is only a slight change required.
In Nuxt 2, the `<Nuxt>` component is used within a layout to render the current page. In Nuxt 3, layouts use slots instead, so you will have to replace that component with a `<slot />`. This also allows advanced use cases with named and scoped slots. [Read more about layouts](/docs/directory-structure/layouts).
You will also need to change how you define the layout used by a page using the `definePageMeta` compiler macro. Layouts will be kebab-cased. So `layouts/customLayout.vue` becomes `custom-layout` when referenced in your page.
### Migration
1. Replace `<Nuxt />` with `<slot />`
1. Use `definePageMeta` to select the layout used by your page.
1. Move `~/layouts/_error.vue` to `~/error.vue`. See [the error handling docs](/docs/usage/error-handling).
### Example: `~/layouts/custom.vue`
::code-group
```diff [layouts/custom.vue]
<template>
<div id="app-layout">
<main>
- <Nuxt />
+ <slot />
</main>
</div>
</template>
```
```diff [pages/index.vue]
<script>
+ definePageMeta({ layout: 'custom' })
export default {
- layout: 'custom'
}
</script>
```
::
## Pages
Nuxt 3 ships with an optional `vue-router` integration triggered by the existence of a `pages/` directory in your source directory. If you only have a single page, you may consider instead moving it to `app.vue` for a lighter build.
### Dynamic routes
The format for defining dynamic routes in Nuxt 3 is slightly different from Nuxt 2, so you may need to rename some of the files within `pages/`.
1. Where you previously used `_id` to define a dynamic route parameter you now use `[id]`.
1. Where you previously used `_.vue` to define a catch-all route, you now use `[...slug].vue`.
### Nested routes
In Nuxt 2, you will have defined any nested routes (with parent and child components) using `<Nuxt>` and `<NuxtChild>`. In Nuxt 3, these have been replaced with a single `<NuxtPage>` component.
### Page keys and keep-alive props
If you were passing a custom page key or keep-alive props to `<Nuxt>`, you will now use `definePageMeta` to set these options.
See [more about migrating Nuxt component hooks](/docs/migration/nuxt-hooks).
### Page and layout transitions
If you have been defining transitions for your page or layout directly in your component options, you will now need to use `definePageMeta` to set the transition.
[Read more about `pages/`](/docs/directory-structure/pages).
### Migration
1. Rename any pages with dynamic parameters to match the new format.
1. Update `<Nuxt>` and `<NuxtChild>` to be `<NuxtPage>`.
1. If you're using the Composition API, you can also migrate `this.$route` and `this.$router` to use `useRoute` and `useRouter` composables.
#### Example: Dynamic Routes
::code-group
``` [Nuxt 2]
- URL: /users
- Page: /pages/users/index.vue
- URL: /users/some-user-name
- Page: /pages/users/_user.vue
- Usage: params.user
- URL: /users/some-user-name/edit
- Page: /pages/users/_user/edit.vue
- Usage: params.user
- URL: /users/anything-else
- Page: /pages/users/_.vue
- Usage: params.pathMatch
```
``` [Nuxt 3]
- URL: /users
- Page: /pages/users/index.vue
- URL: /users/some-user-name
- Page: /pages/users/[user].vue
- Usage: params.user
- URL: /users/some-user-name/edit
- Page: /pages/users/[user]/edit.vue
- Usage: params.user
- URL: /users/anything-else
- Page: /pages/users/[...slug].vue
- Usage: params.slug
```
::
#### Example: Nested routes and `definePageMeta`
::code-group
```vue [Nuxt 2]
<template>
<div>
<NuxtChild keep-alive :keep-alive-props="{ exclude: ['modal'] }" :nuxt-child-key="$route.slug" />
</div>
</template>
<script>
export default {
transition: 'page' // or { name: 'page' }
}
</script>
```
```vue [Nuxt 3]
<template>
<div>
<NuxtPage />
</div>
</template>
<script setup>
// This compiler macro works in both <script> and <script setup>
definePageMeta({
// you can also pass a string or a computed property
key: route => route.slug,
transition: {
name: 'page',
},
keepAlive: {
exclude: ['modal']
},
})
</script>
```
::
## NuxtLink component
Most of the syntax and functionality are the same for the global [NuxtLink](/docs/usage/nuxt-link#nuxtlink) component. If you have been using the shortcut `<NLink>` format, you should update this to use `<NuxtLink>`.
`<NuxtLink>` is now a drop-in replacement for _all_ links, even external ones. You can read more about it, and how to extend it to provide your own link component, [in the docs](/docs/usage/nuxt-link#nuxtlink).

View File

@ -0,0 +1,148 @@
# Compponent Options
## `asyncData` and `fetch` component options
Nuxt 3 provides new options for [fetching data from an API](/docs/usage/data-fetching).
<!-- TODO: Intro to <script setup> -->
<!-- TODO: Mention about options compatibility with asyncData -->
### Isomorphic fetch
In Nuxt 2 you might use `@nuxtjs/axios` or `@nuxt/http` to fetch your data - or just the polyfilled global `fetch`.
In Nuxt 3 you can use a globally available `fetch` method that has the same API as [the Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) or `$fetch` method which is using [unjs/ohmyfetch](https://github.com/unjs/ohmyfetch). It has a number of benefits, including:
1. It will handle 'smartly' making [direct API calls](/concepts/server-engine#direct-api-calls) if it's running on the server, or making a client-side call to your API if it's running on the client. (It can also handle calling third-party APIs.)
2. Plus, it comes with convenience features including automatically parsing responses and stringifying data.
You can read more [about direct API calls](/concepts/server-engine#direct-api-calls) or [fetching data](/docs/usage/data-fetching).
### Using composables
Nuxt 3 provides new composables for fetching data: `useAsyncData` and `useFetch`. They each have 'lazy' variants (`useLazyAsyncData` and `useLazyFetch`), which do not block client-side navigation.
In Nuxt 2, you'd fetch your data in your component using a syntax similar to:
```ts
export default {
async asyncData({ params, $http }) {
const post = await $http.$get(`https://api.nuxtjs.dev/posts/${params.id}`)
return { post }
},
// or alternatively
fetch () {
this.post = await $http.$get(`https://api.nuxtjs.dev/posts/${params.id}`)
}
}
```
Within your methods and templates, you could use the `post` variable similar how you'd use any other piece of data provided by your component.
With Nuxt 3, you can perform this data fetching using composables in your `setup()` method or `<script setup>` tag:
```vue
<script setup>
// Define params wherever, through `defineProps()`, `useRoute()`, etc.
const { data: post, refresh } = await useAsyncData('post', () => $fetch(`https://api.nuxtjs.dev/posts/${params.id}`) )
// Or instead - useFetch is a convenience wrapper around useAsyncData when you're just performing a simple fetch
const { data: post, refresh } = await useFetch(`https://api.nuxtjs.dev/posts/${paramsÌ.id}`)
</script>
```
You can now use `post` inside of your Nuxt 3 template, or call `refresh` to update the data.
::alert{type=info}
Despite the names, `useFetch` is not a direct replacement of the `fetch()` hook. Rather, `useAsyncData` replaces both hooks and is most customizable; it can do more than simply fetching data from an endpoint. `useFetch` is a convenience wrapper around `useAsyncData` for simply fetching data fromn an endpoint.
::
### Migration
1. Replace the `asyncData` hook with `useAsyncData` or `useFetch` in your page/component.
1. Replace the `fetch` hook with `useAsyncData` or `useFetch` in your component.
## `head`
See [meta tag migration](/docs/migration/meta).
## `key`
You can now define a key within the `definePageMeta` compiler macro.
```diff [pages/index.vue]
- <script>
- export default {
- key: 'index'
- // or a method
- // key: route => route.fullPath
- }
+ <script setup>
+ definePageMeta({
+ key: 'index'
+ // or a method
+ // key: route => route.fullPath
+ })
</script>
```
### Migration
1. Migrate `key` from component options to `definePageMeta`.
## `layout`
See [layout migration](/docs/migration/pages-and-layouts).
## `loading`
This feature is not yet supported in Nuxt 3.
## `middleware`
See [middleware migration](/docs/migration/plugins-and-middleware).
## `scrollToTop`
This feature is not yet supported in Nuxt 3. If you want to overwrite the default scroll behavior of `vue-router`, you can do so in `~/app/router.options.ts` (see [docs](/docs/directory-structure/pages/#router-options)) for more info.
## `transition`
See [layout migration](/docs/migration/pages-and-layouts).
## `validate`
There is no longer a validate hook in Nuxt 3. Instead, you can create a custom middleware function, or directly throw an error in the setup function of the page.
```diff [pages/users/[id].vue]
- <script>
- export default {
- async validate({ params, query, store }) {
- return true // if valid
- }
- }
+ <script setup>
+ definePageMeta({
+ middleware: [
+ async function (to, from) {
+ const nuxtApp = useNuxtApp()
+ if (!valid) {
+ return abortNavigation('Page not found')
+ }
+ }
+ ]
+ })
</script>
```
## `watchQuery`
This is not supported in Nuxt 3. Instead, you can directly use a watcher to trigger refetching data.
```vue [pages/users/[id].vue]
<script setup>
const route = useRoute()
const { data, refresh } = await useFetch('/api/user')
watch(() => route.query, () => refresh())
</script>
```

View File

@ -0,0 +1,49 @@
# Runtime Config
If you wish to reference environment variables within your Nuxt 3 app, you will need to use runtime config.
When referencing these variables within your components, you will have to use the `useRuntimeConfig` composable in your setup method (or Nuxt plugin). In the Nitro portion of your app, you can import directly from `#config`.
[Read more about runtime config](/docs/usage/runtime-config).
## Migration
1. Add any environment variables you use in your app to your `publicRuntimeConfig` or `privateRuntimeConfig`.
1. Migrate `process.env` to `useRuntimeConfig` throughout the Vue part of your app.
## Example
::code-group
```ts [nuxt.config.ts]
import { defineNuxtConfig } from 'nuxt3'
export default defineNuxtConfig({
publicRuntimeConfig: {
BASE_URL: process.env.BASE_URL || 'https://nuxtjs.org'
},
privateRuntimeConfig: {
// variables that can only be accessed on server-side
},
})
```
```vue [pages/index.vue]
<script setup>
const config = useRuntimeConfig();
// instead of process.env.BASE_URL you will now access config.BASE_URL
</script>
```
```ts [server/api/hello.ts]
import config from '#config';
export default (req, res) => {
// you can now access config.BASE_URL
return {
baseURL: config.BASE_URL
}
}
```
::

View File

@ -0,0 +1,6 @@
---
navigation.collapse: true
layout.aside: true
layout.asideClass: ''
navigation.redirect: /docs/migration/overview
---