先擼擼幾個概念: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...