什么是服务端渲染这里就再解释了,网上已经有很多详细的介绍了。
为什么需要服务端渲染
这里再说下为什么需要服务端渲染,最主要解决的问题就是解决 SEO 问题了,因为 React
Vue
基于这些框架写出来的项目数据都是浏览器端动态调用后端接口获取的,包括页面的元素结构什么的都是放在 Js 文件里的。当爬虫来访问时只拿到了 <div id="app"></div>
这样一个空的 div
里边什么内容也没,十分不利于 SEO 。
有了上述的 SEO 问题,那么解决问题思路就很简单了,就是如何能让搜索引擎的爬虫爬到页面是包含了完整内容的。
如何实现
实现的方法也很多,大都是要启动个单独的服务来处理这些爬虫的请求。这里使用的是一个开源的解决方案 prerender 使用非常简单,需要有个 nodejs
运行环境,以下上官方的使用文档。
安装 pretender
1
npm install prerender
创建文件 server.js
1
2
3const prerender = require('prerender');
const server = prerender();
server.start();启动并测试
1
2
3node server.js
curl http://localhost:3000/render?url=https://www.example.com/
其原理就是启动一个 headless
的 chrome
浏览器,在渲染完成后把结果在返回给客户端。
如何部署
到服务器上部署的时候会有个麻烦的问题,服务器一般都是 Liunx
系统安装 chrome
比较麻烦,那么就可以通过 Docker
来完美解决这个问题了,我已经构建了这样一个镜像,如果要使用可以通过以下步骤使用。
获取镜像
1
docker pull registry.aliyuncs.com/leiem/prerender
启动容器
1
docker run -d --restart=always -p 3000:3000 registry.aliyuncs.com/leiem/prerender
配置Nginx规则
1
2
3
4
5
6
7
8location / {
try_files $uri /index.html;
if ($http_user_agent ~* "googlebot|bingbot|yandex|baiduspider") {
rewrite .* /render?url=$scheme://$host$request_uri break;
proxy_pass http://127.0.0.1:3000;
}
}上述规则会匹配常见的搜索引擎的 User-Agent,让这些请求通过我们搭建的服务去处理。
自己构建镜像
可以直接使用我制作好的镜像 registry.aliyuncs.com/leiem/prerender
,如果要自己构建镜像可参考以下文档。
Dockerfile
1
2
3
4
5
6
7
8FROM browserless/chrome
USER root
WORKDIR /usr/src/prerender
COPY server.js package.json ./
RUN npm install
USER blessuser
EXPOSE 3000
CMD [ "npm", "run", "start" ]server.js
1
2
3
4
5
6
7
8
9
10
11
12const prerender = require('prerender')
const server = prerender({
followRedirects: true,
chromeLocation: '/usr/bin/google-chrome',
chromeFlags: [ '--no-sandbox', '--headless', '--disable-gpu', '--remote-debugging-port=9222', '--hide-scrollbars' ],
})
server.use(prerender.blockResources())
server.use(prerender.removeScriptTags())
// server.use(require('prerender-memory-cache'))
server.start()package.json
1
2
3
4
5
6
7
8
9
10
11
12{
"name": "leiem.cn",
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"prerender": "5.19.0",
"prerender-memory-cache": "1.0.2"
},
"scripts": {
"start": "node server.js"
}
}