美文网首页
前后端分离 SEO预渲染

前后端分离 SEO预渲染

作者: 半打真心 | 来源:发表于2019-12-12 21:17 被阅读0次
海蒂拉玛

    技术上很多人跟我一样都是赶时髦的小伙子,但是也容易sao!断!腿!

    有一天你架构好了前后端分离的框架,项目分离、ip分离、职能分离,环境搭好、git仓库搭好、接口完成、页面完成、联 调完成,仅仅只是做个官网(天哪)。准备上线的时候上面告诉你,要严格考虑SEO,哦吼。。。

    严格考虑SEO知道意味着什么么?简单来说你的页面不能有初始化的ajax、甚至不能有js渲染页面,也就是说不能动态加载页面。在不分离的时期后 端初始化页面,完全不存在问题,前后端纯粹分离时期这就是一个棘手的问题。怎么解决?我已经趟好坑了!

    在不增加前后端工作量、前后端完全分离的基础上解决方案有两个:预渲染与SSR。这两个概念百度一下,我的项目较小所以选择“预渲染”方案。预渲染其实就是在服务器上定时跑一遍页面,并且加载好动态渲染的结构后生成一个新的页面,然后让用户直接访问这个渲染后的页面。

    这样的想法很不错,面临两道坎:1、shell脚本 2、使用无头浏览器读取动态内容。“无头浏览器”就是在命令行执行的浏览器,一个没有界面的浏览器。

步骤一、搭建前后端项目

1、假设你的服务器域名为x.com。将8000端口开放给前端,8888端口开放给后端。假设前后端项目分别为front和api。
2、front项目中将会通过定时脚本建立./dist目录,假设该定时脚本在预选染服务目录/web/preRender/shell/prerender.sh。该目录将会自动建立预渲染后的html目录,以及完全复制项目所需的依赖目录、文件。然后将80端口指向该目录,nginx配置如下

  server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name _;
        root        /web/front/dist;
        charset     utf-8;

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }

    }

在前后端以及预选染服务项目各自的代码仓库的hooks下的post-receive中添加执行脚本命令

echo 'sh /web/preRender/shell/prerender.sh' >> /home/git/front.git/hooks/post-receive
echo 'sh /web/preRender/shell/prerender.sh' >> /home/git/api.git/hooks/post-receive
echo 'sh /web/preRender/shell/prerender.sh' >> /home/git/preRender.git/hooks/post-receive

步骤二、搭建预渲染服务

1、无头浏览器选用PhantomJs。下载安装流程可以参考:

https://www.cnblogs.com/daysme/p/10250224.html

2、搭建预渲染项目,比如命名为preRender。搭建过程参考:

https://www.jianshu.com/p/117498ab0240

3、进入preRender,我们来写爬虫脚本。可以选择.js模块、也可以用php-phantomjs...,pythone、java都有相应的封装类。

js模块如下,新建spider.js

// spider.js

"use strict";

// 单个资源等待时间,避免资源加载后还需要加载其他资源

var resourceWait =10000;

var resourceWaitTimer;

// 最大等待时间

var maxWait =11000;

var maxWaitTimer;

// 资源计数

var resourceCount =0;

// PhantomJS WebPage模块

var page = require('webpage').create();

// NodeJS 系统模块

var system = require('system');

// 从CLI中获取第二个参数为目标URL

var url = system.args[1];

// 设置PhantomJS视窗大小

page.viewportSize = {

width:1280,

    height:1014

};

// 获取镜像

var capture =function(errCode){

// 外部通过stdout获取页面内容

    console.log(page.content);

    // 清除计时器

    clearTimeout(maxWaitTimer);

    // 任务完成,正常退出

    phantom.exit(errCode);

};

// 资源请求并计数

page.onResourceRequested =function(req){

resourceCount++;

    clearTimeout(resourceWaitTimer);

};

// 资源加载完毕

page.onResourceReceived =function (res) {

// chunk模式的HTTP回包,会多次触发resourceReceived事件,需要判断资源是否已经end

    if (res.stage !=='end'){

return;

    }

resourceCount--;

    if (resourceCount ===0){

// 当页面中全部资源都加载完毕后,截取当前渲染出来的html

        // 由于onResourceReceived在资源加载完毕就立即被调用了,我们需要给一些时间让JS跑解析任务

        // 这里默认预留500毫秒

        resourceWaitTimer =setTimeout(capture, resourceWait);

    }

};

// 资源加载超时

page.onResourceTimeout =function(req){

resouceCount--;

};

// 资源加载失败

page.onResourceError =function(err){

resourceCount--;

};

// 打开页面

page.open(url, function (status) {

if (status !=='success') {

phantom.exit(1);

    }else {

// 当改页面的初始html返回成功后,开启定时器

        // 当到达最大时间(默认5秒)的时候,截取那一时刻渲染出来的html

        maxWaitTimer =setTimeout(function(){

capture(2);

        }, maxWait);

    }

});

使用php-phantomjs写爬虫脚本,先composer,composer.json如下配置

    "require": {
        "jonnyw/php-phantomjs":"4.*"
    }

然后,composer update。创建入口文件index.php用以编写爬虫业务,代码如下

<?php
require __DIR__.'/vendor/autoload.php';
use JonnyW\PhantomJs\Client;

$channel_pre = $argv[1] ?? '';
preg_match("/\/(.*)\.html/i", $channel_pre, $channel_arr);
$channel = $channel_arr[1] ?? $channel_pre;
if(empty($channel)) exit('');

$url = "http://***.*.***.***:8000/{$channel}.html"; // 写自己的域名
$client = Client::getInstance();
$client->getEngine()->setPath('/usr/local/src/phantomjs/bin/phantomjs'); //设置phantomjs位置
$client->getProcedureCompiler()->clearCache();
$client->setProcedure('global_variables');
$client->isLazy();
$client->getEngine()->addOption('--load-images=true');
$client->getEngine()->addOption('--ignore-ssl-errors=true');
$request = $client->getMessageFactory()->createRequest();
$response = $client->getMessageFactory()->createResponse();
$request->setTimeout(500000); //设置超时
$request->setDelay(10);
$request->setUrl($url);
$request->setMethod('GET');
$request->addHeader('userAgent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36');
$client->send($request, $response);

echo $response->getContent();

4、在preRender目录下新建shell目录,再添加定时任务脚本prerender.sh

#!/bin/bash

if [ -d "/web/front" ]; then
  cd /web/front
  if [ -f "/web/preRender/index.php" ]; then
    if [ ! -d "./dist" ]; then
      mkdir -p dist
      chown -R git:git dist
    fi
    # 复制一级页面
    for n in `find . -maxdepth 1 -name "*.html"`; do
      if [ ! -f "./dist/"$n ]; then
        touch ./dist/${n}
        chown -R git:git dist
      fi
      echo `php /web/qjhPreRender/index.php $n` > ./dist/${n}
    done
    # 复制一级目录
    for m in `find . -maxdepth 1 -type d`; do
      if [ $m != './.idea' ] && [ $m != './.git' ] && [ $m != '.' ] && [ $m != './dist' ]
      then
        cp -arf ${m} ./dist/
      fi
    done
  fi
fi

步骤三、设置定时任务

先不用守护进程的方式,就用普通的crontab。

# crontab -e

*/2 * * * * sh /web/preRender/shell/prerender.sh

# crontab -l

    以上就完成了一个预渲染,这样前后端各忙各的,谁都不要做多余的工作就按自己一贯的节奏开发即可。这些工作建议架构师自己来完成!

相关文章

  • 前后端分离 SEO预渲染

    技术上很多人跟我一样都是赶时髦的小伙子,但是也容易sao!断!腿! 有一天你架构好了前后端分离的框架,项目分离、i...

  • 前后端渲染扫盲

    前言 1. 基础概念 在讲前端渲染和后端渲染之前,我们需要首先明白一些概念:前端渲染、后端渲染、同构渲染、SEO ...

  • nodejs作为前后端分离中间件的跨域解决方案

    前后端分离时候SEO问题很头疼,上次提供了nuxt+axios解决服务端渲染问题的解决方案,其实nodejs一样可...

  • 基于vue的服务端渲染

    SPA缺点: 不利于SEO ===》 服务端渲染SSR 首屏渲染时间长 ===》 预渲染Prerenderi...

  • 基于Flask开发的前后端分离租房项目(一)

    一、明确前后端分离和前后端不分离的概念: 我的理解:前后端不分离的概念是后端要控制前端的数据显示和模板渲染(dja...

  • 基于 Next.js 的 SSR/SSG 方案了解一下?

    最近在探索学习前端工程化相关内容,在如今前后端分离的架构下,为了提升首屏渲染速度和 SEO 效果,兜兜转转,又回到...

  • JavaScript XHR

    前后端分离 服务端渲染 什么是HTTP

  • 前端杂谈

    1. SPA优缺点? 缺点:不利于SEO ----> 服务端渲染 SSR首屏渲染时间长 ----> 预渲染 优点...

  • 前后端不分离和分离的区别

    前后端不分离 在前后端不分离的应用模式中,前端页面看到的效果都是由后端控制,由后端渲染页面或重定向,也就是后端需要...

  • 前后端分离的必要性

    前后端分离之前 在前后端分离观点出现之前,我们往往都是后端直接使用后端模板引擎渲染出html页面,当然这个时候对于...

网友评论

      本文标题:前后端分离 SEO预渲染

      本文链接:https://www.haomeiwen.com/subject/ygvtnctx.html