Nuxt4 线上部署踩坑实录:WWW/裸域名跨域、HTTPS证书报错、伪SSR深度解析
近期完成 Nuxt4 企业官网线上部署,全程踩遍生产环境高频坑点:www 域名与裸域名跨域冲突、HTTPS证书域名不匹配、Nginx反向代理配置、Nuxt4看似SSR实则客户端注水渲染。
很多本地开发完全正常的代码,上线后直接栏目空白、接口500、跨域报错、服务频繁重启。本文结合真实生产报错日志、根因分析、最终落地解决方案,帮大家一次性避开 Nuxt4 生产部署全套陷阱。
一、项目背景与初始部署问题
1.1 基础环境
- 前端框架:Nuxt 4.0(Vue3 同构框架)
- 后端服务:Midway Node 接口服务(7001端口)
- 部署服务:PM2 进程守护 + Nginx 反向代理 + HTTPS 证书
- 业务域名:
www.example.com/example.com
1.2 初始故障现象
项目初期仅配置 带 www 域名 https://www.example.com,出现诡异兼容性问题:
- 带 www 访问:网站首页、所有栏目浏览器访问正常,无报错;
- 裸域名访问(集团内网默认不带www):
https://example.com仅首页正常,所有子栏目空白; - 控制台固定报错:跨域冲突 + TLS证书域名不匹配 + 接口返回 undefined;
- 服务端日志:
ERR_TLS_CERT_ALTNAME_INVALID证书异常、菜单数据menuData.value: undefined。
二、核心故障1:WWW域名与裸域名跨域冲突(根源+解决)
2.1 报错本质
浏览器同源策略限制:二级域名不互通
example.com(裸域名) ≠ www.example.com(子域名)
问题链路:
裸域名访问页面 → 页面渲染后,前端接口地址硬编码为 www.example.com → 浏览器判定「裸域名页面请求 www 域名接口」→ 跨域拦截 → 栏目数据请求失败 → 页面空白。
2.2 隐藏深坑:Node SSR 与浏览器差异
很多人只排查浏览器跨域,忽略 Nuxt SSR 服务端TLS校验:
- 浏览器:HTTPS证书校验宽松,访问 www 和裸域名容错性高,页面能正常展示;
- Node.js SSR:严格校验证书备用域名(altnames) ,证书仅备案了
example.com,未包含www.example.com; - 最终报错:
Host: www.example.com. is not in the cert's altnames: DNS:example.com。
这也是为什么本地开发完美运行,线上直接炸机的核心原因:本地无HTTPS校验、无域名区分。
2.3 最终根治方案(生产最优)
方案1:Nginx 强制301重定向(域名统一,彻底杜绝跨域)
统一域名入口,所有访问强制跳转为裸域名,从根源消除双域名冲突:
nginx
# www域名强制重定向到裸域名
server {
listen 80;
listen 443 ssl;
server_name www.example.com;
ssl_certificate /xxx/example.com.pem;
ssl_certificate_key /xxx/example.com.key;
return 301 https://example.com$request_uri;
}
方案2:Nuxt 服务端内网请求(解决SSR证书报错)
核心原则:SSR 永远不走公网HTTPS域名
Nuxt SSR 阶段直接请求服务器本机内网接口 http://127.0.0.1:7001/api/public,避开公网域名、HTTPS证书校验、跨域三重问题;浏览器客户端正常走公网域名。
为避免全局修改业务代码,采用 服务端专属插件拦截(零侵入业务):
typescript
// plugins/fix-api-url.server.ts 仅SSR生效
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.hooks.hook("fetch:request", (ctx) => {
// 服务端自动将公网域名接口替换为内网本机接口
ctx.url = ctx.url.replace(
/^https?:\/\/.*?\/OfficialWebsiteServer\/api\/public/,
"http://127.0.0.1:7001/api/public"
);
});
});
优势:所有页面、store、组件的 useFetch 自动适配,原有业务代码一行不用改。
三、核心故障2:HTTPS证书配置与Nginx部署坑点
3.1 证书报错根因
SSL 证书仅绑定 裸域名 example.com,未配置泛域名/ www 子域名,导致:
- 浏览器访问 www 域名:轻微证书警告,可正常访问;
- Node SSR 服务请求 www 域名:直接拒绝连接,抛出 TLS 错误,接口数据 undefined。
3.2 生产可用完整Nginx HTTPS配置
nginx
# 裸域名主服务配置
server {
listen 80;
server_name example.com;
# http强制跳转https
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com;
# 证书配置
ssl_certificate /mnt/ssl/example.com.pem;
ssl_certificate_key /mnt/ssl/example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
# Nuxt反向代理
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# www域名全部重定向
server {
listen 80;
listen 443 ssl;
server_name www.example.com;
ssl_certificate /mnt/ssl/example.com.pem;
ssl_certificate_key /mnt/ssl/example.com.key;
return 301 https://example.com$request_uri;
}
3.3 避坑总结
- 证书优先申请泛域名证书 ,同时覆盖
example.com和*.example.com; - 无泛域名证书则强制域名统一,不要同时启用双域名访问;
- Nuxt SSR 绝对禁止走公网HTTPS,内网请求是生产最优解。
四、深度解惑:Nuxt4 不是真正的纯服务端渲染
很多开发者误区:Nuxt4 默认SSR = 全程服务端渲染、无客户端渲染。这是完全错误的。
4.1 Nuxt4 真实渲染模式:通用渲染(同构渲染)
Nuxt4 官方默认渲染模式为 Universal Rendering(通用渲染),并非传统纯SSR,核心流程分为两步:
- 首屏服务端渲染:首次访问页面,Nitro 服务端执行组件渲染、接口请求,生成完整HTML、CSS返回浏览器,实现首屏秒开、SEO友好;
- 客户端注水激活(Hydration) :页面加载完成后,浏览器会下载完整JS资源,接管页面路由、事件、数据响应,后续所有页面跳转、接口请求全部在客户端执行。
4.2 为什么说它不是「真正纯SSR」?
传统纯SSR(如Java Thymeleaf、PHP模板):每一次页面跳转、每一次数据刷新,都由服务端重新渲染完整页面,客户端仅负责展示。
而 Nuxt4 的渲染逻辑:
- 仅首次加载走服务端;
- 后续所有路由跳转、栏目切换、数据更新,全部是客户端SPA渲染;
- 本质是:首屏SSR + 后续SPA 的混合模式。
4.3 对应本次故障的核心关联
本次栏目空白、跨域报错,完全印证了 Nuxt4 的渲染特性:
- 首页静态内容多、无动态接口依赖,首屏SSR渲染完成后正常展示;
- 子栏目依赖接口数据,页面首次SSR渲染时,Node 因证书报错请求失败,数据为空;
- 客户端注水完成后,二次请求出现双域名跨域冲突,最终页面空白;
4.4 如何开启 Nuxt4 真正纯服务端渲染?
如需实现全程服务端渲染、无客户端注水,需手动配置路由预渲染:
typescript
// nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
// 全站预渲染,无客户端JS注水
'/**': { prerender: true, noScripts: true }
}
})
适用场景:纯展示官网、静态页面;缺点:无法实现动态交互、实时数据更新。
五、完整生产部署最终规范(总结)
5.1 接口请求规范(零报错)
- SSR 服务端:统一请求
http://127.0.0.1:7001/api/public内网地址,规避证书、跨域问题; - 客户端浏览器:请求公网HTTPS域名;
- 通过
.server.ts专属插件自动区分环境,零侵入业务代码。
5.2 域名规范
- 统一单域名入口,Nginx 301 重定向杜绝 www/裸域名双入口;
- SSL 证书优先使用泛域名,覆盖所有子域名。
5.3 Nuxt4 部署认知规范
- 默认是通用渲染(首屏SSR+后续SPA),非纯服务端渲染;
- 线上90%的接口报错、页面空白,都来自「服务端和客户端请求环境不一致」;
- 本地开发无问题,是因为本地无HTTPS校验、无域名区分、无注水差异。
六、写在最后
Nuxt4 本地开发体验极佳,但生产部署隐藏大量「同构框架专属坑点」:域名同源策略、Node严格TLS校验、SSR/客户端双环境差异、渲染模式混淆。
本次故障的核心不是代码Bug,而是对Nuxt渲染机制、线上网络环境、证书规则的认知缺失。通过域名统一、内网SSR请求、服务端插件拦截,最终彻底解决跨域、证书、页面空白三大生产问题。
希望这篇真实踩坑实录,能帮正在部署Nuxt线上项目的开发者少走弯路!
如果你想把这篇文章发布到掘金之类的技术平台,工作任务模式可以帮你优化标题、增加开篇钩子、调整排版,要不要用它继续?