「技术干货」SEO解决方案。

「技术干货」SEO解决方案。

作者/冯雨森

概述

优化SEO将改善网站在搜索引擎结果中的排名,吸引更多的用户访问网站,提高网站的访问量,从而提升品牌效应。

搜索引擎并不会执行JavaScript文件,因此只有将数据在html文件中静态化才会被搜索引擎检索到。

主流SEO解决方案

1. SSR服务端渲染

如VUE-SSR,页面在服务端渲染完成后返回给客户端。

- 优点:SEO效果好,首屏渲染快。

- 缺点:开发成本高,SPA应用无法快速迁移为SSR。页面由服务端渲染,服务器开销大。

2. Nuxt

结合了SPA和SSR,Nuxt在服务端运行一个Nuxt服务,客户端发起请求后,会先在服务端运行页面的Nuxt的asyncData和fetch钩子,通常在这两个钩子里初始化页面数据请求,Nuxt会在钩子执行完毕并渲染完数据后返回页面。相比SSR,Nuxt的开发方式和SPA大部分都相同,并且开发会更加方便,例如路由会直接按照层级结构自动生成,不需要自己写路由,开发成本相比SSR低了很多,迁移成本也相对较低。

- 优点:开发成本和SPA相似,SPA应用迁移成本较低,SEO效果好,可以选择打包成SPA还是SSR,拥有SSR的大部分优点。

- 缺点:服务器开销大,依然是在服务端进行页面渲染,并且因为Nuxt服务可能与后端服务不在一起,有可能因为请求网络延迟导致首屏速度变慢。目前的坑也比较多,踩坑也是个不轻松的过程。

3. 静态 html

最原始的方法,对于静态数据来说,SEO不是问题。

- 优点:页面小,不会引入 vue/react/angular 等框架,大幅减少js的体积,静态数据SEO效果好,首屏渲染快。

- 缺点:开发成本高,维护成本高,并且接口数据是无法静态化的,只对无接口数据需求的纯静态站点有优势。

4. 预渲染

可直接在SPA应用基础上增加预渲染插件即可实现预渲染,例如:prerender-spa-plugin。预渲染是在本地构建时,将指定路由的页面全部渲染出一份html,在客户端请求页面时先请求这份html。

- 优点:SPA应用成本最低的优化SEO方案,只需要添加插件和配置,首屏渲染速度快,SEO效果好。

- 缺点:因为构建渲染页面时,本地环境为localhost,所有与window.location相关代码都可能会出问题,这会导致很多链接错误问题,虽然可以注入变量来解决,但是多环境构建依然可能遇到问题,并且要做很多额外的处理。prerender-spa-plugin是基于puppeteer的,支持接口拉取,但是渲染发生在构建阶段,并且是本地环境,会有很多其他问题,例如每次接口数据修改还需要重新构建,并且渲染页面时一旦有接口报错导致页面渲染失败,也将会是个麻烦的事。我个人认为预渲染还是更适合纯静态类spa站点的静态化。

离线预渲染

离线预渲染与预渲染类似,但是解决了预渲染的一些问题,离线预渲染的使用场景仍具有很大的局限性,但是在特定的场景下,却是非常合适的方案。

LStack的官网www.lstack.com就使用了离线预渲染作为SEO解决方案,我们先看一下对于官网的需求:

1. SEO优化要好

2. 数据要使用接口数据

3. 不能使用服务端渲染(页面很少变化,使用服务端渲染浪费服务器资源)

SEO的要求,首先就可以排除SPA了,数据要使用接口数据,那原生html这种无法静态化接口数据的方案也无法满足这个要求,不能使用服务端渲染,又再次排除了服务端渲染和Nuxt。而预渲染又存在诸多问题,事实上LStack官网重构前正是使用的预渲染方案,只对静态数据做了静态化,但是仍对代码有侵入性,并且遇到了一些本地环境渲染页面而导致的问题,处理这些问题,需要在写代码时考虑这种情况的处理。在这种情况下,离线预渲染就是最合适的解决方案了。

优点

- 改造简单,对源代码0侵入,不需要任何改造,spa不需要任何修改就可以仅搭建一个爬虫服务来实现SEO优化。

- 可以对接口数据静态化。

- 不占用服务器资源,渲染一次,便可以重复使用,直到下次数据变化重新渲染。

- 加速首屏渲染,首屏效果和服务端渲染一致。

- 可以部署到cdn/oss。

缺点

- 仅适用于数据改变频率低,时效性低的站点,例如官网,文案也许一个月变更一次。

- 开发成本虽然低,但是搭建维护坑比较多,需要考虑的点较多。

- 和预渲染一样,因为js拉取完毕后会以spa模式渲染页面,因此js加载完成后页面会闪动一次,替换掉静态html内的内容。

原理

离线预渲染使用爬虫爬取页面,生成静态html,从而实现动态数据的静态化。

爬虫使用puppeteer,puppeteer是nodejs的一个爬虫框架,提供了对headless chrome的高级操控api,headless chrome为无界面chrome。使用这种方式渲染页面,完全模拟了用户的真实访问环境。

- 爬虫生成的静态html,只是对spa原本没有数据的index.html填充了数据,js拉取回来后,依然会执行js,接口依然会触发,行为和spa没有区别,只是首屏从空白页面变为了填充了数据的页面。

- 涉及到登录等有状态的部分,因为爬虫渲染的环境并没有用户登录信息,所以首页面总是未登录状态,js加载完毕后,才会判断登录状态。

方案

「技术干货」SEO解决方案。

「技术干货」SEO解决方案。

项目构建完毕后,将构建完成的源代码上传至OSS,然后拉取源文件到容器中,Nginx代理此项目,然后Puppeteer访问Nginx,对每个路由依次访问并渲染页面,按照路由结构安排文件目录结构,然后打包上传至oss。上传完毕后拉取渲染成功的页面,覆盖到容器中。

踩坑

1. 为了在只用一个Nginx服务的情况下,保证无论页面是否经过爬虫处理都要可以正常访问,并且数据也要是最新的,可以参考这样的规则:每一级路由都有对应的文件夹,此路由页面为此文件夹下的index.html。所有页面路由默认匹配/[url]/index.html,手动拼接/index.html后缀,这样爬虫处理过的页面都可以被正常访问到,而如果此时后端数据更新,要重新渲染页面,因为爬虫会等到页面完全渲染完毕才会储存页面,因此此时最新数据已经通过接口返回了,不必担心数据依然是旧的。而当页面没有被爬虫处理过时,页面只有一个index.html,其他路由都会404,此时当找不到对应文件时,不返回404页面,而是返回index.html,前端js加载完毕后,自动判断路由来跳转对应的页面,如果路由页面不存在,也是前端跳转404,此时的行为完全是spa行为,只有首屏会拉取html,其余页面跳转都是spa行为。

location / {
   root     /usr/share/nginx/html/website/website;
   index    index.html;
   gzip_static on;
   try_files $uri $uri/ /$1/index.html;
}

2. linux环境下,puppeteer安装会报错,是因为chrome安装报错。可以手动安装chrome,然后puppeteer启动添加参数。

const browser = await puppeteer.launch({
    args: ['--no-sandbox', '--disable-dev-shm-usage']
});

3. 内网可能会遇到dns问题,爬虫爬到了公网上,导致页面爬错,配置好dns即可。

4. SSL证书错误,只需要在启动参数里添加ignoreHTTPSErrors: true,忽略SSL错误。

5. linux下中文乱码问题,安装中文编码即可。

6. 每一套源码应该有一份配套的html页面,如果代码做了修改,webpack打包出的js文件名也会变化,如果继续使用旧的html,则会导致js拉取到错误的代码,为什么不是404而是200呢?因为Nginx配置中,404的时候,默认转发index.html,所以这种情况下js并不会404,而是js里面都是html代码。而如果这样的事情发生了,那这个页面无论是用户还是爬虫,都只能访问到静态的html了,只能重新拉取代码,并且不要把旧的html页面覆盖进去,如果是自动化部署,脚本逻辑上就需要多做一些考虑了。

7. puppeteer是node的库,但是有基于其他语言的封装,例如java版封装为jvppeteer,但用法上可能会有区别。

LStack产品简介

面向行业应用开发商(ISV/SI)提供混合云/边缘云场景下云原生应用开发测试、交付、运维一站式服务,帮助企业采用云原生敏捷开发交付方法论,从而提高软件开发人员效率、减少运维成本,加快数字化转型,并最终实现业务创新。

-End-

本文来自投稿,不代表科技代码立场,如若转载,请注明出处https://www.cwhello.com/409201.html

如有侵犯您的合法权益请发邮件951076433@qq.com联系删除

(0)
上一篇 2023年12月6日 00:14
下一篇 2023年12月6日 00:14

联系我们

QQ:951076433

在线咨询:点击这里给我发消息邮件:951076433@qq.com工作时间:周一至周五,9:30-18:30,节假日休息