当然!下面是一个 最小可运行的 Vue 3 项目迁移到 Nuxt 3 的完整示例,包含原始 Vue 3 项目结构、迁移后的 Nuxt 3 结构、关键文件内容对比,以及运行说明。
🧩 原始 Vue 3 项目(Vite + Vue 3 + Pinia + Vue Router)
目录结构
vue3-app/
├── src/
│ ├── main.ts
│ ├── App.vue
│ ├── router/
│ │ └── index.ts
│ ├── views/
│ │ ├── Home.vue
│ │ └── About.vue
│ ├── stores/
│ │ └── counter.ts
│ └── components/
│ └── HelloWorld.vue
├── public/
│ └── favicon.ico
├── index.html
└── package.json
关键文件内容
src/main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.mount('#app')
src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
import Home from '@/views/Home.vue'
import About from '@/views/About.vue'
export default createRouter({
history: createWebHistory(),
routes: [
{ path: '/', component: Home },
{ path: '/about', component: About }
]
})
src/stores/counter.ts
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
actions: {
increment() {
this.count++
}
}
})
src/views/Home.vue
<template>
<div>
<h1>Home</h1>
<p>Count: {{ counter.count }}</p>
<button @click="counter.increment">+</button>
<router-link to="/about">Go to About</router-link>
</div>
</template>
<script setup>
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
</script>
✅ 迁移后的 Nuxt 3 项目结构
nuxt3-app/
├── app.vue
├── nuxt.config.ts
├── pages/
│ ├── index.vue ← 替代 Home.vue
│ └── about.vue ← 替代 About.vue
├── stores/
│ └── counter.ts ← 同名,位置不变
├── components/
│ └── HelloWorld.vue
├── public/
│ └── favicon.ico
└── package.json
注意:没有 router、没有 main.ts、没有 App.vue(被 app.vue 替代)
🔁 迁移后关键文件内容
app.vue(替代原 App.vue + main.ts)
<template>
<div>
<NuxtPage />
</div>
</template>
<style>
body {
margin: 0;
font-family: sans-serif;
}
</style>
<NuxtPage /> 自动渲染当前路由组件。
pages/index.vue(原 Home.vue)
<template>
<div>
<h1>Home</h1>
<p>Count: {{ counter.count }}</p>
<button @click="counter.increment">+</button>
<NuxtLink to="/about">Go to About</NuxtLink>
</div>
</template>
<script setup>
// 自动从 stores/ 导入
const counter = useCounterStore()
</script>
✅ NuxtLink 替代 router-link
✅ useCounterStore() 自动可用(无需 import)
pages/about.vue
<template>
<div>
<h1>About</h1>
<NuxtLink to="/">Back to Home</NuxtLink>
</div>
</template>
stores/counter.ts(完全不变)
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({ count: 0 }),
actions: {
increment() {
this.count++
}
}
})
Nuxt 3 会自动扫描 stores/ 并注册 Pinia。
nuxt.config.ts
export default defineNuxtConfig({
// 默认已启用 Vue 3 + Vite + Pinia
devtools: { enabled: true },
compatibilityDate: '2026-02-11'
})
无需额外配置即可使用 Pinia 和文件路由。
package.json(关键依赖)
{
"name": "nuxt3-app",
"private": true,
"scripts": {
"dev": "nuxt dev",
"build": "nuxt build",
"generate": "nuxt generate",
"preview": "nuxt preview"
},
"dependencies": {
"nuxt": "^3.15.0",
"vue": "^3.5.0",
"pinia": "^2.2.0"
}
}
使用 npx nuxi init 创建的项目已包含这些。
▶️ 如何运行
-
安装依赖:
npm install
-
启动开发服务器:
npm run dev
-
访问:
- http://localhost:3000 → Home 页面
- http://localhost:3000/about → About 页面
-
构建静态站点(SSG):
npm run generate
输出到 .output/public/
-
构建 SSR 应用:
npm run build
npm run preview # 预览 SSR 效果
✅ 迁移成功验证点
| 功能 | 是否工作 |
|---|---|
| 路由跳转(Home ↔ About) | ✅ |
| Pinia 状态管理(计数器) | ✅ |
| 无需手动 import 组件/Store | ✅ |
| SEO 友好(查看页面源码含内容) | ✅(SSR/SSG 模式下) |
📦 补充建议
-
若使用 UI 库(如 Element Plus),创建
plugins/element-plus.client.ts。 -
若需全局 CSS,放在
assets/并在nuxt.config.ts中引入:css: ['~/assets/main.css']
-
异步数据用
useAsyncData:const { data } = await useAsyncData('posts', () => $fetch('/api/posts'))