网页预渲染方案

2019-07-24  本文已影响0人  鹤空

起因

业务需要,对官网进行改版,服务对象由C端转为B端,对SEO有比较强的需求。

目前项目是采用vue框架,多页配置。页面内容由js动态加载,不利于搜索引擎抓取,首屏渲染速度也有一定影响。

为了解决爱尖子官网的SEO优化,及页面渲染速度优化问题,有如下几种方案。

  1. 后端渲染不使用vue,react框架(node express,jsp)
    • 该方案直接pass
  2. vue SSR
    • 需要对项目结构重新构建
    • 需要node服务器,相对于静态文件来说,服务器压力比较大
    • 服务端渲染,某些生命周期不可用
  3. nuxt
    • 没咋用过
  4. prerender-spa-plugin
    • 该插件也是基于puppeteer无头浏览器
    • 问题是每当站点内容需要更新时,都需要重新打包发布
  5. 自己使用无头浏览器(puppeteer),生成静态页面
    • 自己写脚本比较灵活
    • 内容变化时,可以随时执行脚本,更新静态内容

方案

我们选择第5种方案,以下是基础流程图。

黄色部分为预渲染流程

流程图,大图看这里

image

实施

搭建预渲染服务

npm 下载 puppeteer,由于网络问题,使用cnpm

cnpm install puppeteer --save

npm 下载express,搭建node服务

使用puppeteer 获取html

const puppeteer = require('puppeteer');                               
let browser;                                                          
async function createInstance(options) {                              
  if(browser) return;                                                 
    const config = Object.assign(                                     
          {},                                                         
          {                                                           
                  ignoreHTTPSErrors: true,                            
                  devtools: false,                                    
                  headless: true,                                     
                  args: ['--no-sandbox', '--disable-setuid-sandbox'], 
                },                                                    
          options                                                     
        );                                                            
                                                                      
    browser = await puppeteer.launch(config);                         
}                                                                     
async function closeInstance() {                                      
}                                                                     
module.exports =                                                      
  async function getHtml(url) {                                       
    await createInstance();                                           
    const page = await browser.newPage();
    // 设置header 重要 nginx根据此header做跳转
    page.setExtraHTTPHeaders({prerender:"ajz"});
    await page.goto(url, {waitUntil: 'networkidle2'});                
    const html = await page.$eval('html', e => e.outerHTML);          
    await page.close();                                               
    return html;                                                      
}                                                                                                                                  

编写请求处理逻辑

 var express = require('express');                        
 var router = express.Router();                           
 var getHtml = require('../getHtml');                     
                                                          
 /* GET home page. */                                     
 router.get('/', function(req, res, next) {              
      res.render('index', { title: 'Express' });         
    });                                                  
 router.get('/render', async function(req, res, next) {  
      let query = req.query.url;                         
      if (query) {                                       
           let url = decodeURIComponent(query);        
           let html = await getHtml(url);              
           res.send(html);                             
       } else {                                      
           res.send('url is undefind')                 
       }                                              
    })                                                   
                                                         
 module.exports = router;                                
nginx配置
 server {                                                     
         listen 80;                                           
         server_name localhost testy.aijianzi.com;            
         access_log /var/log/nginx/testy.access.log;       
         location / {                                         
                 root /www/www.aijianzi.com/dist-static; 
                 // 根据header跳转
                 if ($http_prerender = "ajz") {               
                         root /www/www.aijianzi.com/dist-static;
                 }                                            
                 index index.html;                            
                                                              
                 autoindex off;                               
                                                              
         }                                                    
 # redirect server error pages to the static page /50x.html   
 error_page 500 502 503 504 /50x.html;                        
 location = /50x.html {                                       
         root /var/www/nginx-default;                         
 }                                                            
  # deny access to .htaccess files, if Apache’s document root 
 location ~ /\.ht {                                           
         deny all;                                            
 }                                                            
 }                                                            

配置之后的访问效果

通过预渲染服务器访问 获取到真实的页面

image

用户直接通过域名访问,获取到已经渲染好的静态页面

image
编写shell脚本

通过脚本,快捷的更新静态文件。可手动触发,计划任务定时触发

#!/bin/bash
static-workspace="/www/www.aijianzi.com/dist-static"
readonly static-workspace
cd ${static-workspace}
curl -o index.html http://localhost:3000/render?url=http://testy.aijianzi.com
上一篇 下一篇

猜你喜欢

热点阅读