Top Tips for Migrating Your Vue.js Project to Nuxt 3

Introduction

Are you considering migrating your Vue.js project to Nuxt 3? Transitioning between frameworks can be a transformative step, and our experts are here to guide you through the process. In this comprehensive guide, we’ll share top tips and insights to ensure a seamless migration and help you make the most of Nuxt 3’s powerful features. Let’s begin.

Setup a New Nuxt 3 Project

Start by creating a new Nuxt 3 project using command npx nuxi init <PROJECT_NAME>.

Links in page <head> section

// === [Vue 3] /index.html
<html lang="en">
  <head>
    <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Bubblegum Sans&display=swap">
  </head>
</html>

// === [Nuxt 3] /nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      link: [
        { rel: 'stylesheet', href: 'https://fonts.googleapis.com/css?family=Bubblegum Sans&display=swap' },
      ],
    },
  },
});
  

Global CSS

// === [Vue 3] /src/main.js
import './style.css';
// CSS file: /src/style.css

// === [Nuxt 3] /nuxt.config.ts
export default defineNuxtConfig({
  css: [
    '@/assets/css/main.scss',
  ],
});
// CSS file: /assets/css/main.scss
  

import.meta

By default using import.meta will throw error (esbuild plugin) [esbuild] (.nuxt/dist/server/_nuxt/…) “import.meta” is not available in the configured target environment (“es2019”) and will be empty during nuxt generate. The following setting will allow usage of import.meta and window.
// === [Nuxt 3] /nuxt.config.ts
export default defineNuxtConfig({
  nitro: {
    esbuild: {
      options: {
        target: 'node18',
      }
    }
  },
});
// Note: Change node18 to the node version that you are using
  

Entry Point

Vue 3: /index.html
Nuxt 3: /app.vue

Modify <head> Settings

// === [Vue 3] /index.html
<html lang="en">
  <head>
    <meta name="description" content="..." />
    <title>...
  </head>
</html>

// === [Vue 3] /src/*.vue
document.title = ...;
document.querySelector('meta[name="description"]').setAttribute('content', ...);

// === [Nuxt 3] /pages/*.vue, /components/*.vue, /composables/*.ts...
useSeoMeta({
  description: () => ...,
  title: () => ...,
});
  

Routing

// === [Vue 3] /index.html
<html lang="en">
  <head>
    <script async type="module" src="/src/main.js">
  </head>
</html>

// === [Vue 3] /src/main.js
import { createApp } from 'vue';

import App from '@/App.vue';
const app = createApp(App);

import router from '@/router';
app.use(router);

app.mount('#app');

// === [Vue 3/Vue Router] src/router/index.js
import { createRouter, createWebHistory } from 'vue-router';

const routes = [
  {
    path: '/',
    component: () => import('@/components/index.vue'),
  },
  {
    path: '/about',
    component: () => import('@/components/AboutUs.vue'),
  },
];

const router = createRouter({
  history: createWebHistory(),
  routes,
});

export default router;

// === [Vue 3] /src/components/index.vue
<template>
  <h1>Hello World
</template>

// === [Vue 3] /src/components/AboutUs.vue
<template>
  <h1>About Us
</template>

// === [Nuxt 3] /pages/index.vue
// Note: Creating components within the /pages folder will automatically create a route, index.vue is the root (/)
<template>
  <h1>Hello World
</template>

// === [Nuxt 3] /pages/about.vue
// Creates route /about
<template>
  <h1>About Us
</template>
  

Asset Files

Images, audio, video files etc.
Vue 3: Folder /src/assets/*, url reference new URL(`/src/assets/images/${fileName}`, import.meta.url).href
Nuxt 3: Folder /assets/*, url reference new URL(`../assets/img/${fileName}`, import.meta.url).href

Composable

Nuxt 3: Composables will be automatically imported as long as they are placed in folder /composables
// === Vue 3
import { computed } from 'vue';
import useTimer from '@/composables/useTimer.js';

const counter = computed(() => { ... });
const timer = useTimer();

// === Nuxt 3
// Note: computed and useTimer can be used directly without import
const counter = computed(() => { ... });
const timer = useTimer();
  

Static Hosting

// === Vue 3
yarn build
// Copy all files from folder /dist/ to remote server

// === Nuxt 3
yarn generate
// Copy all files from folder /.output/public/ to remote server
  
Share: