先撸撸几个概念:html
Nuxt => Vue 基本是Next的翻版,语法也是Next语法,大坑的地方是在 大多数稳定的项目是1.4.2的版本 现有2.X的版本 基本彻底不兼容老版本。前端
PhantomJS 原理就是经过Nginx配置,将搜索引擎的爬虫请求转发到一个node server,再经过PhantomJS来解析完整的HTML。vue
总体仍是结合当前需求的场景 和自身的条件来进行选择,短期高效完成需求。node
相关收录文章:linux
Nuxt
Next
Prerender + vuejs SEO最佳实践 百度爬虫 + 谷歌收录 亲测成功 Prerender.io
前端渲染与 SEO 优化踩坑 小记
用PhantomJS来给AJAX站点作SEO优化
首先,咱们须要一个叫spider.js的文件,用于phantomjs 解析网站。web
"use strict"; // 单个资源等待时间,避免资源加载后还须要加载其余资源 var resourceWait = 500; var resourceWaitTimer; // 最大等待时间 var maxWait = 5000; 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); } });
进行测试=> phantomjs spider.js 'https://www.baidu.com/'
express
响应搜索引擎爬虫的请求,咱们须要将此命令服务化,经过node起个简单的web服务缓存
var express = require('express'); var app = express(); // 引入NodeJS的子进程模块 var child_process = require('child_process'); app.get('/', function(req, res){ // 完整URL var url = req.protocol + '://'+ req.hostname + req.originalUrl; console.log(req,req.hostname) // 预渲染后的页面字符串容器 var content = ''; // 开启一个phantomjs子进程 var phantom = child_process.spawn('phantomjs', ['spider.js', url]); // 设置stdout字符编码 phantom.stdout.setEncoding('utf8'); // 监听phantomjs的stdout,并拼接起来 phantom.stdout.on('data', function(data){ content += data.toString(); }); // 监听子进程退出事件 phantom.on('exit', function(code){ switch (code){ case 1: console.log('加载失败'); res.send('加载失败'); break; case 2: console.log('加载超时: '+ url); res.send(content); break; default: res.send(content); break; } }); }); app.listen(3002)
运行node server.js,此时咱们已经有了一个预渲染的web服务啦,接下来的工做即是将搜索引擎爬虫的请求转发到这个web服务,最终将渲染结果返回给爬虫。
为了防止node进程挂掉,可使用nohup来启动,nohup node server.js &。
经过Nginx配置,咱们能够轻松的解决这个问题。服务器
# 定义一个Nginx的upstream为spider_server upstream spider_server { server localhost:3000; } # 指定一个范围,默认 / 表示所有请求 location / { proxy_set_header Host $host:$proxy_port; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 当UA里面含有Baiduspider的时候,同时能够加其余的头信息进行转发 流量Nginx以反向代理的形式,将流量传递给spider_server if ($http_user_agent ~* "Baiduspider") { proxy_pass http://spider_server; } }
参考连接:
https://www.mxgw.info/t/phant...
http://imweb.io/topic/560b402...
https://icewing.cc/linux-inst...
https://www.jianshu.com/p/2bb...