单页面应用的主要内容都依赖于JS的执行,当其首页面下载下来的时候,其实不是完整的页面,而是HTML + JS文件,浏览器提供执行环境于是页面被渲染了出来。用户在访问的时候体验会很好,但是对于搜索引擎的爬虫就不太友善了,因为他们不能执行JS,这时候Prerender就派上用场了,它可以帮忙把页面渲染完成之后再返回给爬虫工具,我们的页面也就能被解析到了。最近我尝试搭建了基于本地的Prerender + NGINX的预渲染服务,希望可以帮到大家。

前置条件

由于本地的Prerender服务需要有NodeJs环境支持,如果之前服务器环境没有NodeJs需要先进行安装,可参考官网。

安装Prerender

此处我们假定安装目录在 /opt/ 下

1
2
3
4
5
6
7
8
9
10
cd /opt
git clone https://github.com/prerender/prerender.git
cd prerender

# Phantomjs 官方的下载地址会超时,此处重新指定其下载地址为淘宝镜像
export PHANTOMJS_CDNURL=https://npm.taobao.org/mirrors/phantomjs
npm install

# 启动Server.js, 默认监听3000端口
node server.js

可以通过curl进行测试,看看返回的内容是不是解析后的内容

1
2
# 如果按照成功,通过3000端口访问后的页面内容是已经解析过的
curl http://localhost:3000/http://hostname.com/webpath

配置NGINX

我们假设项目的访问路径为 http://hostname.com/webpath/anything, 将所有/webpath/*的请求当做项目的入口地址。参考官方配置

我们只需要针对搜索引擎的访问进行Prerender预渲染,正常的浏览器访问我们避免通过Prerender进行渲染

10
11
12
13
14
15
16
17
18
19
20
21
22
location^~ /webpath/ {
set $prerender 0;
if ($http_user_agent ~* "baiduspider|twitterbot|facebookexternalhit|rogerbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator") {
set $prerender 1;
}

# 谷歌推荐的配置方式
if ($args ~ "_escaped_fragment_") {
set $prerender 1;
}

if ($prerender = 1) {
# 官方推荐通过$prerender变量来进行跳转来解决NGINX缓存
set $prerender "127.0.0.1:3000";

rewrite .* /$scheme://$host$request_uri? break;
proxy_pass http://$prerender;
}

# 此处,我们假设主页面html为 /index.html
try_files $uri$args /index.html;
}

在上面的NGINX配置中,我们针对请求参数包括 _escaped_fragment_ 也启用了Prerender服务,官方说明表示谷歌会通过这种方式来抓取单页面应用。而我们也可以借助这个特点很方便地测试配置是否正确:

1
2
# 不再需要直接访问 localhost:3000的地址了
curl http://hostname.com/webpath/anything?_escaped_fragment_=

在配置NGINX以前,以上返回的只是index.html的内容, 如果配置成功则会返回解析后的内容。

将Prerender加入守护进程

上面的功能虽然能运行起来了,但是Prerender服务是依赖于SSH终端的,如果这个终端被关闭,那么服务也就被关闭了,为此我们需要将Prerender加入守护进程。
我直接使用了Git上的一个Prerender守护进程模板,并将其配置成我的环境,如下:

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
21
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/bin/sh
#
# chkconfig: 35 99 99
# description: prerender.js server for the given user
#

. /etc/rc.d/init.d/functions

APPNAME="Prerender"

# 用来运行Prerender服务的用户
USER="<user that runs prerender>"

# Node命令的路径,此处我直接配置为"node",因为node已经加入全局变量
DAEMON="node"

# Prerender的安装目录,即是我们拷贝下来的Prerender文件夹目录,此处为 /opt/prerender
ROOT_DIR="<path to prerender>"

SCRIPT="$(basename $0)"
PIDFILE="/var/run/$SCRIPT.pid"

SERVER="$ROOT_DIR/server.js"
LOG_FILE="/var/log/prerender.log"
SHUTDOWN_WAIT=20

app_pid()
{
echo `ps -aefw | grep "$DAEMON $SERVER" | grep -v " grep " | awk '{print $2}'`
}

do_start()
{
echo -n $"Starting $SERVER: "
pid=$(app_pid)
if [ -n "$pid" ]
then
echo "$APPNAME is already running (pid: $pid)"
else
if [ ! -w $LOG_FILE ]
then
if [ ! -e $LOG_FILE ]
then
touch $LOG_FILE
fi
chown $USER $LOG_FILE
fi
echo "$APPNAME  is not running - starting it up!"
runuser  --shell=/bin/bash -l "$USER" -c "$DAEMON $SERVER >> $LOG_FILE 2>&1 &"
pid=$(app_pid)
echo $pid > ${PIDFILE}
do_status
RETVAL=$?
echo
[ $RETVAL -eq 0 ]
fi
return 0
}

do_wait()
{
echo "Waiting for process to exit";
pid=$(app_pid)
if [ -n "$pid" ]
then
let kwait=$SHUTDOWN_WAIT
count=0;
until [ `ps -p $pid | grep -c $pid` = '0' ] || [ $count -gt $kwait ]
do
echo -n -e "\nwaiting for processes to exit";
sleep 1
let count=$count+1;
done
fi
return 0
}

do_stop()
{
echo -n $"Stopping $APPNAME : "
pid=`ps -aefw | grep "$DAEMON $SERVER" | grep -v " grep " | awk '{print $2}'`
kill -9 $pid > /dev/null 2>&1 && echo_success || echo_failure
if [ -f ${PIDFILE} ]; then
rm ${PIDFILE}
fi
RETVAL=$?
echo
[ $RETVAL -eq 0 ]
}

do_status()
{
pid=$(app_pid)
if [ -n "$pid" ]
then
echo -n "$APPNAME is running (pid: $pid)"
echo_success
else
echo -n "$APPNAME is not running"
echo_failure
fi
echo
return 0
}

case "$1" in
start)
do_start
;;
stop)
do_stop
;;
status)
do_status
;;
restart)
do_stop
do_wait
do_start
;;
*)
echo "Usage: $0 {start|stop|restart|status}"
RETVAL=1
esac

exit $RETVAL

将此文件命名为 prerender, 并拷贝至 /etc/init.d/ 目录下。然后我们重新载入脚本:

1
2
3
4
5
6
7
8
# 服务新增文件可执行权限
chmod +x /etc/init.d/prerender

# 重新载入systemctl
systemctl daemon-reload

# 启动
service prerender start

后续,我们可以通过 service prerender start|stop|restart 来起停服务,同时Prerender也会随机启动。

http://codingfishman.github.io/2016/05/06/prerender%E9%A2%84%E6%B8%B2%E6%9F%93%E4%BC%98%E5%8C%96SEO/

Prerender预渲染优化SEO相关推荐

  1. vue项目使用预渲染 进行seo优化

    vue项目使用预渲染 进行seo优化 vue进行seo优化的两个方法 1.预渲染*** 针对项目其中几个页面的seo,标题不能通过接口数据动态渲染 情况使用 使用以下两个插件进行预渲染seo优化: n ...

  2. vue使用prerender预渲染配合vue-meta实现单页面实现SEO优化

    公司项目在已在开发完成的情况下通知需要做SEO优化.因为项目使用的是vue做的单页面应用,顿时人都不好了,只好网上搜罗出来一些配置(其实是另一个带我的老大哥他做的,但是他要走了,工作交接给我, 我需要 ...

  3. prerender ajax,Vue Prerender.io 预渲染seo优化

    前言 目前 Vue单页面应用在前端界混的风生水起,它的开发思想使得我们能真正做到前后端分离.解耦.单页面应用使用浏览器动态解析JS,呈现出最终的页面,用户体验比较好,网站性能也提高不少.但网络爬虫并不 ...

  4. prerender html5,HTML5 VUE单页应用 SEO 优化之 预渲染(prerender-spa-plugin)

    前言:当前 SPA 架构流行的趋势如日中天,前后端分离的业务模式已经成为互联网开发的主流方式,但是 单页面 应用始终存在一个痛点,那就是 SEO, 对于那些需要推广,希望能在百度搜索时排名靠前的网站而 ...

  5. 构建时预渲染:网页首帧优化实践

    前言 自JavaScript诞生以来,前端技术发展非常迅速.移动端白屏优化是前端界面体验的一个重要优化方向,Web 前端诞生了 SSR .CSR.预渲染等技术.在美团支付的前端技术体系里,通过预渲染提 ...

  6. 前端性能优化 之 首屏预渲染

    本文介绍一种优化首屏访问速度的技术:前端预渲染,并封装自定义的React hook,解决预渲染中的数据初始化问题. 一.首屏速度慢的问题 如果网站页面首屏访问比较慢,应该怎么优化呢? 这要结合实际情况 ...

  7. vue项目利用预渲染prerender-spa-plugin处理seo --viga

    vue项目利用预渲染处理seo 写在前面 什么是SEO? SEO是英文 Search Engine Optimization 的缩写,中文意思"搜索引擎优化".SEO是指在了解搜索 ...

  8. Vue SPA项目SEO优化之预渲染Prerender-spa-plugin

    目的 由于基于Vue的SPA项目普通的爬虫无法爬取项目的静态文本的内容,通过预渲染插件prerender-spa-plugin解决vue的SPA项目的SEO问题. 可以看到项目编译后的index.ht ...

  9. vue的SEO优化——预渲染后路由+点击事件失效问题解决

    vue是单页面框架且前后端分离,不利于seo优化.针对这一点,还是有解决办法的. 预渲染后路由+点击事件失效问题解决--近期发现 最近遇到了一个前台官网,由于时间比较紧,所以我选择了用vue框架去搭建 ...

最新文章

  1. JAVA环境变量配置与配置后CMD的使用
  2. 将某个目录上的Excel表,导入到数据库中.sql
  3. 洛谷 1858 多人背包
  4. centos7 編譯 chmsee
  5. 图解 MongoDB 地理位置索引的实现原理
  6. hdu 5144 NPY and shot(三分)
  7. Sendmail with Attachment script
  8. 在C 语言中 下列变量命名不合规范的是,GJB9001C-2017内审员培训试题D卷(答案)
  9. scrapy实现爬取全书网小说到本地TXT文件
  10. 解决可视化界面的时候灰屏【已解决】
  11. w ndows10更新后变成32位了,三种直接从 Win7 升级到 Win10 的方法
  12. 2019工程伦理慕课答案(2019秋)习题及期末答案
  13. LabVIEW编程LabVIEW开发1920 LCR仪表例程与相关资料
  14. WPF之Binding深入探讨
  15. 无线模块为什么要加屏蔽罩外壳?
  16. 对于java的初步认识
  17. React实现(Web端)网易云音乐项目(三),错过了真的可惜呀
  18. 65Z5的芯片,65Z5三极管,稳压输出3V的IC资料
  19. 图片版权保护 用这个盲水印API就够了
  20. jmh气象传真图网站_接收日本JMH气象传真

热门文章

  1. ​外观专利申请的申请文件、流程
  2. 服务器如何有效防御CC攻击?
  3. UVa220黑白棋问题
  4. 有源钳位正激变换器的设计及其 PoE BT 中的应用
  5. 领导想提拔你,这点最真实,可别犯傻不当回事!
  6. 魅族要加入鸿蒙系统,魅族宣布接入鸿蒙系统
  7. html字体下沉怎么设置,Word表格中字体下沉设置
  8. 山东理工大学中外合作办学计算机专业,山东理工大学学费多少 收费标准
  9. Linux系统如何安装oki打印机,oki打印机驱动安装图解
  10. 移动 WEB 开发之 阿里百秀移动端页面制作