單頁應用(Single Page Application)愈來愈受web開發者歡迎,單頁應用的體驗能夠模擬原生應用,一次開發,多端兼容。單頁應用並非一個全新發明的技術,而是隨着互聯網的發展,知足用戶體驗的一種綜合技術。前端
一直以來,搜索引擎優化(SEO)是開發者容易忽略的部分。SEO是針對搜索(Google、百度、雅虎搜索等)在技術細節上的優化,例如語義、搜索關鍵詞與內容相關性、收錄量、搜索排名等。SEO也是同行、市場競爭經常使用的的營銷手段。Google、百度的搜索結果是重要的用戶入口,騰訊雲(www.qcloud.com)有30%左右的流量來自搜索引擎。所以SEO在品牌、營銷、用戶量的緯度是很是重要的基礎能力。node
那麼單頁應用與傳統直出頁面在SEO方面有哪些不一樣之處呢?web
單頁應用實際是把視圖(View)渲染從Server交給瀏覽器,Server只提供JSON格式數據,視圖和內容都是經過本地JavaScript來組織和渲染。而搜索搜索引擎抓取的內容,須要有完整的HTML和內容,單頁應用架構的站點,並不能很好的支持搜索。後端
若是站點在用戶體驗和搜索友好權衡時,若是咱們作到更好的體驗,也作到友好的搜索支持,既是一舉兩得。api
單頁應用只有一個頁面,視圖的變化一般是經過路由(route)來驅動,首先,咱們先來談一談單頁應用的URL中的#號,不少採用單元結構網站的URL都出現了這個符號。瀏覽器
#
號在瀏覽器的URL中是一個錨點,在當前頁改變#
號的參數,頁面會跳轉到錨點所在的位置,經過JavaScript咱們能夠獲取到#
號後的參數:架構
location.hash // 獲取URL hash location.hash = "#list" //改變URL hash
改變#
號後的參數,頁面並不會重載,因而大多數的單頁架構網站,都在URL中採用#
號來做爲當前視圖的URL地址,例如:優化
example.com/#index //首頁視圖 example.com/#list //列表頁視圖 example.com/#list/1 //id爲1的列表信息的視圖
Backbone.js就是經過改變#
號參數來組織視圖,這裏有一個demo能夠很直觀的體驗URL的變化。網站
看過這個demo,你或許會發現很熟悉的符號#!
,Twitter曾在URL使用這個標識。這個標識是Google提出(AJAX 抓取:網站站長和開發人員指南1):搜索引擎
由於複雜的單頁架構頁面,對Google來講抓取比較困難,因而給開發者制定一個規範:
#!
符號,例如example.com/#!/detail/1
,因而Google開始抓取example.com/?_escaped_fragment_=/detail/1
;_escaped_fragment_
這個參數是Google指定的命名,若是開發者但願把網站內容提交給Google,就必須經過這個參數生成靜態頁面。
根據上面的demo,我簡單示例一下Google要抓取的頁面的樣子:
http://119.28.4.22/?escapedfragment_=/detail/1
如此以來,就須要Server經過生成靜態的內容以便Google抓取。
如下將簡單介紹,單頁架構,爬蟲訪問根目錄時若是配置Server端的路由。
當Google訪問119.28.4.22/#!/detail/1
時,會自動轉化成http://119.28.4.22/?_escaped_fragment_=/detail/1
,以Nginx爲例:
if ($args ~ _escaped_fragment_) { rewrite ^ /api; }
/api
爲後臺服務的接口,已nodejs爲例,代理設置以下:
upstream nodejs { server 127.0.0.1:3000; } location /api { proxy_set_header X-Request-URI $request_uri; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_set_header Port $server_port; proxy_pass http://nodejs; proxy_redirect off; }
如此,咱們便將Google的訪問重寫到/api
這個接口,而後在Server的/api
處理請求把靜態內容輸出便可。
Gogole的這個規範,必須有sitemap支持,由於有可能單頁架構的站點,索引頁面也是JavaScript渲染的。提交sitemap時,不用關注_escaped_fragment_
這個參數名,只提交帶哈希符號的URL便可,例如:
http://119.28.4.22/#!/detail/1 weekly 0.5
技術潮流的步伐很快,單頁應用,URL哈希處理也沒渲染的方式實際上已經流行了好久,在國外不少用戶數據較好的狀況下,開發者會選擇HTML5 History API的pushstate特性開發,在URL中拋棄#!
。可是IE六、7等低端瀏覽器用戶狀況較多的網站,#
可以很好的兼容。關於採用HTML5 History API來架構單頁應用的方案,也歡迎討論。
參考1: https://support.google.com/webmasters/answer/174992?hl=zh-Hans