# 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 recommanded to do it 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 yet need to be implemented for Nuxt 3 and some are new in Nuxt 3 (and Bridge). Noticable and/or Breaking changes with Nuxt 3 other than the requirements of bridge are: ::list{type=warning} - Vue app templates are rewritten - Vue upgraded to `3.x` - Using `` 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 comparation 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**, as long as your code is following below guidelines, 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)) ### Avoid CommonJS syntax Nuxt natively supports TypeScript and ECMAScript Modules. #### Update the imports ::code-group ```js [Before] const lib = require('lib') ``` ```js [After] import lib from 'lib' // or using code-splitting const lib = await import('lib').then(e => e.default || e) ``` :: #### Update the exports ::code-group ```js [Before] module.exports = ... ``` ```js [After] export default ... // or using named export export const hello = ... ``` :: #### Avoid using specific CJS syntax Avoid the usage of `__dirname` and `__filename` as much as possible. ### 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, we changed how the build process should work and modules hooking into the Nuxt runtime is now considered an anti-pattern and will not work. Your module should work fine by adding only to [`buildModules`](/docs/directory-structure/nuxt.config#buildmodules) (instead of `modules`): - 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. Add them by referencing to 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 Nuxt ecosystem is shifting to use TypeScript, 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. ::