Vue3 + Axios + 多环境部署 + 国际化 全套落地方案
一、前言
全程使用 Nuxt4 开发。从最开始疯狂踩 SSR、接口 502、打包报错、部署失败,到最后彻底跑通全流程,我把所有真实踩坑 + 解决方案全部整理在这里。
二、我的项目背景
-
项目类型:智能仓储 / 工厂 3D 可视化后台系统
-
技术栈:Vue3 + Nuxt4 + Three.js + Axios + i18n 国际化
-
核心需求:
- 3D 场景渲染
- 接口请求统一封装
- 中英文切换
- 开发 / 生产环境自由切换
- 打包后不改代码、不重新打包就能换接口
- 稳定部署,不 502、不报错
三、我踩过的所有 Nuxt4 大坑(全部真实)
1. 打包后访问报错:[nuxt] instance unavailable
原因 在 axios 工具文件最外层直接写:
js
arduino
const config = useRuntimeConfig()
SSR 服务端执行时,还没有实例,直接崩溃。
最终正确写法 把 useRuntimeConfig() 放到 请求拦截器里:
js
arduino
service.interceptors.request.use((config) => {
const runtimeConfig = useRuntimeConfig()
config.baseURL = runtimeConfig.public.apiBase
})
2. 接口代理配置错误,一直 502
错误写法
ts
vbnet
routeRules: {
'/api/**': {
proxy: '{{runtimeConfig.public.apiBase}}/api/**'
}
}
原因 :routeRules 不支持运行时变量,只会当成字符串,所以代理地址无效。
正确方案
- 开发环境:用 vite 代理
- 生产环境:用运行时环境变量
3. 服务端渲染(SSR)不适合我的项目
我总结了一个超级实用的判断标准:
表格
| 项目类型 | 是否适合 SSR |
|---|---|
| 官网、电商、需要 SEO | ✅ 适合 |
| 后台系统、3D 可视化、内部系统 | ❌ 不适合 |
我的项目属于后台系统 + 3D 渲染,直接关闭 SSR:
ts
arduino
export default defineNuxtConfig({
ssr: false
})
关闭后:
- localStorage 正常用
- 不再报实例错误
- 部署超级简单
- 接口不再 502
四、开发 / 生产环境一套代码搞定
1. 开发环境(vite 代理)
ts
css
vite: {
server: {
proxy: {
'/api': {
target: 'http://10.102.129.12:18088',
changeOrigin: true
}
}
}
}
2. 生产环境(运行时配置)
ts
css
runtimeConfig: {
public: {
apiBase: '' // 留空,环境变量覆盖
}
},
nitro: {
host: '0.0.0.0',
port: 3000
}
五、Axios 封装最终版(可直接复制)
ts
javascript
import axios from 'axios'
const service = axios.create({
baseURL: '/api',
timeout: 10000
})
service.interceptors.request.use((config) => {
if (process.env.NODE_ENV === 'production') {
const runtimeConfig = useRuntimeConfig()
config.baseURL = runtimeConfig.public.apiBase
}
const token = process.client ? localStorage.getItem('factory_token') : null
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
})
service.interceptors.response.use((response) => {
const res = response.data
if (res.code !== 'SUCCESS') return Promise.reject(res)
return res.records
})
export const request = {
get: (url, params) => service.get(url, { params }),
post: (url, data) => service.post(url, data),
put: (url, data) => service.put(url, data),
delete: (url, params) => service.delete(url, { params })
}
export default service
六、国际化 i18n 配置(URL 不带前缀)
ts
css
i18n: {
locales: ['zh', 'en'],
defaultLocale: 'zh',
strategy: 'no_prefix',
detectBrowserLanguage: false
}
七、生产环境启动命令
PowerShell
powershell
bash
$env:NUXT_PUBLIC_API_BASE="http://10.102.129.12:18088"
node .output/server/index.mjs
Windows 一键启动脚本 start.bat
bat
bash
@echo off
set NUXT_PUBLIC_API_BASE=http://10.102.129.12:18088
node .output/server/index.mjs
pause
Docker 部署(目录挂载,不用重新打包)
yaml
yaml
version: '3.8'
services:
nuxt-app:
image: node:20-alpine
volumes:
- ./.output:/app
ports:
- "3000:3000"
environment:
- NUXT_PUBLIC_API_BASE=http://10.102.129.12:18088
command: ["node", "server/index.mjs"]
八、nuxt 配置文件
php
export default defineNuxtConfig({
ssr: true,
// 只保留最干净的配置
modules: [
'@pinia/nuxt',
'@element-plus/nuxt',
'@nuxtjs/i18n',
'@pinia-plugin-persistedstate/nuxt'
],
css: ['~/assets/css/main.css'],
elementPlus: {
// 配置图标组件前缀,设置为 'ElIcon' 即可启用自动导入
icon: "ElIcon",
// 如果你需要自定义主题,可以设置为 'scss'
// importStyle: 'scss',
},
i18n: {
// 指定翻译文件存放的目录
langDir: '',
// 配置支持的语言列表
locales: [
{
code: 'zh',
language: 'zh',
file: 'zh.json',
name: '简体中文'
},
{
code: 'en',
language: 'en',
file: 'en.json',
name: 'English'
},
],
// 默认语言
defaultLocale: 'en',
strategy: 'no_prefix',
// 是否检测浏览器语言并进行重定向
detectBrowserLanguage: {
useCookie: true, // 使用cookie保存用户语言选择
cookieKey: 'i18n_redirected', // cookie的key
redirectOn: 'root', // 仅在访问根路径时检测
},
},
runtimeConfig: {
public: {
apiBase: "", // 运行时覆盖
},
},
nitro: {
compressPublicAssets: true,
minify: true,
devProxy: {
'/web': {
target: 'http://10.102.129.12:18088/web',
changeOrigin: true,
}
},
// routeRules: {
// "/web/**": {
// proxy: 'http://10.102.129.12:18088/web/**'
// }
// }
},
vite: {
ssr: {
noExternal: ['vue']
}
}
})
九、结束语
这篇文章完全来自 我真实的 Nuxt4 实战提问与踩坑历史,从零基础到全流程打通,希望能帮助到正在做 Nuxt4 后台、可视化、3D 项目的同学。
如果你也在踩坑,欢迎交流~