利用 PhantomJS 為 SPA 做 SEO

利用 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 為 SPA 做 SEO

PhantomJS 加入與修改之後

一般使用者(非 robot)檢視原始碼時會看到這樣的狀況,經由 ajax 取得資料後 append 到畫面上的區塊依然是空的。

利用 PhantomJS 為 SPA 做 SEO

但…使用 webmaster 的測試工具來測,robot 可以檢視到經由 ajax 取得資料後 append 到 畫面上的文字。

利用 PhantomJS 為 SPA 做 SEO

總結:優缺比較

優點

可讓 robot 讀取由 JavaScript render 的頁面。

缺點

每一次 robot 來訪時,就會執行兩次回應:一次是 robot 讀取頁面,一次是 PhantomJS 打開頁面(程式碼中 return page.open(fullUrl) 這一行),增加 Server 端的負擔。並且,phantomjs 打開頁面後產生的靜態內容是每次都會重新產生的。

由於這些缺點,因此還找了其他解法使用。例如:使用 Prerender.io 或自己實作後端 render 的服務,請看這裡

推薦閱讀

參考資料


這篇文章的原始位置在這裡-利用 PhantomJS 為 SPA 做 SEO

由於部落格搬遷至此,因此在這裡放了一份,以便閱讀;部份文章片段也做了些許修改,以期提供更好的內容。

SEO 搜尋引擎優化 node.js SEO101