將Web視為應用平臺的概念,正前所未有的流行著。但用來創建這些所謂“Web應用”的工具仍存在許多經常被我們忽視或誤解的陷阱。單頁面Web應用框架已得到極大關注,我們可以借助這些框架創建一些復雜的高性能應用,與傳統網站相比,這些應用更可靠且交互更加豐富。但所有的這些益處,以及隨之而來的思維模式和開發方式的轉變,是以犧牲瀏覽器的基本功能為代價的,Web開發者們有時卻將其視為理所當然。
JavaScript可能非常脆弱
隨著各家廠商不斷地炒作這股熱浪,我們可能誤以為當用戶的瀏覽器不能執行JavaScript時,并不需要為他們提供回退方案。用戶的瀏覽器不能執行JavaScript一定事出有因,他們手動選擇禁用JavaScript只是眾多原因之一。維護英國政府網站的團隊——政府數字服務(GDS)發現:每500位訪問GOV.UK的用戶中,有5人沒有請求JavaScript,其中只有1人主動禁用了JavaScript,其他4人沒有請求可能因為以下幾個原因:企業代理服務器限制過高;高延遲導致JavaScript請求超時;甚或是一個沒有被注意到的語法錯誤。
此外,CSS和HTML都可以優雅降級,而JavaScript卻做不到。這意味著,如果開發者使用一個單一的ES6語法特性,甚或是調用一個沒有經過驗證的標準庫函數,他們的JavaScript就很有可能在執行過程中終斷或者根本就不執行。如果你使用JavaScript來增強網站,上面提到的這些問題尚且可以忍受,畢訪問者仍然可以訪問鏈接,可以提交表單,可以使用Web能提供的原始功能;但如果JavaScript是網站必不可少的一部分時,無論是誰使用稍微過時的瀏覽器都可能獲得一個空白頁面,自然也沒有人來解釋頁面為什么會變成空白。
語義結構仍然非常重要
自1993年Tim Berners-Lee設計HTML以來,HTML為相互關聯的文檔網定義了一個通用結構,也就是我們熟知的Web。滲透在這個通用結構中的語義含義為Web頁面中包含的信息提供了計算機可以處理的上下文。從實際的意義來說,這些額外的信息增強了用戶使用Web瀏覽器時的體驗。舉個例子,Web瀏覽器可以實現一個向用戶的日歷中添加使用time元素定義的事件的方法;屏幕閱讀器可以用不同的方式通讀一個列表或一段文字,對于人類來說,文檔中的列表與段落看起來明顯不一樣,HTML提供的通用框架讓計算機也能夠清晰分辨列表與段落。
HTML暗含的語義含義使Web與諸如Cocoa、WPF以及Qt這樣的原生應用環境有著不同的發展方向。結構化的信息對Web來說非常重要,因為我們需要通過多種方式訪問Web信息。而當我創建一個iPhone應用時,我可以穩妥地假設每一個人都會用相同的方式去使用它。我的App總會以相同的方式呈現信息,并且我能夠完全掌控信息在應用里的終呈現。即使有些人通過VoiceOver(Apple為視障人群提供的輔助技術)與我的App進行交互,他們仍然可以與視力正常的用戶一樣:通過點擊屏幕進行操作。的不同是他們需要聽文字而不是去閱讀。
而這種方法在Web上卻行不通。人們除了通過Web瀏覽器訪問網站,還會通過類似Pocket、Instapaper這樣的應用來消費網站內容,這些應用嘗試使用Web頁面的結構化信息來提取網站的相關內容。智能手表上的瀏覽器可能直接忽略你的布局,然后通過更適合一英寸屏幕的方式展現你的信息。未來的設備也許能夠直接將網站提供的信息轉化為人類大腦中的思維,這誰又會知道呢?回過頭看,VoiceOver的工作原理是按順序朗讀用戶指尖下排列的文字,然而Web屏幕閱讀器則通讀全部文檔,忽略布局,并且通過HTML標簽的標準化語義來推斷文檔含義。舉個例子,近推出的main元素(譯者注:參考https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/main)用來定義文檔的主體部分,Web屏幕閱讀器可以讀取并識別這樣的標簽。對于一個視覺正常的用戶來說,通過Google Chrome訪問你的網站時,無論你使用<main>或者是<div id=”main”>基本沒有區別。但對于使用其它Web客戶端的人來說,例如使用屏幕閱讀器或Instapaper,main元素隱含的含義可以讓軟件更好地幫助他們瀏覽文檔。
所以,開發一款Web應用不像為原生平臺開發那么簡單。在五個主流瀏覽器中確保應用能按照我們的需求正常工作并及時發布,對于Web平臺來說還遠遠不夠,我們需要在屏幕閱讀器中測試我們的工作成果,需要重審我們的標記來確保應用能提供盡可能多的語義元數據——不僅需要協調已有的Web客戶端,也要為將來可能出現的一切設備做準備。
單頁面Web應用框架
當使用類似Angular和Ember這樣的“單頁面Web應用”框架時,流行的做法是把網站當成原生應用一樣對待,如此一來,開發者們就很少會考慮到Web平臺與眾不同的一面。他們為用戶作出的假設很容易徹底毀掉不滿足假設的用戶的真實體驗。這種思維模式會導致什么后果?我們來看一個示例,并認真思考我近在Patreon網站上發現的一個登錄按鈕(后來有改動):
[html] view plaincopy在CODE上查看代碼片派生到我的代碼片
<span class="patreon-button sub-section navigation-active" data-ng-click="triggerChangeWindow(navigation.login_url)">Log In</span>
Patreon那個相當標準的登錄按鈕表現得像一個鏈接,這里不需要特殊的JavaScript。
這個鏈接在我的Safari中可以正常運行,但是在除主流瀏覽器外的其它環境中,這個按鈕完全不能使用。假設我們有一個稱為WatchBrowse的智能手表瀏覽器,很可能它需要為用戶顯示一系列的列表鏈接來實現站內導航,因為這個特殊的智能手表沒有光標用來與頁面進行交互。HTML定義了一個在Web頁面上創建鏈接的標準方式(a元素),WatchBrowse理論上可以在頁面上列出每一個a標簽和它的href屬性以及內容,除非出現一個類似Patreon的網站,并且該網站決定回避Web標準并且重新實現瀏覽器的基本功能。
如果Patreon使用一個a標簽而不是span標簽,WatchBrowse大概可以找到鏈接并將它顯示在列表中,你可以為鏈接模擬一個點擊事件,當用戶選中鏈接時進行跳轉。但是如果讓瀏覽器提前知曉鏈接將導向何處是否會更好?一個瀏覽器擴展可能通過頁面上標簽的href屬性來查找鏈接,如果你想快速找到某人Twitter賬戶的鏈接,那么提供一個可以溯源的href屬性就很實用。當鏈接的href屬性不再是靜態值,而是取決于任意的JavaScript點擊句柄,這些有用的功能就無法實現了。
Patreon的網站是基于Angular建立的,Angular本身沒有錯,將HTML當做視圖層并用這些框架去實現大概是導致Patreon糟糕決定的主要原因。
如果我們按照框架開發者在他們文檔中推薦的方法創建相同的鏈接會怎樣?一個更標準創建鏈接的方式看起來可能是這樣的:
[html] view plaincopy在CODE上查看代碼片派生到我的代碼片
<a ng-href="/login">Log In</a>
當通過客戶端JavaScript渲染到DOM中時,上面的代碼被轉換成這樣:
[html] view plaincopy在CODE上查看代碼片派生到我的代碼片
<a ng-href="/login" class="ng-binding" href="/login">Log In</a>
Ember以相同的方式處理這個問題。一個鏈接在Ember模板中被這樣定義:
[js] view plaincopy在CODE上查看代碼片派生到我的代碼片
{{#link-to sessions.new}}Log In{{/link-to}}
當它被渲染到DOM中時,它變成這樣:
[html] view plaincopy在CODE上查看代碼片派生到我的代碼片
<a id="ember-563" class="ember-view" href="/sessions/new">Log In</a>
Ember和Angular之后會攔截鏈接的點擊事件,這樣就可以不通過重載頁面來渲染新的內容。至關重要的是,如果點擊事件永遠不被觸發并且瀏覽器已經加載了href的值,那么對于用戶來說點擊鏈接只會帶來一次額外的頁面重載,看起來并不會有什么不同,因為Ember和Angular默認情況下不會嘗試依照URL定義他們自己的路由來重新制造輪子。
然而,在當前的形式下,Ember和Angular仍然需要加載JavaScript來渲染他們的模板并且在時間創建那些連接。每500個訪問使用Angular或Ember構建的網站中4人將會遭遇一次徹底白屏。
是否有一個解決方案?
如果在服務端渲染動態Web頁面的內容,那么渲染功能的代碼只需支持在服務器端運行。但Web頁面放在客戶端進行渲染時,相關代碼需要支持每一臺可能訪問網站的客戶端。開發者現在正逐步拋棄服務端渲染的做法,因為他們不能提供客戶端渲染所帶來的富應用體驗。但是我認為在客戶端應用的新世界中,服務端渲染尚有一席之地。
目前,開發者使用單頁面Web應用框架需要針對加載JavaScript作出一個權衡。但在我看來,這些正是框架應該去解決的問題。作為Web開發者,我們有幸使用有史以來通用的編程語言之一為Web編寫應用代碼。如果框架開發者能夠夜以繼日(不可否認任務非常艱辛)地使應用像在瀏覽器中一樣地運行在Node中,服務器就可以完成初始頁面渲染的任務,隨后所有的任務由瀏覽器負責處理。當然,如果服務器可以將鏈接渲染成a標簽的形式,就像Ember目前在客戶端上實現的那樣,那么就可以允許沒有收到JavaScript的用戶(無論出于什么樣的原因)正常瀏覽網站。同樣也可以通過在服務器(而不是在客戶端)上運行所有的驗證和子任務邏輯,使表單正常工作。如果框架維護者一開始就朝著這個方向努力,那么每一個使用該框架的開發者都可以立即將一個只能工作在新Web瀏覽器中的應用轉換為一種漸進增強的體驗,這樣做幾乎可以兼容任何Web客戶端——過去的、現在的、以及未來的。
漸進增強對于Web開發者來說早已是重要的一環,它使我們意識到對于Web體驗來說內容是至關重要的一部分,任何針對用戶體驗的額外改進不應當破壞任何一個客戶端訪問Web頁面所包含的內容。目前創建單頁面應用的方法傾向于放棄這條準則,然而漸進增強和單頁面應用從本質上來講其實可以相互兼容。
事實上,這個領域已經有了不小的進步,例如,一個Ember內部的團隊正在通過實現服務端渲染來改進Ember與搜索引擎的兼容性。但是由單頁面Web應用引發的問題的解決方案并不能只依賴純技術角度:人們看待Web的方式已成為一個日益嚴重的問題。將Web視為另一個應用平臺的做法已司空見慣,但是Web所能做的比這多得多。無論訪問者通過2000美元的iMac還是50美元的安卓平板,甚至在我們無法想象的未來,花費5美元就可以購買的Web客戶端來訪問,Web始終是一個通用信息平臺。事實上,不犧牲小部分用戶的體驗對我們來說非常重要,如此一來我們可以在這個過程中稍微改進一下其余正在破壞Web普適性的體驗。
作者:Ross Penman是一位來自蘇格蘭的web開發者和狂熱的技術專家。2014年度新型人才網絡獎決賽入圍選手。Ross經常慶祝他的工作來促進科技領域的年輕人。他的Twitter內容與web開發和口袋怪獸訓練有關。(譯者:劉振濤,審校:陳秋歌)
原文鏈接:http://alistapart.com/article/let-links-be-links
本站文章版權歸原作者及原出處所有 。內容為作者個人觀點, 并不代表本站贊同其觀點和對其真實性負責,本站只提供參考并不構成任何投資及應用建議。本站是一個個人學習交流的平臺,網站上部分文章為轉載,并不用于任何商業目的,我們已經盡可能的對作者和來源進行了通告,但是能力有限或疏忽,造成漏登,請及時聯系我們,我們將根據著作權人的要求,立即更正或者刪除有關內容。本站擁有對此聲明的最終解釋權。