uni-app ssr(服务器渲染) + 动态路由(伪静态) + seo优化
uni-app主要用于小程序开发 也支持H5开发。由于使用的是vue单页面。所以想要搜索引擎seo优化的难度是相当大。uni-app只提供了一个托管云函数的ssr方式,作用相当有限。所以这个轮子必须得自己来造。
这些坑帮你们踩过了 不要去踩了。
1:ssr(服务器渲染) 只支持托管代码到uni-app云函数上。
2:路由是pages.json写死的单页面不支持伪静态
3:路由不能使用自己的vue-router@4
4:路由不能自行增加addRouters uni-app会去自己的对象检测路由是否存在。
5:哪怕检测路由你都绕过了 你会发现页面不会调用onLoad这些生命周期。当普通组件而不是页面级组件。而且ssr服务端也不支持。
1:解决动态路由:
就是一个页面组件 实现多个路径都可以访问。
比如/pages/index/id /id/:id 定义这样的动态高级路由。
有人会想到使用url参数不就可以了。
我的哥既然做seo优化。H5页面还在使用动态参数这样的动态路径。权重根本不高。
如果一个个的手动pages.json增加页面。那商城 文章这样的 怎么办。
所以要解决seo 必须要解决动态路由。
这条路坑很多。网上没有一个能用的。
都是解决路由守卫这些功能。并没有动态高级路由
但看都在说有个能用 但是价格有点小贵. 收费的。
因为这些我觉得我花时间研究uni-app源码自然可以解决。
最终功夫不负有心人找到了解决办法。
const hookRoute = (routes) => {if (!routes && typeof __uniRoutes !== 'undefined') routes = __uniRoutesif (!Array.isArray(routes)) return routesconst needPush = []for (const route of routes) {let seoPath = route?.meta?.seoPath || seoRoutes[route.path];if (!seoPath) {if (!route.path || route.alias) continue;const seoPathSplit = route.path.split('/')seoPath = `/${seoPathSplit[seoPathSplit.length-1]}`}const newRoute = {}for (const k in route) newRoute[k] = route[k];newRoute.path = seoPathif (pathKeys[seoPath]) continue;pathKeys[seoPath] = newRouteneedPush.push(pathKeys[seoPath])}routes.push(...needPush);return routes}
就这么简单。路由就增加好了。
但新的问题来了。测试普通路由这样动态添加没问题。
但动态高级路由这样添加就有问题。
上面说过就算增加了路由又能怎样。
uni-app有判断路由是否存在。 像 /id/:id 这样的路由 怎么能通过判断呢。
使用:alias
动态变更这个alias就能通过uni-app判断路由是否存在。
那就使用uni.addInterceptor 拦截器拦截请求之前动态设置这个alias就实现。
function seoHook(path) {if (!path || typeof path !== 'string') return nullpath = path.split("?")[0];if (pathKeys[path]) return pathKeys[path]const hookData = matchPath(path, pathKeys);if (hookData) hookData.alias = path;return hookData}//该拦截器如果跟你的守卫有冲突 需要自行合并到你的守卫代码里 seoHook(args.url)function addInterceptor() {// 要拦截的页面跳转方法列表const navigationMethods = ['navigateTo', 'redirectTo', 'reLaunch', 'switchTab'];// 设置拦截器navigationMethods.forEach(method => {uni.addInterceptor(method, {invoke(args) {const seoHookData = seoHook(args.url);return true; // 允许跳转},fail(e) {console.error(e)}});});}
测试通过一切正常
2:解决seo优化
这个简单直接在页面里增加即可
<page-meta> <head> <title>标题</title> <meta name="description" content="uniapp h5 seo搜索引擎优化 支持伪静态" /> <meta name="keywords" content="uniapp seo,uniapp ssr,uniapp 伪静态" /> </head></page-meta>
那么动态如何实现呢:
//uniapp_seo/pages/index/id.vue 具体看这个演示代码export default { data() { const idData={ "1": { "title": "这是文章1的标题 黑神话悟空", "keywords": "这是文章1的关键词", "description": "这是文章1的description", "content": "文章1:黑神话悟空" }, "2": { "title": "这是文章2的标题 全红婵", "keywords": "这是文章2的关键词", "description": "这是文章2的description", "content": "文章2:全红婵" }, "default": { "keywords": "这是默认的关键词", "description": "这是默认的描述", "content": "我是默认的内容" } } return { ...idData[this.$route?.params?.id||"default"] } }}
需要注意写data函数里 其他地方ssr不会渲染。
我之前还说过如果是商城 文章系统上面这样的肯定无法满足了必须服务器上渲染了
这部分放文档里说。 太复杂不是好事。
3: 解决ssr(服务器渲染)
上一篇文章有详细的如何解决非托管使用uni-app的ssr。 这里不再多说。
可以看上一篇文章
最终打包全部源码开源给需要的人 不要再去踩坑造轮子。
uniapp-router-h5
仅支持uni-app Vue3项目 不支持Vue2 (因为uni-app vue2不支持ssr)
用途:
实现uni-app的h5项目的搜索引擎seo优化提高网站排名终极解决方案。
功能:
- uni-app h5项目(Vue3)动态路由 也就是伪静态路由(网上并没有相关的功能 据说有一家支持但收费)
- ssr(服务器渲染)将uni-app项目在服务器上转为静态页面并实现服务端的动态路由。
- 突破uni-app官方ssr必须托管代码并使用uniCloud(云函数)的限制 可以任何平台运行
- seo优化 支持每个页面设置meta 关键词 描述等 (动态路由设置页面关键词有单独的说明)
开始使用:
- 下载安装
git clone https://github.com/fzl51/uniapp-router-h5.gitcd uniapp-router-h5npm install
- 运行
npm start
或者
node main.js
此时打开 http://localhost:8080 鼠标右键查看源码看seo效果
演示:https://v.yy2169.com
使用文档:
uniapp_seo目录
uni-app项目源码 里面是演示如何使用。
- 在main.js导入路由 会自动hook路由增加动态路由(伪静态)
//uniapp_seo/main.jsimport './router'
- 配置路由方法1: uniapp_seo/router.js (推荐) 2选1
//uniapp_seo/router.jsconst seoRoutes = { "/pages/index/id": "/id/:id"}
- 配置路由方法2: 直接在pages.json 设置简单(微信小程序端会有提示 可以加条件编译)
{ "path": "pages/index/seo", "style": { // #ifdef H5 "seoPath":"/seo/:name", // #endif "navigationBarTitleText": "uni-app seo 动态路由 伪静态" }}
- 路由格式:支持动态高级路由(伪静态) /id/:id 这种路径也支持 /h5 这样的静态路径
- seo优化 在页面级组件直接写下面代码即可
#uniapp_seo/pages/index/seo.vue<page-meta> <head> <title>标题</title> <meta name="description" content="uniapp h5 seo搜索引擎优化 支持伪静态" /> <meta name="keywords" content="uniapp seo,uniapp ssr,uniapp 伪静态" /> </head></page-meta>
- 动态页面设置不同的meta关键词 页面数据等信息
//uniapp_seo/pages/index/id.vue 具体看这个演示代码export default { data() { const idData={ "1": { "title": "这是文章1的标题 黑神话悟空", "keywords": "这是文章1的关键词", "description": "这是文章1的description", "content": "文章1:黑神话悟空" }, "2": { "title": "这是文章2的标题 全红婵", "keywords": "这是文章2的关键词", "description": "这是文章2的description", "content": "文章2:全红婵" }, "default": { "keywords": "这是默认的关键词", "description": "这是默认的描述", "content": "我是默认的内容" } } return { ...idData[this.$route?.params?.id||"default"] } }}
- 也可以在服务端写代码实现动态路由seo优化 我们演示项目在服务端实现的.
为了减少复杂度我们删除了服务端实现部分代码。
不然一会uni-app项目设置一会在服务端代码设置 人都醉了。
服务端设置动态路由seo 优点是每次更改不需要重新编译。
注意:⚠️服务端实现seo优化就不要在页面组件实现
//routes.jsconst meta={ "/": { "keywords": "这是默认的关键词", "description": "这是默认的描述", }, "/id/1": { "title": "这是文章1的标题 黑神话悟空", "keywords": "这是文章1的关键词", "description": "这是文章1的description", }}const head = meta["/id/1"];// /id/1 根据请求页面动态获取if (head) { let headStr = '' for (const key in head) { headStr += key==='title'?`<title>${head[key]}</title>\n`: `<meta name="${key}" content="${head[key]}">\n` } //finalHtml是routes.js文件里的 if (headStr) finalHtml = finalHtml.replace(/(<head[^>]*>)(?!.*<head[^>]*>)/i, `$1\n${headStr}\n`);}
8. uniapp-router-h5 使用了 uni.addInterceptor 拦截器。可以扩展实现路由前置守卫。
如果你也使用此拦截器造成冲突。可以将你的拦截器合并进了。也可以删除我们的拦截器 在你的代码里调用 seoHook(args.url);
uni-app HBuilder X设置
1.在uniapp设置路由mode: history
2.发布的时候设置ssr发行 (Vue3才支持)
web 目录
web是uniapp HBuilder X选择ssr发行H5项目后生成。直接复制到网站目录即可
ssr(服务器渲染)注意事项
- 不能有环境代码。详情可以看官方的说明 比如 window document
- 还有很多api不支持 比如 uni.getSystemInfoSync uni.createSelectorQuery uni.createAnimation
- 注意链接是否是onclik事件 需要使用navigator
- 如果有不兼容的代码 会node报错 不会服务器渲染 但不影响网页运行
- ssr很多代码不兼容 多到让你怀疑人生 做好心里准备。
github开源