你有没有遇到过这样的尴尬?
用户打开你的 UniApp 项目,首屏白屏几秒钟,用户还没看到内容就走了。尤其是在 SEO 场景下,搜索引擎爬虫来了,你却只能返回一个“加载中…”的页面,结果自然是——被搜索引擎无情抛弃。
但好消息是,从 HBuilderX 4.18 版本起,UniApp X 正式支持 SSR(Server Side Rendering)服务器端渲染,这意味着你可以让你的 UniApp 应用“首屏即内容”,秒开页面、SEO 友好、用户体验更丝滑。
本文将带你从“零”玩转 UniApp X 的 SSR 世界,看看它是如何工作的,如何配置,以及如何部署到 uniCloud。
🌐 SSR 是什么?为什么它这么香?
SSR,全称 Server Side Rendering,即“服务器端渲染”。简单来说,就是:
在服务器上就把 Vue 组件渲染成 HTML 字符串,直接返回给浏览器,而不是等浏览器下载 JS 再渲染。
这样做的好处是:
- 首屏加载快:用户看到的是直接返回的 HTML,而不是“加载中…”
- SEO 友好:搜索引擎爬虫也能看到完整的页面内容
- 同构(Isomorphic)应用:一套代码,既能在服务器跑,也能在客户端跑,真正“一鱼两吃”
⚙️ 配置 SSR:从零开始的快乐旅程
首先,确保你使用的是 HBuilderX 4.18 或以上版本,然后在项目根目录下创建 vite.config.js
文件,内容如下:
import { defineConfig } from 'vite'
import uni from '@dcloudio/vite-plugin-uni'
export default defineConfig({
base: 'https://static-xxxx.bspapp.com/', // 静态资源地址,如 uniCloud 前端托管
plugins: [
uni(),
]
})
小贴士:
base
是你的静态资源路径,建议指向 uniCloud 前端托管地址或其他 CDN 地址。
🧠 数据预取与状态同步:SSR 的灵魂
SSR 的核心在于:服务器渲染时,组件的数据必须已经准备好。否则,客户端和服务器渲染出的内容不一致,就会出现“混合失败(hydration mismatch)”。
为此,UniApp X 提供了:
✅ serverPrefetch
生命周期钩子
这是 SSR 专属的钩子函数,用于在服务器端预取数据。
export default {
async serverPrefetch() {
await this.fetchItem()
},
methods: {
fetchItem() {
return this.$store.dispatch('fetchItem', id)
}
}
}
它只在服务器执行,适合做数据请求。
✅ ssrRef
和 shallowSsrRef
适用于简单的响应式数据,在服务端和客户端保持一致。
const categories = ssrRef(['c1', 'c2'], 'categories');
export default {
data() {
return {
categories
}
}
}
✅ Vuex 状态管理(推荐用于复杂数据)
对于复杂数据结构,建议使用 Vuex 来统一管理状态。
创建 SSR 兼容的 App:
import { createSSRApp } from 'vue'
import App from './App.uvue'
import createStore from './store'
export function createApp() {
const app = createSSRApp(App)
const store = createStore()
app.use(store)
return { app, store }
}
示例 Store:
import { createStore } from 'vuex'
function fetchItem(id) {
return new Promise(resolve => {
setTimeout(() => resolve({ id, title: 'title' + id }), 300)
})
}
export default () => {
return createStore({
state() {
return {
items: {}
}
},
actions: {
fetchItem({ commit }, id) {
return fetchItem(id).then(item => {
commit('setItem', { id, item })
})
}
},
mutations: {
setItem(state, { id, item }) {
state.items[id] = item
}
}
})
}
🧾 SEO 支持:page-meta 让你轻松写 head 内容
在 SSR 模式下,你可以使用 <page-meta>
标签来定义页面的 <head>
内容,比如:
<template>
<page-meta>
<head>
<meta name="keywords" content="uni-app ssr, 服务器端渲染, SEO优化" />
<meta name="description" content="使用 UniApp X 的 SSR 功能提升首屏速度和 SEO 表现" />
</head>
</page-meta>
</template>
注意:需要确保你的
index.html
中有<!--head-meta-->
注释标记,否则这些内容不会被注入。
📦 编译与部署:让 SSR 跑起来
编译 SSR 项目时,会生成两个部分:
- client:客户端资源(JS、CSS、图片等)
- server:服务端代码(用于渲染 HTML)
你可以通过以下方式部署:
☁️ 部署到 uniCloud(推荐)
前置条件:
- 开通 uniCloud
- 配置前端网页托管
- 为云函数绑定自定义域名(防止浏览器下载 HTML 而不是展示)
部署步骤:
-
从插件市场导入
uni-ssr
插件 -
修改
cloudfunctions/uni-ssr/package.json
中的_moduleAliases
,确保依赖路径正确 -
使用 HBuilderX 的发行菜单:
- 发行 > 网站(PC Web / 手机 H5)
- 勾选 SSR
- 勾选 部署到 uniCloud 前端网页托管
-
配置云函数 URL 化,参考官方文档
🧪 手动部署(进阶玩法)
- 使用 CLI 编译 SSR 项目:
npm run build:h5:ssr
- 将
dist/build/h5/client
上传到前端托管平台(如阿里云 OSS) - 将
dist/build/h5/server
部署到 Node.js 服务器或云函数中 - 确保服务端能访问静态资源(配置跨域)
⚠️ 注意事项:别让 SSR 变“坑”
-
Hydration mismatch 警告:
- 如果浏览器控制台提示:
[Vue warn]: Hydration node mismatch: - Client *** - Server ***
ssrRef
,或者数据是否同步。
- 如果浏览器控制台提示:
-
History 路由模式问题:
- 如果你使用了
history
模式,但页面报错:Hydration completed but contains mismatches
index.html
。
- 如果你使用了
🎉 结语:SSR,让 UniApp X 更强大
SSR 的加入,让 UniApp X 不再只是一个跨平台的 App 开发框架,而是真正具备了 Web 全栈开发能力。你可以用它开发:
- 高性能的 Web 应用
- SEO 友好的内容网站
- 同构的前后端一体化项目
📢 欢迎关注我的 UniApp X 技术专栏,持续更新跨平台开发技巧与实战经验。我们下期再见!