单页应用使用Rendertron实现服务端渲染优化seo

前言

由于百度的spider不支持js,所以vue cli构建的这种单页应用就对百度的spider非常不友好了。网上介绍了好几种方案,像nuxt.js个人感觉对项目有入侵,phatomjs据说对vue的单页渲染也不是很好。Rendertron是谷歌出品的Headless Chrome渲染方案,由于是chrome浏览器加持,所以对网页的兼容性也特别好,所以就选择了Rendertron作为渲染方案。此外,也不想对项目做任何改造,所以选择nginx对spider的ua识别进行代理。

安装rendertron

推荐使用git下载源码的方式进行使用,因为我们以后可能会对源码和一些配置进行手动修改,不过这种方式因为一些你懂的原因需要保持网络环境良好。

1
2
3
4
git clone https://github.com/GoogleChrome/rendertron.git
cd rendertron
npm install
npm run build

启动rendertron

确认上面的build无误后,即可通过下面命令进行启动

1
npm run start

如果正常的话可以看到以下输出

1
2
3
> rendertron@3.1.0 start /root/rendertron
> node build/rendertron.js
Listening on port 3000

测试rendertron

默认的rendertron跑在3000端口,请求方式为GET请求/render/路径

1
curl localhost:3000/render/https://www.baidu.com

如果正常的话,即可看到渲染后的页面

使用pm2后台运行

使用pm2可以在后台运行rendertron

1
2
npm install pm2 - g
pm2 start build/rendertron.js

正常则可以看到下面输出

1
2
3
4
5
6
[PM2] Done.
┌─────┬───────────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id  │ name          │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
├─────┼───────────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 0   │ rendertron    │ default     │ 3.1.0   │ fork    │ 734      │ 0s     │ 0    │ online    │ 0%       │ 29.0mb   │ root     │ disabled │
└─────┴───────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘

nginx配置

由于谷歌的spider早就支持了js的渲染,所以我们判断的ua只要针对百度的spider就行

1
2
3
4
5
6
location / {
        if ($http_user_agent ~* "Baiduspider") {
                rewrite  ^/(.*)$  /render/https://网站地址/$1 break;
                proxy_pass  http://localhost:3000;
         }
}

测试nginx配置

可以在curl加上-A参数配置UA,从而让curl模拟百度spider请求。这里的网站地址就是目标的单页应用URL,如果成功的话即可看到渲染后的页面,而不是只有单调的no script标签内容。

1
curl -A "Baiduspider" 网站地址

性能优化

由于服务器的性能不是很好,所以渲染的时间都是在秒级的。下面就是处理请求的日志,可以看到我自己的网页https://www.huihongcloud.cn/toolbox/ 就渲染了4s多,如果是比较密集的爬虫的话,对服务器的压力也是比较大的。

1
2
  <-- GET /render/https://www.huihongcloud.cn/toolbox/
  --> GET /render/https://www.huihongcloud.cn/toolbox/ 200 4,416ms 3.29kb

下面介绍一下rendertron的缓存,rendertron支持三种缓存方式分别是内存缓存、磁盘缓存和cloud datastore。
由于我的页面就是个工具网站,因此我也不需要经常更新,只要我自己通过curl的方式生成一些静态页面让搜索引擎爬取生成的静态内容即可,或者让搜索引擎自行爬取生成。所以我选择了磁盘缓存,并将缓存寿命设置为永久,由于是磁盘缓存我也去掉了缓存条目的限制。将下面文件保存为config.json到一开始git clone的rendertron目录下。

1
2
3
4
5
6
7
{
    "cache": "filesystem",
    "cacheConfig": {
        "cacheDurationMinutes":-1,
        "cacheMaxEntries": -1
    }
}

rendertron的缓存目录为操作系统的tmp路径下的rendertron目录,如果我需要更新页面的话删除这个目录即可。

启动后可以观察渲染的速度变化。第一次请求是真实渲染,第二次是走了缓存,可以看到第二次只有毫秒级。

1
2
3
4
  <-- GET /render/https://www.huihongcloud.cn/toolbox/
  --> GET /render/https://www.huihongcloud.cn/toolbox/ 200 4,933ms 3.3kb
  <-- GET /render/https://www.huihongcloud.cn/toolbox/
  --> GET /render/https://www.huihongcloud.cn/toolbox/ 200 9ms 3.3kb

小结

通过rendertron加nginx可以对vue cli react等单页(PWA)项目无入侵地进行服务端渲染,在谷歌的search console中测试爬取单页应用已经很完美了,所以这种方案主要是针对百度这种不支持js渲染的spider。如果要支持其他spider的话,可以在nginx的配置文件中加上其他的ua。

作者

ZhongHuihong

发布于

2021-08-22

更新于

2021-10-02

许可协议