# 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
::

In table below there is an overall feature comparison table:

Feature / Version         | Nuxt 2  | Nuxt 3   | Changes required
--------------------------|---------|----------|------------------
Vue Version               | 2       | 3        | Yes
`app.vue`                 | ❌      | ✅        | -
Assets                    | ✅      | ✅        | No
Components                | ✅      | ✅        | No
Layouts                   | ✅      | ✅        | Yes
Error Pages               | ✅      | 🚧        | Yes
Pages                     | ✅      | ✅        | Yes
Pages: Dynamic Params     | ✅      | ✅        | Yes
Pages: _.vue              | ✅      | ✅        | No
Plugins                   | ✅      | ✅        | Yes (compatible by default)
Store                     | ✅      | 🚧        | Yes
Transitions               | ✅      | 🚧        | ?
Suspense                  | ❌      | ✅        | -
Options API: `asyncData`  | ✅      | 🚧        | ?
Options API: `fetch`      | ✅      | 🚧        | ?

### 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 needs 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 module. Instead, add them by referencing a file path so that they are independent of module context

(*) Unless it is for `nuxt dev` purpose only and guarded with `if (nuxt.options.dev) { }`.

### Add module meta

Ensure your module is exporting meta object.

\[TODO\]

### 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 simply 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.
::
