Nuxt在使用过程中的一些小总结(二)

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,出现诡异兼容性问题:

  1. 带 www 访问:网站首页、所有栏目浏览器访问正常,无报错;
  2. 裸域名访问(集团内网默认不带www):https://example.com 仅首页正常,所有子栏目空白
  3. 控制台固定报错:跨域冲突 + TLS证书域名不匹配 + 接口返回 undefined;
  4. 服务端日志: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 避坑总结

  1. 证书优先申请泛域名证书 ,同时覆盖 example.com*.example.com
  2. 无泛域名证书则强制域名统一,不要同时启用双域名访问;
  3. Nuxt SSR 绝对禁止走公网HTTPS,内网请求是生产最优解。

四、深度解惑:Nuxt4 不是真正的纯服务端渲染

很多开发者误区:Nuxt4 默认SSR = 全程服务端渲染、无客户端渲染。这是完全错误的

4.1 Nuxt4 真实渲染模式:通用渲染(同构渲染)

Nuxt4 官方默认渲染模式为 Universal Rendering(通用渲染),并非传统纯SSR,核心流程分为两步:

  1. 首屏服务端渲染:首次访问页面,Nitro 服务端执行组件渲染、接口请求,生成完整HTML、CSS返回浏览器,实现首屏秒开、SEO友好;
  2. 客户端注水激活(Hydration) :页面加载完成后,浏览器会下载完整JS资源,接管页面路由、事件、数据响应,后续所有页面跳转、接口请求全部在客户端执行

4.2 为什么说它不是「真正纯SSR」?

传统纯SSR(如Java Thymeleaf、PHP模板):每一次页面跳转、每一次数据刷新,都由服务端重新渲染完整页面,客户端仅负责展示。

而 Nuxt4 的渲染逻辑:

  • 首次加载走服务端;
  • 后续所有路由跳转、栏目切换、数据更新,全部是客户端SPA渲染
  • 本质是:首屏SSR + 后续SPA 的混合模式。

4.3 对应本次故障的核心关联

本次栏目空白、跨域报错,完全印证了 Nuxt4 的渲染特性:

  1. 首页静态内容多、无动态接口依赖,首屏SSR渲染完成后正常展示;
  2. 子栏目依赖接口数据,页面首次SSR渲染时,Node 因证书报错请求失败,数据为空;
  3. 客户端注水完成后,二次请求出现双域名跨域冲突,最终页面空白;

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线上项目的开发者少走弯路!

如果你想把这篇文章发布到掘金之类的技术平台,工作任务模式可以帮你优化标题、增加开篇钩子、调整排版,要不要用它继续?

相关推荐
2601_958352904 小时前
A-59U 仅 37mm 却集成 USB + 双波束?
前端·回声消除·语音模块·降噪处理·降噪消回音
泯泷10 小时前
那段文字是谁删的?Yjs 14 正式版之前,一套删除归属方案的实现与边界
前端·javascript·算法
野槐12 小时前
前端项目优化(有了我,会发生...)
前端
aa小小13 小时前
【无标题】
前端
计算机魔术师14 小时前
还在单线程跟 AI 聊天?Claude Code 并行多会话让你一个人干三个人的活
前端
志尊宝14 小时前
Vue3 零基础每日笔记(038):亲手封装 useDebounceFn 与 useThrottleFn——高频事件的流量阀
前端·javascript·vue·html·vue3
JavaGuide14 小时前
对标 MinIO!全新一代分布式文件系统正式发布
前端·后端
风骏时光牛马14 小时前
AI驱动自动化业务工作流搭建实践
前端
码云之上15 小时前
Skill 里的脚本终于能跑了,星悟接 CubeSandbox 的纪实
前端·人工智能·前端框架