使用HeadlessChrome做单页应用SEO

本文作者:ivweb 吴浩麟

随着react、vue、angular等前端框架的流行越来越多的web应用变成了单页应用,它们的特点是异步拉取数据在浏览器中渲染出HTML。使用这些框架极大的提升web用户体验和开发效率的同时缺带来一个新问题,那就是这样的网页无法被搜索引擎收录。虽然这些web框架支持服务端渲染,但这可能又会增加开发成本。

有没有一个可用于任何单页应用的SEO解决方案,让我们不用对代码做改变保持原有的开发效率?chrome-render可以帮我们做到这点,它通过控制HeadlessChrome渲染出最终的HTML返回给爬虫来实现。

HeadlessChrome介绍

前不久chrome团队宣布chrome支持headless模式,HeadlessChrome支持chrome所具有的所有功能只不过因为不显示界面而更快资源占用更小。相比于之前的phantomjs(作者因为HeadlessChrome的推出而宣布停止维护)chrome的优势在于它又一个很强的爹(google)会一直维护它优化它,并且chrome在用户量、体验、速度、稳定性都是第一的,所以我认为HeadlessChrome会渐渐替代之前所有的HeadlessBrowser方案。

如何操控HeadlessChrome

既然HeadlessChrome是以无界面模式运行的,那要怎么控制它和它交互? chrome提供了远程控制接口,目前可以通过chrome-remote-interface来用js代码向chrome发送命令进行交互。在启动chrome的时候要开启远程控制接口,然后通过 chrome-remote-interface 连接到chrome后再通过协议控制chrome。具体操作见文档:

chrome-render原理与实践

原理

chrome-render先会通过chrome-runner以headless模式启动和守护你操作上的chrome,再通过chrome-remote-interface操控chrome去访问需要被SEO的网页让chrome运行这个网页,等到包含数据的HTML被渲染出来时读取当前网页DOM转换成字符串后返回。

怎么知道你的网页什么时候已经渲染出包含数据的HTML了可以返回了呢?为了提升chrome-render效率,默认会在domContentEventFired时返回。对于复杂的场景还可以通过开启chrome-render的useReady选项,等到网页里调用了window.chromeRenderReady()时返回。

只渲染出了HTML还不够我们还需要检测出来着搜索引擎爬虫的访问,如果请求来着爬虫就返回chrome-render渲染后的HTML否则返回正常的单页应用所需HTML。

综上,整体架构如下:

实践

只需以下几行简单代码就可做到:

const ChromeRender = require('chrome-render');
ChromeRender.new().then(async(chromeRender)=>{
    const htmlString = await chromeRender.render({
       url: 'http://qq.com',
    });
});

chrome-render只是做了渲染出HTML的工作,要实现SEO还需要和web服务器集成。为了方便大家使用我做了一个koa中间件koa-seo,要集成到你现有的项目很简单,如下:

 const seoMiddleware = require('koa-seo');
const app = new Koa();
app.use(seoMiddleware());

通过以上简单的两步,你的单页应用就被SEO了。

应用场景扩展

chrome-render除了用于通用SEO解决方案其实可以用于通用服务端渲染,因为目的都是渲染出最终的HTML再返回。针对通用服务端渲染我也做了一个koa中间件koa-chrome-render。使用chrome-render做服务端渲染的

优势在于:

  • 通用,适用于所有单页应用
  • 对原有代码几乎无改动,最多再合适的地方加个window.chromeRenderReady(),保持原有开发效率

缺点在于:

  • 和react、vue等只带的服务端渲染相比性能低(经我测试大约 200ms vs 60ms)
  • chrome-render渲染时占用资源高,一次渲染大约占用25Mb内存,当请求量大时服务器可能扛不住。但是可以通过缓存渲染结果优化。

总结

大家可能会说这个很像prerender.io,没错思路是一样的,chrome-render的优势在于:

  • chrome-render开源可自己部署,prerender要收费是商业产品
  • prerender基于已经停止维护的phantomjs

本文中所提到的相关项目都是开源的并且有详细的使用文档,它们的文档链接如下:

喜欢的给个star,希望大家和我一起来改进它们让它们更强大。

阅读原文

原文链接:http://ivweb.io/topic/59524c2498bb3850f554d9b8

原创声明,本文系作者授权云+社区-专栏发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Youngxj

QQ防红跳转短网址生成网站源码(91she完整源码)

7704
来自专栏老马寒门IT

Node入门教程(11)第九章:Node 的网络模块

net网络模块 net模块是node对TCP或者IPC开发的封装,包括了客户端和服务器端相关API。对于阅读本文,请您有一定的网络编程的基础。 您需要已经了解了...

3138
来自专栏魏艾斯博客www.vpsss.net

wordpress 前台源代码显示查询次数、加载时间和内存占用的方法

833
来自专栏破晓之歌

fiddler网址代理调试工具 原

软件下载地址:https://www.telerik.com/download/fiddler/fiddler4

833
来自专栏跟着阿笨一起玩NET

IIS服务中五种身份验证

转载:http://os.51cto.com/art/201005/202380.htm

452
来自专栏前端知识分享

第160天:Http协议的详细总结

超文本传输协议(HyperText Transfer Protocol),缩写HTTP。通过HTTP或者HTTPS协议请求的资源由统一资源标识符(Uniform...

512
来自专栏快乐八哥

前后端分离下如何登录

目前大多数Web应用采用前后端分离方式进行开发。所以前端网站或应用都属于SPA(Single Page Application)。如果前端,后台API部署在同域...

1052
来自专栏菩提树下的杨过

基于thrift的微服务框架

前一阵开源过一个基于spring-boot的rest微服务框架,今天再来一篇基于thrift的微服务加框,thrift是啥就不多了,大家自行百度或参考我之前介绍...

23210
来自专栏hbbliyong

ASP.NET 运行机制详解

1.浏览器和服务器的交互原理 通俗描述:我们平时通过浏览器来访问网站,其实就相当于你通过浏览器去访问一台电脑上访问文件一样,只不过浏览器的访问请求是由被访问的电...

2717
来自专栏前端技术总结

基于iframe的跨域与更新父窗体地址栏的解决方案

管理平台前端页面需要在当前前端框架结构基础上,在顶级导航中增加两个模块:首页、运维管理模块,以此接入运维平台提供的页面。在访问到内部某个页面后,希望父窗体的地...

1.7K135

扫码关注云+社区