详解在不使用ssr的情况下解决Vue单页面SEO问题


Posted in Javascript onNovember 08, 2018

遇到的问题:

近来在写个人博客的时候遇到了大家可能都会遇到的问题

Vue单页面在SEO时显得很无力,尤其是百度不会抓取动态脚本

Vue-Router配合前后端分离无法让meta标签在蜘蛛抓取时动态填充

Vue单页面又是大势所趋,写起来也不止是一个爽,当然也可以选择多页面

但即使是多页面在面对文章和文档时候也不可能说给每篇文章生成个Vue页面

SSR当然能解决这个问题,但是仔细想想SSR不就跟以前的.php页面一样了么

都是预先拉取所有数据然后填充返回给浏览器,需要多消耗服务器资源,而且配置繁琐

当然预渲染也不能解决这个问题

那么问题来了,我只是想让百度抓取下我的动态文章,但是配置个繁琐的SSR并不是最好选择

我的解决办法:

既然只是想让百度抓取下我的动态文章,其实就是让蜘蛛抓取我的静态页面时候,html的meta标签是已经填充好的

那么就很简单了,我们只需要实现一个极其简单的阉割版的SSR不就好了么

PS:我百度了很久没有找到相关的文章,不知道是不是我百度的姿势不对?

具体思路:

因为我的服务器后端语言是php,service是nginx,所以我这里展示的所有后端代码都是基于php,大家当然可以选择nodejs或者其他的语言去实现,这里提供个简单的思路

上面说到我们要实现个阉割版SSR,其实就是在服务器有请求过来的时候在静态html的meta标签上填充好数据然后返回给请求端

这里的实现都是基于已经构建好的Vue单页面,所以请先构建好一个Vue单页面

先把构建好的dist下的index.html改造下

在顶部将变量拿取到,因为接口都是现成的,所以偷个懒直接调取接口

<?php

$valDescription = '前端入门,进阶总结记录,个人日志博客,分享web学习经验的小窝。';
$valKeywords = 'web窝,前端,vue,js,博客,JavaScript,css,入门,教程';
$valTitle = 'web窝';

/**
 * 发送HTTP请求方法
 * @param string $url  请求URL
 * @param array $params 请求参数
 * @param string $method 请求方法GET/POST
 * @return array $data  响应数据
 */
function http_Req($url, $params, $method = 'GET', $header = array("Content-type: text/html; charset=utf-8"), $multi = false){
  if($method == 'POST'){
    $header = ["Content-type: application/x-www-form-urlencoded"];
  }
  $opts = array(
    CURLOPT_TIMEOUT    => 30,
    CURLOPT_RETURNTRANSFER => 1,
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_SSL_VERIFYHOST => false,
    CURLOPT_HTTPHEADER   => $header
  );
  /* 根据请求类型设置特定参数 */
  switch(strtoupper($method)){
    case 'GET':
      $opts[CURLOPT_URL] = $url . '?' . http_build_query($params);
      break;
    case 'POST':
      //判断是否传输文件
      $params = $multi ? $params : http_build_query($params);
      $opts[CURLOPT_URL] = $url;
      $opts[CURLOPT_POST] = 1;
      $opts[CURLOPT_POSTFIELDS] = $params;
      break;
    default:
      throw new Exception('不支持的请求方式!');
  }
  /* 初始化并执行curl请求 */
  $ch = curl_init();
  curl_setopt_array($ch, $opts);
  $data = curl_exec($ch);
  $error = curl_error($ch);
  curl_close($ch);
  if($error) throw new Exception('请求发生错误:' . $error);
  return $data;
}
//分割当前请求的路径
$urlExp = explode('/',$_SERVER['REQUEST_URI']);
//如果当前的路径是文章内容
if(count($urlExp)>2 && $urlExp[1] == 'article'){
//请求当前文章的标题和描述
  $ret = json_decode(http_Req('http://127.0.0.1/api/Blog/getsinglelist',['tuid'=>$urlExp[2]],'POST'),true);
  $valKeywords = $ret['info'][0]['tt'].','.$valKeywords;
  $valDescription = $ret['info'][0]['txt'].' - '.$valTitle.','.$valDescription;
  $valTitle = $ret['info'][0]['tt'].' - '.$valTitle;
}
?>

将拿到的数据输出到meta标签上

<meta name="description" content="<?php echo $valDescription; ?>"/>
<meta name="keywords" content="<?php echo $valKeywords; ?>"/>

 
<title><?php echo $valTitle; ?></title>

然后把文件名改为index.php

写的很糙,反正就只有这一个功能,先扔到这

我的service是nginx,Vue-Router是history模式,所以当有html请求过来的时候我把所有原先转向index.html的请求都转向到了index.php

这样就实现了个阉割版的SSR

效果就像这样 web窝

每篇文章刷新的时候相应的meta标签都会提前填充好数据

配合nginx实现Vue-Router的history模式

当然只有history模式才有SEO的意义

只需要将nginx配置里原先转向index.html的地方改为index.php即可,Apache同理

location / {
  index index.php;
  alias /var/www/html/blog/;
  try_files $uri $uri/ /index.php;
}

关于后端接口请求的问题

因为我自己就一台服务器,后端语言是php

php所用的框架也需要伪静态

所以我的解决方式是用nginx配置根据二级域名,去代理所访问的路径

类似静态资源访问的都是cdn的二级域名,接口的请求访问的都是api的二级域名

server {
  listen    80;
  listen   443 ssl;
  server_name cdn.linkvall.cn;
  root     /var/blog;
}
server {
  listen    80;
  listen   443 ssl;
  server_name api.linkvall.cn;
  root     /var/api;
}

当然你可以简单的用请求的路径去配置

server {
  listen    80;
  listen   443 ssl;
  server_name cdn.linkvall.cn;
  root     /var;

 
location ~ ^/api/ {
alias /var/api;
}

 
location ~ ^/blog/ {
alias /var/blog/;
}
}

这样就可以把各自的资源路径区分开

写在最后

本来是打算用nodejs实现的,写一个npm包,跑一个node进程,然后nginx把请求反向代理到node端口,这样看上去更优雅

不过转念一想我的后端是php,直接代理到这个php文件可以省去写npm包的时间,就是构建好的html还要每次都更改下有一点点费劲,而且不优雅

这里更多的是提供一个思路,后面有时间了或许我会写一个npm包优雅的实现它

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JS俄罗斯方块,包含完整的设计理念
Dec 11 Javascript
jquery radio 操作代码
Mar 16 Javascript
JS实现在页面随时自定义背景颜色的方法
Feb 27 Javascript
JavaScript中判断函数、变量是否存在
Jun 10 Javascript
jQuery添加和删除指定标签的方法
Dec 16 Javascript
JSON格式的时间/Date(2367828670431)/格式转为正常的年-月-日 格式的代码
Jul 27 Javascript
详解vue.js2.0父组件点击触发子组件方法
May 10 Javascript
label+input实现按钮开关切换效果的实例
Aug 16 Javascript
JavaScript实现的斑马线表格效果【隔行变色】
Sep 18 Javascript
基于vue2.x的电商图片放大镜插件的使用
Jan 22 Javascript
重新认识vue之事件阻止冒泡的实现
Aug 02 Javascript
JavaScript实现简单日历效果
Sep 11 Javascript
Vux+Axios拦截器增加loading的问题及实现方法
Nov 08 #Javascript
Angular设置别名alias的方法
Nov 08 #Javascript
vue-cli安装使用流程步骤详解
Nov 08 #Javascript
vue项目动态设置页面title及是否缓存页面的问题
Nov 08 #Javascript
vue-awesome-swiper 基于vue实现h5滑动翻页效果【推荐】
Nov 08 #Javascript
Vue实现简易翻页效果源码分享
Nov 08 #Javascript
vue-cli3.0 环境变量与模式配置方法
Nov 08 #Javascript
You might like
可快速识别放射性物质-国外大神教你diy一个开放式辐射探测器
2020/03/12 无线电
慎用preg_replace危险的/e修饰符(一句话后门常用)
2013/06/19 PHP
迅速确定php多维数组的深度的方法
2014/01/07 PHP
php调用nginx的mod_zip模块打包ZIP文件
2014/06/11 PHP
PHP生成唯一订单号的方法汇总
2015/04/16 PHP
大家在抢红包,程序员在研究红包算法
2015/08/31 PHP
Yii2框架中日志的使用方法分析
2017/05/22 PHP
PHP实现对数字分隔加千分号的方法
2019/03/18 PHP
JavaScript控制listbox列表框的项目上下移动的方法
2015/03/18 Javascript
node.js require() 源码解读
2015/12/13 Javascript
AngularJs 弹出模态框(model)
2016/04/07 Javascript
值得学习的bootstrap fileinput文件上传工具
2016/11/08 Javascript
原生js实现类似fullpage的单页/全屏滚动
2017/01/22 Javascript
JavaScript装饰器函数(Decorator)实例详解
2017/03/30 Javascript
JavaScript Canvas绘制圆形时钟效果
2020/08/20 Javascript
详解Node.js中exports和module.exports的区别
2017/04/19 Javascript
20170918 前端开发周报之JS前端开发必看
2017/09/18 Javascript
React Native悬浮按钮组件的示例代码
2018/04/05 Javascript
JavaScript对象的浅拷贝与深拷贝实例分析
2018/07/25 Javascript
解决Idea、WebStorm下使用Vue cli脚手架项目无法使用Webpack别名的问题
2019/10/11 Javascript
[02:47]2018年度DOTA2最佳辅助位选手4号位-完美盛典
2018/12/17 DOTA
Python中列表和元组的使用方法和区别详解
2020/12/30 Python
pyqt5 tablewidget 利用线程动态刷新数据的方法
2019/06/17 Python
JAVA及PYTHON质数计算代码对比解析
2020/06/10 Python
Python 多进程、多线程效率对比
2020/11/19 Python
Melijoe时尚童装德国官网:Melijoe德国
2016/09/03 全球购物
菲律宾最大的网上花店和礼品店:PhilFlower.com
2018/02/09 全球购物
ktv总经理岗位职责
2014/02/17 职场文书
党委班子对照检查材料
2014/08/19 职场文书
遗失说明具结保证书
2015/02/26 职场文书
《清澈的湖水》教学反思
2016/02/17 职场文书
python如何获取网络数据
2021/04/11 Python
react如何快速设置文件路径别名
2021/04/28 Javascript
mysql升级到5.7时,wordpress导数据报错1067的问题
2021/05/27 MySQL
vue打包时去掉所有的console.log
2022/04/10 Vue.js
win10搭建配置ftp服务器的方法
2022/08/05 Servers