利用PhantomJS為SPA做SEO
隨著前端技術的不斷更新,使用前端框架(React、Vue等)來建構網站是普遍現象。但目前搜尋引擎無法有效讀取使用JavaScript render出來的頁面,且使用AJAX Crawling的解法只適用於Google又此法已被廢棄,因此另一解法就是使用PhantomJS。
這裡使用 Node.js + PhantomJS 為SPA/以Ajax讀取資料的頁面做SEO。
說明
以下程式碼是我為某個頁面寫的範例。
頁面載入時會用ajax取得一行字串「今天吃飯,該吃什麼好呢?只要輸入美食欲望,立刻給你最真實、現場、生活化的評價,找餐廳再也不煩惱,就讓吃什麼,どっち幫你決定吃什麼!」,然後append到畫面上。
程式流程:當讀取頁面的時候,先去判斷是不是robot,如果是robot,就使用PhantomJS丟給它已讀取好的靜態頁面內容,說白話些就是預先載入頁面後取得頁面內容;如果不是robot,就走一般的流程,也就是render樣版。
PhantomJS和Node.js是不相容的,因此使用了一個中間橋梁phantom - Fast NodeJS API for PhantomJS。但這不是官方的,可能會因為各種原因崩解。
程式碼
var express = require('express'),
router = express.Router(),
phantom = require('phantom'),
fs = require('fs');
router.get('/', function(req, res, next) {
var ua = req.headers['user-agent'],
fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl,
pattern = /Googlebot|Googlebot-News|Googlebot-Image|Googlebot-Video|Googlebot-Mobile|Mediapartners-Google|Mediapartners|AdsBot-Google|AdsBot-Google-Mobile-Apps/i,
isRobot = pattern.test(ua);
if(isRobot) {
var sitepage = null,
phInstance = null;
phantom.create().then(function (instance) {
phInstance = instance;
return instance.createPage();
}).then(function (page) {
sitepage = page;
return page.open(fullUrl);
}).then(function (status) {
return sitepage.property('content');
}).then(function (content) {
res.send(content);
sitepage.close();
phInstance.exit();
}).catch(function (error) {
console.log(error);
phInstance.exit();
});
} else {
res.render('system', {
title: '吃什麼,どっち',
description: '今天吃飯,該吃什麼好呢?只要輸入美食欲望,立刻給你最真實、現場、生活化的評價,找餐廳再也不煩惱,就讓吃什麼,どっち幫你決定吃什麼!'
});
}
});
router.post('/getInfo', function(req, res, next) {
res.json({
isSuccess: true,
response: '今天吃飯,該吃什麼好呢?只要輸入美食欲望,立刻給你最真實、現場、生活化的評價,找餐廳再也不煩惱,就讓吃什麼,どっち幫你決定吃什麼!'
});
});
module.exports = router;
測試結果
未經過PhantomJS加入與修改之前
未經過PhantomJS加入與修改之前,robot只能看到這樣的狀況--經由Ajax取得資料後append到畫面上的區塊是空的。
PhantomJS加入與修改之後
一般使用者(非robot)檢視原始碼時會看到這樣的狀況,經由Ajax取得資料後append到畫面上的區塊依然是空的。
但...使用webmaster的測試工具來測,robot可以檢視到經由Ajax取得資料後append到畫面上的文字。
總結:優缺比較
優點
可讓robot讀取由JavaScript render的頁面。
缺點
每一次robot來訪時,就會執行兩次回應:一次是robot讀取頁面,一次是PhantomJS打開頁面 (程式碼中 return page.open(fullUrl)
這一行),增加Server端的負擔。並且,phantomjs打開頁面後產生的靜態內容是每次都會重新產生的。
由於這些缺點,因此還找了其他解法使用。例如:使用Prerender.io或自己實作後端render的服務,後續會有相關文章說明和實驗。
推薦閱讀
參考資料
- phantom - Fast NodeJS API for PhantomJS
- PhantomJS | PhantomJS
- Easily index your Single Page Application thanks to PhantomJS
- Getting Started | AJAX Crawling (Deprecated) | Google Developers
由於部落格搬家了,因此在新落格也放了一份,未來若有增刪會在這裡更新-利用 PhantomJS 為 SPA 做 SEO。
留言