当前位置: 首页 > 后端技术 > Node.js

不使用ssr解决Vue单页SEO问题

时间:2023-04-03 12:05:18 Node.js

遇到的问题:最近在写个人博客的时候,遇到一个大家可能会遇到的问题。vue单页在SEO上很弱,尤其是百度不会抓取动态脚本。Vue-Router做不了meta蜘蛛爬取时动态填充Vue单页标签是大势所趋。写起来不仅仅是一件很酷的事情。当然你也可以选择多页,但是面对文章和文档,即使是多页也不能说是每篇文章都生成。一个vue页面SSR固然可以解决这个问题,但是仔细想想,SSR不就是和之前的.php页面一样吗?所有的数据都是预先拉取然后填充返回给浏览器的。需要消耗更多的服务器资源,当然配置也比较繁琐。预渲染无法解决这个问题。那么问题来了。我只是想让百度抓取我的动态文章,但是配置一个繁琐的SSR对我来说不是最好的解决方案:既然我只是想让百度抓取我的动态文章,其实就是让蜘蛛抓取我的静态页面,htmlmeta标签是已经填好了,所以就很简单了,我们只需要实现一个极其简单的阉割版SSR,不就可以了吗?PS:百度了很久,没有找到相关的文章。不知是不是我的百度姿势不对?具体思路:因为我服务器的后端语言是php,而我的服务是nginx,所以我这里展示的所有后端代码都是基于php的,当然你也可以选择nodejs或者其他语言来实现。这是一个简单的想法。上面提到我们要实现一个阉割版的SSR。其实就是当服务端有请求时,在静态html的meta标签中填入数据,然后返回给请求者这里的实现是基于已经搭建好的vue单页,所以请先搭建一个vue单页,先改造建好的dist下的index.html,获取最上面的变量,因为接口都是现成的,偷懒直接调用接口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);休息;case'POST'://判断是否传输文件$params=$multi?$params:http_build_query($params);$opts[CURLOPT_URL]=$url;$opts[CURLOPT_POST]=1;$opts[CURLOPT_POSTFIELDS]=$params;休息;默认值:thrownewException('不支持的请求方法!');}/*初始化并执行curl请求*/$ch=curl_init();curl_setopt_array($ch,$opts);$data=curl_exec($ch);$error=curl_error($ch);curl_close($ch);if($error)thrownewException('请求中发生错误:'.$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标签中"/>"/><?phpecho$valTitle;?>然后将文件名改为index.php。一个函数,先丢在这里。我的服务是nginx,Vue-Router是历史模式,所以所以当有html请求的时候,我把原来对index.html的请求全部重定向到index.php,这样就实现了一个阉割版的SSR效果。这样,当网巢中的每篇文章被刷新时,相应的meta标签会被预先填入数据,配合nginx实现Vue-Router的历史模式。当然,只有历史模式才有SEO的意义。只需要将nginx配置中原来的index.html改为index.php即可,Apache也是一样location/{indexindex.php;别名/var/www/html/blog/;try_files$uri$uri//index.php;}关于后端接口请求因为我自己有服务器,后端语言是phpphp使用的框架伪静态也是需要的,所以我的解决方案是根据二级域名。代理访问的路径类似于静态资源访问。访问CDN的二级域名,通过api的二级域名服务器访问接口请求。{听80;听443SSL;server_namecdn.linkvall.cn;root/var/blog;}server{listen80;听443SSL;server_nameapi.linkvall.cn;root/var/api;}当然你可以简单地用请求的路径配置服务器{listen80;听443SSL;server_namecdn.linkvall.cn;根目录/变量;location~^/api/{alias/var/api;}location~^/blog/{alias/var/blog/;}}这样可以区分各自的资源路径,写在最后。本来打算用nodejs实现的,写一个npm包,运行一个node进程,然后nginx将请求反向代理到node端口,这样看起来比较优雅,但是后来想了想,我的后端是php,我可以通过直接代理到这个php文件来节省写作。npm包的时间就是每次改建好的html有点费力,也不优雅。这里更多的是提供一个思路。等以后有空了,说不定会自己写一个npm包来优雅的实现。