uni-app H5 端 SEO 优化需在 SSR 云函数中用 ${appInstance.$data.title}动态插入 TDK,因 asyncData/serverPrefetch 预取数据并注入服务端 HTML 的 <head>;uni build –ssr 生成的是 Node.js 可执行包而非静态 HTML 文件,须部署至 uniCloud 云函数且 H5 域名指向该函数。
uni-app H5 端 SEO 优化:title/description/keywords 怎么动态写进 HTML?
不能靠 uni.setnavigationbartitle 或pages.json里的 meta 字段——这些只影响客户端渲染后的 dom,ssr 场景下搜索引擎根本看不到。
真实生效的 TDK 必须在服务端拼进 HTML 字符串的 <head> 里。关键点是:数据得从 asyncData 或serverPrefetch提前拿到,再透传给云函数模板。
-
asyncData更适合页面级 TDK,它返回的对象会自动合并到组件data,后续可在云函数中用appInstance.$data.title取到 - 避免在
mounted里改document.title——SSR 已生成静态 HTML,这时改只影响浏览器,对爬虫无效 - 如果用了
uniCloud,云函数里拼 HTML 时别直接写死字符串,要用${appInstance.$data.title}这种插值,否则所有页面 TDK 都一样
uni-app SSR 配置:为什么 uni build --ssr 后没生成 HTML 文件?
因为 uni-app 的 SSR 不是纯静态站点生成(SSG),而是「按需服务端渲染」——它不产出一堆 .html 文件,而是把渲染逻辑打包进云函数,由请求触发实时生成 HTML。
所以你运行 uni build --ssr 后看到的是 dist/uniapp-ssr 目录,里面是 Node.js 可执行的入口和 Vue SSR bundle,不是 HTML 文件夹。
- 检查
package.json是否已添加"build:ssr": "uni build --ssr"脚本 - 确保项目已启用
uniCloud且云函数目录为uniCloud/cloudfunctions/ssr-render - 构建后要手动部署该云函数,H5 访问域名需指向这个云函数 HTTP 地址,而非静态托管地址
- 若误用
uni build -p h5,得到的是 SPA 产物,完全无 SSR 能力
serverPrefetch vs asyncData:选哪个做数据预取?
serverPrefetch是 Vue 2/ 3 通用的 SSR 生命周期钩子,asyncData是 uni-app 封装的语法糖,底层仍调用serverPrefetch。但二者行为有本质差异。
-
serverPrefetch只在服务端执行,返回 Promise,适合纯数据请求;客户端不会执行,所以不能放uni.showToast这类 API -
asyncData在服务端和客户端都会执行(客户端执行时 query 为空),返回对象会被浅合并到data,适合需要服务端 + 客户端双端初始化的场景 - 如果页面有路由参数(如
/detail?id=123),asyncData接收的{query}参数比serverPrefetch更直观 - 注意:两者都不能访问
this.$refs或document,服务端没有 DOM
uni-app SSR 常见混合失败(hydration mismatch)怎么排查?
典型现象是控制台报Hydration failed,页面首屏闪一下又重绘,或部分样式错乱。根本原因是服务端渲染的 HTML 和客户端挂载时的 VNode 不一致。
最常踩的坑是:服务端没等数据就渲染了空结构,而客户端等数据回来才补内容。
- 检查
serverPrefetch是否 return 了 Promise,漏掉await或没 return 会导致服务端跳过等待 - 避免在
data里写依赖异步结果的初始值,比如item: this.$store.state.items[id]——服务端此时 state 为空 - 使用
ssrRef替代普通ref或data属性,它能保证服务端和客户端数据序列化一致 - 禁用客户端特有的条件编译,比如
#ifdef H5里调用localStorage,服务端执行会报错中断渲染
SSR 不是开关一开就完事,核心在于“服务端必须把数据准备好再吐 HTML”,这点漏掉,后面所有 TDK、首屏速度都白搭。