利用 PhantomJS 為 SPA 做 SEO
11 Sep 2016隨著前端技術的不斷更新,使用前端框架(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
- Easily index your Single Page Application thanks to PhantomJS
- Getting Started - ajax Crawling (Deprecated) - Google Developers
這篇文章的原始位置在這裡-利用 PhantomJS 為 SPA 做 SEO
由於部落格搬遷至此,因此在這裡放了一份,以便閱讀;部份文章片段也做了些許修改,以期提供更好的內容。