使用 HeadlessChrome 添加一个中间件解决 React/Vue 单页的 SEO 问题
发布于 7 年前 作者 Binaryify 5517 次浏览 来自 分享

背景

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

如果在原有 express/koa 项目上添加一个中间件就能解决这个问题不是更好吗

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。具体操作见文档:

express-middleware-seo

本项目在chrome-render 的基础上封装成一个中间件,因为作者已经基于chrome-render 出了 koa 版本的中间件而没出 express 版本的中间件的计划,所以又造了个轮子

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

怎么知道你的网页什么时候已经渲染出包含数据的HTML了可以返回了呢?为了提升chrome-render 效率,默认会在domContentEventFired 时返回。对于复杂的场景还可以通过开启 chrome-render 的useReady选项,等到网页里window.isPageReady 等于 1 时返回。 只渲染出了 HTML 还不够我们还需要检测出来着搜索引擎爬虫的访问,如果请求来着爬虫就返回chrome-render 渲染后的HTML否则返回正常的单页应用所需 HTML。

综上,整体架构如下: 架构

实践

只需以下几行简单代码就可让爬虫抓到 js 执行 window.isPageReady = 1 完成后的页面 express 部分

const { seoMiddleware } = require('express-middleware-seo')

app.use(
  seoMiddleware({
    render: {
      useReady: true
    }
  })
)

HTML 部分

<h1 id="app">You are not a crawler, I will be ready after 1S</h1>
  <script>
      setTimeout(function () {
          document.getElementById('app').innerText = 'Im ready now';
          window.isPageReady = 1;
      }, 1000);
  </script>

为什么使用 chrome-render 而不是用 prerender.io 呢, chrome-render 的优势在于

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

chrome-render说明

项目地址

express 中间件:
express-middleware-seo

相关库:
chrome-render

chrome-runner

koa-chrome-render

koa-seo

5 回复

有个疑问,使用这个中间后可以应付任意的爬虫么,比如国内比较重要的 百度爬虫。 感觉百度的seo爬虫算法有点差,基本靠和公司定制规则来收录。。。 还有这个中间件对用户使用的浏览器访问有要求么

来自酷炫的 CNodeMD

@hyj1991 只是能保证爬虫抓到的是渲染后的页面,不保证排名和权重,原理是判断 UA 是否是爬虫,如果是则提供 chrome-headless 渲染后的页面

@Binaryify 明白了,谢谢

来自酷炫的 CNodeMD

原理我看不太懂,是不是只要在node上加上中间件就ok?

@Faithree 需要安装 chrome59+,然后使用这个中间件

回到顶部