Nuxt 3 项目实战:从零搭建到生产环境部署全流程
1. 环境准备与项目初始化
第一次接触Nuxt 3时,我像大多数新手一样被它的高效所震撼,但也踩了不少坑。记得那天下午,我对着报错信息折腾了整整三小时才把项目跑起来。现在把这些经验整理出来,帮你避开我走过的弯路。
Node.js版本是第一个拦路虎。Nuxt 3要求Node.js版本≥18.0,但很多人的开发机可能还停留在Node 16甚至更早版本。建议直接安装最新的LTS版本(目前是20.x),用以下命令检查版本:
node -v如果版本不符,推荐使用nvm(Mac/Linux)或nvm-windows(Windows)管理多版本Node。这是我常用的切换命令:
nvm install 20 nvm use 20网络问题可能是第二个坑。由于某些CDN域名解析问题,初始化项目时可能会卡在下载模板阶段。我在北京和上海的服务器上都遇到过这个问题,解决方案是在hosts文件添加:
185.199.109.133 raw.githubusercontent.comWindows用户注意:hosts文件位于C:\Windows\System32\drivers\etc\,修改需要管理员权限。Mac/Linux用户在终端输入:
sudo nano /etc/hosts现在可以正式初始化项目了。推荐使用nuxi这个官方脚手架工具,它能自动生成最优项目结构:
npx nuxi@latest init my-project执行后会让你选择包管理器。个人推荐pnpm,它的磁盘占用比npm小60%,安装速度也更快。如果遇到选择困难,不妨试试这个组合命令:
npx nuxi@latest init my-project --packageManager=pnpm初始化完成后,用VS Code打开项目,你会看到这样的目录结构:
my-project/ ├── .nuxt/ # 构建生成文件 ├── node_modules/ # 依赖包 ├── public/ # 静态资源 ├── server/ # 服务器相关 ├── app.vue # 根组件 └── nuxt.config.ts # 配置文件2. 项目结构与核心配置
很多新手会困惑Nuxt 3的目录结构到底该怎么组织。经过五个项目的实战,我总结出一套高效目录方案:
src/ ├── assets/ # 需要编译的静态文件 │ └── scss/ │ └── global.scss ├── components/ # 公共组件 │ └── ui/ │ └── Button.vue ├── composables/ # 组合式函数 │ └── useFetchData.ts ├── pages/ # 自动生成路由 │ ├── index.vue │ └── blog/ │ └── [slug].vue └── utils/ # 工具函数 └── date.ts路由系统是Nuxt 3的亮点。只要在pages目录下创建.vue文件,就会自动生成对应路由。比如:
pages/index.vue→/pages/about.vue→/aboutpages/blog/[slug].vue→/blog/xxx(动态路由)
在app.vue中只需要保留最简结构:
<template> <NuxtPage /> </template>全局样式配置是个高频需求。先在assets/scss下创建global.scss,然后在nuxt.config.ts中添加:
export default defineNuxtConfig({ css: ['~/assets/scss/global.scss'], vite: { css: { preprocessorOptions: { scss: { additionalData: '@use "~/assets/scss/_variables.scss" as *;' } } } } })3. 开发实战技巧
数据获取是每个项目都绕不开的话题。Nuxt 3提供了四种方式:
- useAsyncData - 客户端获取
- useFetch - 简化版useAsyncData
- $fetch - 基于ohmyfetch的HTTP客户端
- useLazyFetch - 懒加载版本
这是我的常用模式:
<script setup> const { data: posts } = await useFetch('/api/posts', { pick: ['title', 'excerpt'], transform: (data) => data.filter(item => item.published) }) </script>SEO优化需要关注这几个配置:
// nuxt.config.ts export default defineNuxtConfig({ app: { head: { titleTemplate: '%s - 我的网站', meta: [ { charset: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' } ] } } })在页面组件中还可以动态设置:
<script setup> useHead({ title: '文章详情', meta: [ { name: 'description', content: '这是文章详情页' } ] }) </script>性能优化方面,我强烈推荐开启以下配置:
// nuxt.config.ts export default defineNuxtConfig({ nitro: { compressPublicAssets: true, }, experimental: { payloadExtraction: true, inlineSSRStyles: true } })4. 生产环境部署
打包构建是上线前的最后一步:
npm run build这会生成.output目录,里面包含:
.output/ ├── public/ # 静态资源 ├── server/ # 服务端代码 └── nitro.json # 服务配置方案一:直接Node运行
上传.output目录到服务器后:
node ./output/server/index.mjs这种方式的缺点是进程容易挂掉,适合临时测试。我在内网演示环境经常这么用。
方案二:PM2集群模式
先全局安装PM2:
npm install -g pm2创建ecosystem.config.js:
module.exports = { apps: [{ name: 'my-nuxt-app', script: './output/server/index.mjs', instances: 'max', exec_mode: 'cluster', env: { NITRO_PORT: 3000, NODE_ENV: 'production' } }] }启动命令:
pm2 start ecosystem.config.jsNginx反向代理配置示例:
server { listen 80; server_name example.com; location / { proxy_pass http://localhost:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; } }记得重载Nginx配置:
nginx -s reload监控与维护方面,这些PM2命令很实用:
# 查看日志 pm2 logs my-nuxt-app # 开机自启 pm2 startup pm2 save # 性能监控 pm2 monit在阿里云ECS上部署时,我发现内存经常吃紧。后来通过配置PM2的max_memory_restart参数解决了问题:
// ecosystem.config.js module.exports = { apps: [{ // ... max_memory_restart: '1G', max_restarts: 5 }] }