HTML笔记 Nodejs React ·

单页面应用使用rendertron完成服务器渲染解决方案

单页面应用现如今成为了网站的主流,前端框架三剑客React、Vue、Angular基本形成三足鼎立之势。这些框架所带来的的编程体验以及高效的研发效率是不可否认的,但是也有一大缺点就是对于搜索引擎十分的不友好,如果用来做一个后端管理系统来说,无需考虑SEO,十分完美。但是作为前端网站来说,搜索引擎对于流量起着至关重要的作用。

一般情况,我们这些单页面应用都是直接从服务器推送index.html,再根据自身路由通过js在客户端浏览器渲染出完整的html页面。当前搜索引擎中google可以实现抓取js渲染的页面,其他的搜索引擎基本上就GG了。

当然,三大框架也给出了相应的方式来处理服务器端渲染,比如react提供了renderToString,react自带的renderToString 和 renderToStaticMarkup 可以用来将组件(Virtual DOM)输出成 HTML 字符串,但是个人总觉得在写法上不爽,写代码的时候会有多余的顾虑。

网上还有其他的一些方案比如基于react的nextjs,基于VUE的nuxtjs,但是这些框架基本上还是变回了之前的多页面模式,还增加了一定的框架学习成本,另外还有一点就是写起来不爽!而且如果改现有的网站,呵呵呵~~~

如果你想使用可以自行网上搜索,有大把的教程可以看,官方也提供了相应的文档。

之前我也写过一篇关于服务器渲染的文章,但是有很大的局限性,有兴趣的朋友可以去看一看vue/react服务端渲染实例

这里我想说另一个解决方案,无论是对于现有的网站还是新开发的网站来说都是一样的,简单快捷,他就是—— Rendertron

Rendertron

Rendertron是nodejs框架下的产物,是google-chrome旗下的的配套产品。首先,服务器上装有个google-chrome,rendertron把他打开,然后在服务器(官方推荐express)中增加中间件,先判断UA(user-agent)里面有没有带有类似Baiduspider(百度爬虫)等字样,如果没有,就像正常的单页面服务器那样,把原始html推送出去,由客户端浏览器完成js、css渲染的工作;如果带有指定UA头字样,就先把网页推送给本地服务器那个google-chrome,等他渲染好对应页面后,把渲染好的html结果推送出去。这样在写网站的时候无需有其他的顾虑,可以想怎么写就怎么写,只有当爬虫过来的时候将渲染好的页面吐给他即可,其他用户访问正常,没有任何影响,是不是很爽

基本的运行流程如下图所示:
Rendertron流程图
好了,说了很多下面我们来实际搭建一下,将其运行起来看效果。

安装Chromeheadless

网上有很多教程写如何安装,我觉得我们还是用最简单的一个方式吧,使用脚本安装

curl https://intoli.com/install-google-chrome.sh | bash

https://intoli.com 这个网站是专门从事headless browsers使用简化,提供云服务的一家公司。其中在该公司的博客中,可以看到许多关于Google Chrome的文章。

该公司提供的这个脚本,能够自动查找相关依赖,并安装。这样我们就不必担心依赖问题,导致无法安装成功。

安装Rendertron

这个安装有两种方式,一种通过npm直接全局安装

npm install -g rendertron

但是安装过程不会很顺利如果你不会科学上网的话,没关系,官方为我们提供了另外一个方法:

git clone https://github.com/GoogleChrome/rendertron.git

嗯~~~ 我想说这个也很麻烦,下载超级慢,不知道是为啥,而且很容易下载失败,你可以登录上去下载压缩包试试,大概率是可以成功的。

然后我们进入到rendertron目录,执行下面的命令:

npm install
npm run build
pm2 start bin/rendertron

当build的时候可能会出现报错,但是我实际使用的时候发现好像不影响.....。他其实就是一个node项目,我们用pm2来启动他。

项目引用

这里我们使用的是express框架,在你的express服务器程序中引入中间件rendertron-middleware,需要先进行安装

npm install --save express rendertron-middleware

然后再app.js中进行使用

const rendertron = require('rendertron-middleware');

const app = express();

app.use(rendertron.makeMiddleware({
  proxyUrl: 'http://localhost:3000/render',
}));

rendertron默认启动是使用3000端口,如果你想修改端口号,可以在build目录中找到config.js在里面你可以看到修改的位置。

rendertron还有一些其他的配置项:

app.use(rendertron.makeMiddleware({
  proxyUrl: 'http://localhost:3000/render',
  userAgentPattern:****,
  excludeUrlPattern:****,
  timeout:11000,//这个timeout超时参数亲测已经无效了,可以直接删了,在config.js中直接修改就好
}));

userAgentPattern是用来写清楚哪些UA头需要服务器渲染,除此之外的请求都直接单页面推送。比如这样写:

const botUserAgents = [
  'Baiduspider',
  'bingbot',
  'Embedly',
  'facebookexternalhit',
  'LinkedInBot',
  'outbrain',
  'pinterest',
  'quora link preview',
  'rogerbot',
  'showyoubot',
  'Slackbot',
  'TelegramBot',
  'Twitterbot',
  'vkShare',
  'W3C_Validator',
  'WhatsApp',
];

app.use(rendertron.makeMiddleware({
    //其他参数
  userAgentPattern: new RegExp(botUserAgents.join('|'), 'i'),
}));

把你要的爬虫UA头都写到一个数组里,然后用new RegExp()正则一下

excludeUrlPattern是指哪些文件格式需要在chromeheadless中被完全加载,用法如下

const staticFileExtensions = [
  'ai', 'avi', 'css', 'dat', 'dmg', 'doc', 'doc', 'exe', 'flv',
  'gif', 'ico', 'iso', 'jpeg', 'jpg', 'js', 'less', 'm4a', 'm4v',
  'mov', 'mp3', 'mp4', 'mpeg', 'mpg', 'pdf', 'png', 'ppt', 'psd',
  'rar', 'rss', 'svg', 'swf', 'tif', 'torrent', 'ttf', 'txt', 'wav',
  'wmv', 'woff', 'xls', 'xml', 'zip',
];
//略n行代码
app.use(rendertron.makeMiddleware({
    //其他参数
  excludeUrlPattern: new RegExp(`\\.(${staticFileExtensions.join('|')})$`, 'i'),
}));

把你需要加载的文件后缀都写到一个数组里,然后用new RegExp()正则一下

至此我们的搭建工作就完成了,使用pm2来启动express服务器,然后来进行一下测试:

命令行输入curl -A “baiduspider” http://你需要测试的网址(就是访问你的server程序对应的那个网址,即改写前的那个原来的网址),然后就能看到通过chromeheadless渲染好的html代码,大功告成!

或者你可以直接使用postman访问,但是要记得将user-agent修改一下。

本文参考链接:https://blog.csdn.net/grootxu59/article/details/90453679

参与评论