Angular2 網站 SEO 攻略

Angular 的優勢有不少,但若是用它來開發網站的話,就不得不面對它的兩大缺點:javascript

  • 首頁加載慢
  • 搜索引擎的爬蟲獲取不到頁面內容

因爲 Angular 是經過 js 動態生成 dom 並插入到頁面中,搜索引擎默認只能得到頁面的標題。咱們可使用 curl[1] 命令測試一下。css

curl http://localhost:17082

能夠看到相似這樣的內容:html

<!doctype html><html lang="en"><head><meta charset="utf-8"><title>網站的標題</title><base href="/"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" type="image/x-icon" href="favicon.ico"><link href="styles.d41d8cd98f00b204e980.bundle.css" rel="stylesheet"/></head><body style="margin:0px;"><app-root></app-root><script type="text/javascript" src="inline.59a79e692d20ba910ed0.bundle.js"></script><script type="text/javascript" src="polyfills.5d1d5b016f19755a7d41.bundle.js"></script><script type="text/javascript" src="main.a8103efb00c40fad2538.bundle.js"></script></body></html>

整個頁面內容只剩下 title 了。java

解決方案

目前有三種解決方案:node

  1. 服務器端渲染。能夠一次解決首屏加載慢和SEO問題。解決方案比較複雜,跨度較大。
  2. 頁面緩存服務。目前比較流行的是 prerender.io。能夠說是目前最簡單且可用的 SEO 方案。本文將重點介紹此方案。
  3. 使用 phantomjs 生成靜態頁,再配置 nginx 在爬蟲訪問時提供靜態頁中的內容。實測稍微複雜一點的頁面用 phantomjs 生成靜態頁時會報錯。本文將只簡單介紹生成首頁靜態頁的方法。

使用 prerender 頁面緩存服務

要演練此部份內容,首先你要把網站用 nginx 部署[2]。
prerender 的原理是,配置 nginx,判斷出是爬蟲來訪時,先將請求頁面地址發送給 prerender 服務,由 prerender 服務渲染出頁面內容,再將頁面內容返回給爬蟲。prerender 官網提供的服務地址是http://service.prerender.io/ 咱們能夠測試一下該服務的效果,在瀏覽器中訪問:linux

https://service.prerender.io/https://www.google.com

便可在瀏覽器中看到由 prerender 服務返回的靜態頁面內容了。
雖然咱們能夠直接使用 http://service.prerender.io/ 服務,但若是你不但願依賴一個隨時可能沒法訪問的服務的話,能夠架設一個本身的 prerender 服務。或者你但願在本地演練,尚未公網的IP或域名時,也須要架設本身的 prerender 服務。nginx

架設本身的 prerender 服務(可選)

首先在 github 上下載 prerender 源代碼。下載後執行「npm install」安裝依賴項,再執行「node server.js」便可開啓服務,默認端口號是 3000.咱們可使用git

http://localhost:3000/https://www.baidu.com

測試一下。github

注意: 若是是在 linux 下部署的話,還必須先安裝 chrome 瀏覽器,而且不要以 root 身份執行 「node server.js」。想要一直後臺運行服務的話,能夠安裝 forever:「npm install forever -g」,而後使用 「forever start server.js」 後臺運行服務。web

修改 nginx 配置文件

這一步是比較複雜和關鍵的。好在 prerender 已經給咱們寫好了 nodejs、ruby on rails、asp.net、nginx、Apache 等 10 多種 Web 服務器的配置方案,例如官方提供的 nginx 配置方式,但實測此配置文件有一點問題,直接拿過來用是很差用的。我對它進行了一些小修改:

server {
        listen       17082;
        server_name  localhost:17082;

        location / {
            root   C:\projects\bzbclub-dist;
            index  index.html;

            location / {
                try_files $uri @prerender;
            }
        }

        location @prerender {
            #proxy_set_header X-Prerender-Token YOUR_TOKEN;
            
            set $prerender 0;
            if ($http_user_agent ~* "baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator") {
                set $prerender 1;
            }
            if ($args ~ "_escaped_fragment_") {
                set $prerender 1;
            }
            if ($http_user_agent ~ "Prerender") {
                set $prerender 0;
            }
            if ($uri ~* "\.(js|css|xml|less|png|jpg|jpeg|gif|pdf|doc|txt|ico|rss|zip|mp3|rar|exe|wmv|doc|avi|ppt|mpg|mpeg|tif|wav|mov|psd|ai|xls|mp4|m4a|swf|dat|dmg|iso|flv|m4v|torrent|ttf|woff|svg|eot)") {
                set $prerender 0;
            }
            
            #resolve using Google's DNS server to force DNS resolution and prevent caching of IPs
            resolver 8.8.8.8;

            if ($prerender = 1) {
                rewrite .* /$scheme://$host:$server_port$request_uri? break;
                proxy_pass http://localhost:3000;
            }
            if ($prerender = 0) {
                rewrite .* /index.html; # 注意這裏去掉告終尾的 「break」,不然會報 404 錯誤
            }
        }
    }

修改完配置文件記得要使用命令 「nginx -s reload」 從新加載。
以後咱們首先用瀏覽器訪問咱們的網站,測試一下正常訪問沒有異常。而後就可使用 curl[1] 命令模擬百度蜘蛛訪問頁面了。

curl -A "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)" http://localhost:17082 > z:\temp\bzb-baidu.html

以後打開 z:\temp\bzb-baidu.html 應該能夠看到由 prerender 服務渲染出的頁面內容。

使用 prerender 緩存服務(可選)

不管使用 prerender 官網上的服務仍是本身架設 prerender 本地服務,它的速度都不快。雖然 prerender 服務返回的頁面內容只給爬蟲看,並不影響用戶體驗,但爬蟲得到網頁內容的響應時間也是影響搜索結果排名的!聰明的 prerender 在此看到了商機。咱們來試用一下。首先,你要把 nginx.conf 中的本地服務改爲官方服務 https://service.prerender.io 。而後在prerender 官網註冊帳戶,驗證郵件後登陸,默認就會進入「Cached Pages」標籤頁,裏面「your token:」後面跟着的就是分配給你的 token。將此 token 放置到 nginx.conf 中被註釋掉的那行 「X-Prerender-Token」 後面並取消註釋便可:

location @prerender {
            proxy_set_header X-Prerender-Token rM9WgVZmgir9bSiE4sGp;
            
            set $prerender 0;
            if ($http_user_agent ~* "baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator") {
                set $prerender 1;
            }
            if ($args ~ "_escaped_fragment_") {
                set $prerender 1;
            }
            if ($http_user_agent ~ "Prerender") {
                set $prerender 0;
            }
            if ($uri ~* "\.(js|css|xml|less|png|jpg|jpeg|gif|pdf|doc|txt|ico|rss|zip|mp3|rar|exe|wmv|doc|avi|ppt|mpg|mpeg|tif|wav|mov|psd|ai|xls|mp4|m4a|swf|dat|dmg|iso|flv|m4v|torrent|ttf|woff|svg|eot)") {
                set $prerender 0;
            }
            
            #resolve using Google's DNS server to force DNS resolution and prevent caching of IPs
            resolver 8.8.8.8;

            if ($prerender = 1) {
                rewrite .* /$scheme://$host:$server_port$request_uri? break;
                proxy_pass https://service.prerender.io;
            }
            if ($prerender = 0) {
                rewrite .* /index.html; # 注意這裏去掉告終尾的 「break」,不然會報 404 錯誤
            }
        }

修改配置以後使用命令「nginx -s reload」從新加載,而後再次模擬百度蜘蛛訪問:

curl -A "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)" http://47.94.88.230 > z:\temp\bzb-online.html

刷新 prerend.io 頁面,在「Cached Pages」標籤頁下方的列表中便可看到已被自動緩存了的頁面地址。實測不用緩存的時候要 三、4 秒鐘的頁面,緩存後只要 0.2 秒,效果很理想。不過免費帳戶最多隻給緩存 250 個頁面,通常也夠用了。若是想要緩存更多頁面的話就付費吧,價格表在https://prerender.io/pricing,起步價每個月 15 美圓能夠緩存 20000 個頁面。但須要注意的是,緩存默認的刷新週期都是 7 天,免費版也能夠自由修改刷新週期,最短到 1 天。但付費版則是週期越短費用越高,例如起步價 15 美圓那個,7 天要 15 美圓,6 天要 17 美圓,5 天要 20 美圓,1 天則要 84 美圓。

使用 phantomjs 生成靜態頁

prerender已經足夠好了,但若是你想多瞭解一下 phantomjs 的話,請接着往下看。使用此種方案,須要解決 3 個問題:

  1. 如何得知網站有多少須要生成靜態頁的頁面,生成的靜態頁文件以何種層級關係存放,以及如何把訪問地址與靜態頁文件匹配。
  2. 如何使用 phantomjs 生成靜態頁。
  3. 如何在爬蟲訪問時讓爬蟲獲取到靜態頁中的內容。

咱們先忽略前兩個問題,假設如今已經生成了首頁的靜態頁(能夠先經過瀏覽器保存網頁的功能獲得首頁的靜態頁),先解決問題3。

如何在爬蟲訪問時讓爬蟲獲取到靜態頁中的內容

要演練此部份內容,首先你要把網站用 nginx 部署[2]。

如何判斷是爬蟲訪問仍是瀏覽器訪問

爬蟲訪問時,會使用特殊的 user agent,以百度蜘蛛的UA爲例,它會使用「Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/s...)」這樣的UA,因此咱們能夠判斷 UA 中含有「Baiduspider」字樣則意味着是百度蜘蛛來訪問了。

如何在百度蜘蛛來訪問時返回靜態頁

先把靜態頁放置到網站的 /assets/static/ 下,配置 nginx 的配置文件 nginx.conf:

location / {
            root   C:\projects\bzbclub-dist;
            index  index.html index.htm;
           
            if ( $http_user_agent ~*  "Baiduspider"){
                rewrite ^/index.html$ /assets/static/index.html last;
            }
        }

保存配置文件後要使用 nginx -s reload 從新加載網站,而後使用 curl 命令的「-A」參數模擬百度蜘蛛訪問首頁:

curl -A "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)" http://localhost:17082 > z:\temp\bzbclub.html

打開 z:\temp\bzbclub.html 確認是否已經返回了靜態頁的內容。

如何使用 phantomjs 生成靜態頁

生成靜態頁的腳本很簡單:

var fs = require('fs');
var page = require('webpage').create();
phantom.outputEncoding = "utf-8";//指定編碼方式
page.open("http://localhost:17082", function (status) {
    if (status === "success") {
        fs.write('z:\\temp\\index.html', page.content, 'w');
    } else {
        console.log("網頁加載失敗");
    }
    phantom.exit(0);//退出系統
});

將此腳本保存爲「phantom-static-page.js」,在命令行執行此腳本:

phantomjs phantom-static-page.js

附錄

[1] curl

在Windows下也可使用 curl
若是遇到 「 Failed writing body」 錯誤,可使用

curl http://localhost:17082 > z:\temp\test.txt

以後便可看到生成的「z:\temp\index.html」靜態頁文件。

這樣的命令將輸出寫入文本文件中,再打開文本文件查看內容便可。

[2] nginx 部署

若是你是首次使用 nginx,有幾個地方須要注意。

  • 默認 nginx 不開啓 gzip,須要修改配置文件開啓 gzip,方法是修改 nginx.conf 配置文件的 http 節:
http {
    gzip    on;
    gzip_comp_level  6;    # 壓縮比例,比例越大,壓縮時間越長。默認是1
    gzip_types    text/xml text/plain text/css application/javascript application/x-javascript application/rss+xml;     # 哪些文件能夠被壓縮
    gzip_disable    "MSIE [1-6]\.";     # IE6無效
}
  • 解決刷新二級頁面時報 404 錯誤的問題

若是你不是使用hash路由(即路徑中不含「#」),當你使用「在新標籤頁打開連接」的方式打開指向新路由的連接,或者在二級頁面上刷新頁面時,都會報404錯誤。這是由於路由指向的頁面實際是不存在的,是 Angular 虛擬的,必須經由 index.html 中放置的根路由(<base href="/">)來渲染,因此須要在配置文件 nginx.conf 增長「tryfile」,把虛擬路徑重定向到 index.html:

server {
        listen       17082;
       
        location / {
            root   C:\projects\bzbclub-dist;
            index  index.html index.htm;
            try_files $uri $uri/ /index.html;
           
            if ( $http_user_agent ~*  "Baiduspider"){
                rewrite ^/index.html$ /assets/static/index.html last;
            }
        }
    }
相關文章
相關標籤/搜索