简介

rendora 是基于 Go 开发的一个类似代理服务器一样的 SSR 解决方案,可以在无需修改现有项目代码的情况下,实现对 Vue、React、Angular 等 SPA 项目的服务端渲染。

Architecture

主要功能:

  • 配置简单
  • 无需修改原有项目
  • 支持 Redis 缓存
  • 提供 REST ful API
  • 支持 Prometheus 监控
  • 支持任意路由页面的渲染
  • 不受限于前端框架与所使用到的技术
  • 不渲染无效资源(如图片、字体和 CSS),以加快 DOM 渲染
  • 搜索引擎爬虫和普通用户获取到的数据一致(得益于 Chrome API)

其实 rendora 在架构中的位置是可以自行定义的,它既可以放在最前端,也可以放在 Nginx 的后面,等于是在 Nginx 层做决策,来判断请求是来自用户还是爬虫。

开始部署

运行无头浏览器

# 可以在 Docker 上运行
$ docker run --tmpfs /tmp --net=host rendora/chrome-headless

# Mac 上如果安装了 Google Chrome 浏览器,可以使用如下方式运行
$ /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --headless --remote-debugging-port=9222

必要配置

target: # 无头浏览器请求的地址
  url: "http://10.0.8.100:8080" 
backend: # 原 SPA 页面的主机地址
  url: "https://spa.example.it"

注意: target.url 是当请求被允许通过 Chrome headless 渲染时,所转发的地址,backend.url 用来定义当请求未被允许通过 Chrome headless 渲染时,将请求转发到该地址。

配置说明

listen: #设置 Rendora 服务的绑定地址和监听端口 (可选)
  address: 0.0.0.0 # 默认 0.0.0.0
  port: 3001 # 默认 3001
cache: #设置用于缓存的驱动(可选)
  type: redis # 支持 local 和 redis 两种缓存模式,默认是 local
  timeout: 6000 # 缓存生命周期,单位:秒
  redis:
    address: localhost:6379
    password: PASSWORD # Redis 密码
    db: 0 # 默认使用 0
    keyPrefix: Key 前缀 # 默认值为 __:::rendora:
target: # 无头浏览器请求的 SPA 地址,当判断为需要 SSR 渲染时会将请求转发到该地址
  url: "http://10.0.8.100:8080" 
backend: # 原 SPA 页面的主机地址
  url: "https://spa.example.it"
headless: # 无头浏览器配置
  waitAfterDOMLoad: 0 # 在初始DOM加载事件后等待的超时时间(以毫秒为单位),默认值为 0
  timeout: 15 # 用于指定 Rendora 等待无头浏览器响应的超时时间,如果在该时间内未获得无头浏览器的响应,则会向客户端返回 500 状态码,默认值 15
  internal: 
    url: http://localhost:9222 # 指定无头浏览器的地址,默认为 http://localhost:9222
  blockedURLs: # 定义无需加载的资源,可以使用通配符或者绝对 URL
    - "*.png"
    - "*.jpg"
    - "*.jpeg"
    - "*.webp"
    - "*.gif"
    - "*.css"
    - "*.woff2"
    - "*.svg"
    - "*.woff"
    - "*.ttf"
    - "https://www.youtube.com/*"
    - "https://www.google-analytics.com/*"
    - "https://fonts.googleapis.com/*"
output:
  minify: true # 是否压缩 HTML
filters: # 定义过滤器
  userAgent:
    defaultPolicy: blacklist # 定义默认策略 whitelist 和 blacklist,默认值为 blacklist
    exceptions: # 用于定义例外,如果 defaultPolicy 为 whitelist,则这里定义的将会是 blacklist
      keywords:
        - bot
        - slurp
        - bing
        - yandex
        - crawler
    exact: # 可以过滤指定的浏览器
      - Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36
  paths: # 仅在检查请求用户代理并通过其过滤器后才检查路径
    defaultPolicy: whitelist
    exceptions:
      prefix:
        - /users/
      exact:
        - /api/
debug: false # 是否开启 Debug 模式
server: # Rendora API 的配置
  enable: false
  listen: 
    address: 0.0.0.0
    port: 9242
  auth:
    enable: false
    name: X-Auth-Rendora # HTTP身份验证标头名称
    value: '' #定义用于身份验证的 token

安装

Docker

$ docker run --net=host -v ./CONFIG_FILE.yaml:/etc/rendora/config.yaml rendora/rendora

注意:目前通过 Docker 搭建的 Rendora 服务无法连接,在 Github 上已经有人提了 Issue

源码

$ git clone https://github.com/rendora/rendora
$ cd rendora
$ make build
$ sudo make install
$ rendora --config CONFIG_FILE.yaml

场景分析

Rendora 作为最前端的反向代理

对于很多人来说,因为没有形成概念,理解 target 和 backend 的区别有点困难,我当初也是非常困惑,通过多次测试明白了两个设置的作用。下面模拟一个场景,通过场景来解释配置的作用。

target: # 无头浏览器请求的地址
  url: "http://10.0.8.100:8000" 
backend: # 原 SPA 页面的主机地址
  url: "https://spa.example.it"
headless:
  waitAfterDOMLoad: 10
  timeout: 5
  internal:
    url: "http://localhost:9222"
output:
  minify: true
filters:
  userAgent:
    defaultPolicy: blacklist
    exceptions:
      keywords:
        - bot
        - slurp
        - bing
        - crawler
debug: true

例如上面的配置中,target.url 指向的是内部的 SPA 项目地址,也就是上图中的 SPA 模块,backend.url 指向的就是通过 Nginx 访问的。

思考

通过架构图可以发现,其实原理非常简单,就是通过一层类似中间件的服务,让他来调用 Chrome 的 API,让 Chrome 渲染页面然后返回给爬虫。那么我们也可以通过 Nginx 来搭配 Lua 来实现同样的功能。

I hope this is helpful, Happy hacking…