關於大型網站技術演進的思考(十五)--網站靜態化處理—前後端分離—中(7)
上篇裡我講到了一種前後端分離方案,這套方案放到服務端開發人員面前比放在web前端開發人員面前或許得到的掌聲會更多,我想很多資深前端工程師看到這樣的技術方案可能會有種說不出來的矛盾心情,當我的工作逐漸走向越來越專業化的前端開發後,我就時常被這套前後端分離方案所困惑,最近我終於明白了這個困惑的本源在哪裡了,那就是這套前後端分離方案其實是服務端驅動的前後端分離方案,它的實現手段又是從服務端的MVC架構體系演化而來,因此該方案最大的問題就是它並沒有從根本上改變web前端從屬於服務端的被動局面。那麼問題來了,有沒有以web前端為驅動的前後端分離方案呢,該方案能讓web前端的能力獲得更大的釋放了?答案是絕對有。本篇就要講講以web前端驅動的前後端分離方案。
首先要提的就是javascriptMVC,下面我摘抄的是維基百科裡對javascriptMVC的解釋,具體如下:
首先是簡介:
JavaScriptMVC 是一套開放原始碼的多樣化網際網路應用程式框架,以 jQuery 與 OpenAJAX 為基礎。JavaScriptMVC 利用 MVC 架構與工具擴充套件這些函式庫,以便開發與測試。由於 JavaScriptMVC 不需要任何伺服器端的配合,因此它可以和任何的網站服務介面與程式語言整合,如 ASP.NET、Java、Perl、PHP、Python 或 Ruby。
接下來是歷史:
JavaScriptMVC 的第一個版本是在2008年5月釋出。穩定版的 JavaScriptMVC 2.0 在2009年6月釋出,並以 jQuery 為基礎。主要開發目標為維持程式碼的簡短和專注在它獨特的功能上。3.0版本在2010年12月釋出。而從 JavaScriptMVC 中所獨立出來的 MVC 架構“CanJS”則在2012年4月釋出。
從維基百科裡的解釋我們會發現如下啟示,它們分別如下:
啟示一:javascriptMVC是一個應用框架的名字,這和jQuery的命名是一樣的,所以這裡我要宣告一下,本系列裡的javascriptMVC不是指代這個框架,而是指代的是使用javascript語言實現出的一類的web前端的MVC框架,本系列後面的javascriptMVC和前端MVC的含義是一致的。
啟示二:從javascriptMVC歷史裡我們可以看到第一版的javascriptMVC產生於2008年,這個歷史要遠早於nodejs出現的時間,這說明了前端的MVC並不是因為nodejs的出現而產生的,應該是nodejs推動了前端的MVC框架的應用和普及。
啟示三:維基百科裡有一段解釋:
由於 JavaScriptMVC 不需要任何伺服器端的配合,因此它可以和任何的網站服務介面與程式語言整合,如 ASP.NET、Java、Perl、PHP、Python 或 Ruby。
這段話說明了前端MVC的一個很重要的特點就是前端MVC可以擺脫服務端語言的束縛做到真正的獨立,同時前端MVC又可以和任何服務端語言進行整合,大家可以試想下如果我們開發的web應用前端達到了前端MVC的程度,那麼公司在招聘web前端工程師的時候就不在會問你“你會java嗎?”或者“你會php嗎?”假如這個前端工程師所會的服務端語言能力和公司不匹配,面試官也不會再猶豫和搖頭了。
啟示三同時還隱含了一個問題,為什麼好的前端MVC框架可以做到和任何服務端語言配合呢?這個解決手段之一我在前文中的第一階段前後端分離方案裡就提到了,那就是解決報文格式的統一和互動介面的統一的技術手段,只有這樣前端MVC和服務端的靈活對接就不會再是問題了。但是僅僅這個手段還是遠遠不夠的,我們要達到這個需求還需要解決一個問題,這個問題就是要把服務端MVC霸佔web前端的工作也要搶回來。那如何搶呢?
上篇文章裡我分析過服務端MVC的檢視層的問題,服務端MVC的檢視層技術例如java裡的jsp技術,這個技術是將html和java程式碼整合的技術,java的web容器把jsp解析完畢後最終生成為html檔案傳送給瀏覽器,瀏覽器在解析這個html將最終效果展示給使用者。那麼我們要搶回服務端霸佔的web前端的工作我們就得分析下這些動態頁面技術到底做了哪些事情特別是侵佔web前端的事情。
這裡首先我們要談談服務端在動態頁面裡的作用,其實服務端為動態頁面作用很單一就是提供了網站需要展示的資料而已,服務端是不會創造一個新頁面的。服務端提供的資料的型別也是很統一,要不就是服務端語言提供的基本資料型別例如:字元、數字、日期等等,要不就是複雜點的資料型別例如陣列、列表、鍵值對等等,不過歸屬服務端的動態頁面還需要服務端語言幫助做一件事情,那就是把服務端提供的資料整合到頁面裡,最終產生一個瀏覽器可以解析的html網頁,這個操作無非就是使用服務端語言可以構造檔案的能力構建一個符合要求的html檔案而已。不過一個頁面裡需要動態變化的往往只是其中一部分,所以做服務端的動態頁面開發時候我們可以直接寫html程式碼,這些html程式碼就等於在構造頁面展示的模板而已,而模板的空白處則是使用服務端資料填充,因此在java的web開發裡檢視層技術延生出了velocity,freemark這樣的技術,我們將其稱之為模板語言的由來。
由此可見,服務端MVC框架裡搶奪的web前端的工作就是搶佔了構建html模板的工作,那麼我們在設計web前端的MVC框架時候對於和服務端對接這塊只需要讓服務端保持提供資料的特性即可。從這些論述裡我們發現了,其實前端MVC框架要解決的核心問題應該有這兩個,它們分別是:
核心問題一:讓模板技術交由瀏覽器來做,讓服務端只提供單純的資料服務。
核心問題二:模板技術交由瀏覽器來承擔,那麼頁面的動態性體現也就是根據不同的服務端資料進行頁面部分重新整理來完成的。
而這兩個核心問題解決辦法那就是使用ajax技術,ajax技術天生就符合解決這些問題的技術手段了。
要讓web前端承擔模板技術,就得使用javascript的模板技術,時下javascript的模板技術可謂是百花齊放,百家爭鳴,很多朋友曾為這些技術稱奇,其實探求它的本源無非就是用javascript為基礎實現了個jsp,velocity而已,如果有朋友還沒接觸過javascript模板技術,可以在百度裡搜尋下【javascript模板引擎】,本文這裡就不展開談論了。
前端的MVC討論到這裡又出現了一個新的疑問,我上面講到解決前端MVC兩大核心問題的手段是ajax技術,ajax是非同步請求,那麼這是不是就是說讓網站全部使用非同步請求我們就可以實現前端MVC,並且解決網站所有的問題呢?
這個問題的回答當然是不可能的。一個網站是永遠沒法擺脫與非同步請求相對的同步請求,就算有個網站把非同步做到了極致,但是它也無法擺脫使用者第一次訪問要在瀏覽器位址列填寫網站入口頁面url地址的同步請求問題,網站把非同步操作做到極致也無非就是把網站做成了一個純粹的單頁面形式而已。
純粹單頁面的網站很多人一聽到就覺得好牛逼啊,很前衛,很厲害,對前端有所瞭解的人還會想到單頁面也就意味要運用更多的javascript程式設計和DOM程式設計,前端程式碼難度也會大大增強,好的單頁面應用如果這個應用還包含複雜的業務邏輯,那麼單頁面前端開發裡很可能還會使用到如今很火爆的javascript模組技術例如requirejs或者seajs技術,單頁面聽起來實在太完美了,但是我們冷靜下來思考下,單頁面真的完美嗎?下面我要為單頁面潑潑涼水了,具體如下:
潑涼水一:單頁面其實指的是網站只有一個入口,但是並不代表使用者看到的網頁就是一個樣子的,單頁面裡也會有很多頁面切換,但是不管頁面裡的模樣如何變化,瀏覽器位址列的地址都不會變化,能做到這點就得歸功ajax的超強能力了,單頁面不同模樣的展示都是在javascript程式碼裡實現的,那麼問題來了,單頁面對於搜尋引擎的網路爬蟲就非常不友好了,因為網路爬蟲是根據url抓取頁面,抓取完畢後會忽略javascript程式碼,那麼單頁面的設計方案就會導致SEO優化只能作用於首頁,而網站其他頁面將無非有效的被SEO技術進行優化。
潑涼水二:一個網站做成單頁面以後那麼網站不同的展示都在一個url下面,但是如果有些使用者只是對網站的某一部分功能很感興趣,而這部分功能又不是被單頁面的唯一同步請求所展示的首頁裡的內容,那麼結果就是這些使用者每次登陸網站時候都要手動操作一下才能進入自己想要的功能頁面裡,假如首頁進入功能頁面的操作步驟比較繁瑣,那麼這個必然會導致網站使用者體驗的下降。
那麼上面的問題該如何來破呢?
這裡我首先來講講第二個問題的解決方案,第二個潑涼水的問題的核心就是要記錄單頁面的狀態問題,這個狀態可以幫助首頁能快速切換到具體的功能頁面,要讓客戶端網頁有狀態最常用的手段就是cookie了,如果瀏覽器支援html5,那麼儲存狀態的手段就更多,能力也更強了。但是這種手段是和客戶端緊耦合的,那麼如果碰到這種情況,該手段就會出現問題了,例如如果有個人發現單頁面網站裡一個很有趣的功能,這時候他正好和朋友QQ聊天,他告訴了他的朋友,他的朋友也該興趣,讓他把連結發過來,那麼這個朋友就不得不在從首頁在重複操作一遍,由此可見,cookie的手段並沒有全面解決這個問題,那我們還有其他手段嘛?
答案是還真有,那就是使用html的錨連結,錨連結的形式如下所示:
http://www.baidu.com/#sharpxiajun
下面是我摘抄下百度百科對錨連結的解釋:
錨連結實際上就是連結文字,又叫錨文字。可以理解為:帶有文字的超連結,就叫錨連結。錨文字可以作為文字連結所在的頁面的內容的評估。 一般的來講,網站頁面中增加的錨連結都和頁面本身的內容有一定的必然聯絡。網站建設的行業網站上會增加一些同行網站的連結或者一些做網站建設的知名設計網站的連結; 另一方面,錨文字能作為對所指向頁面的評估。錨文字能精確的描述所指向頁面的內容,個人網站上增加Google的連結,錨文字為 “搜尋引擎”。這樣通過錨文字本身就能知道,Google是搜尋引擎。
那麼在單頁面裡的功能切換時候我們改變一下url上的錨文字,反過來說使用錨文字做路由器,讓其可以路由到對應的功能頁面那麼上面的問題不就可以解決了。關於錨連結我這裡要補充一些知識,首先錨連結的形式是url#文字,錨的起始標記是#號,這個#號的內容其實是屬於瀏覽器端的,也就是說#包括#號後面的內容是不會被髮送到服務端的,那麼我們想改變錨連結只能在客戶端進行,但是傳統的錨連結的變化是很難被javascript語言監控到的,直到html5的出現才從根本上解決了這個問題,html5提供了hashchange事件,該事件可以監控錨連結的變化,因為javascript語言可以監控錨連結的變化,那麼使用錨連結路由功能頁面就成為了可能,那麼低版本的瀏覽器該怎麼辦了?這個主要是ie的問題了,其實ie8包括ie8都支援hashchange事件,再低就不行了,不過jQuery有個外掛可以讓低版本的ie支援hashchange事件,有興趣的童鞋可以百度下啊。
看來潑涼水二問題是有解的,那麼潑涼水一怎麼解決了?我的回答是基本無解,這個問題的關鍵在網路爬蟲這邊,如果我們被動解決這個問題,那隻能是拋棄javascript了,這個玩笑就開大了,所以我們只好祈求各大搜尋引擎能不能智慧化再厲害點了。這裡加個題外話,我最近幾天突然意識到一個問題,那就是講到web前端技術我一定要加強對SEO的思考,因為絕大多數網站都會把搜素引擎當做入口的生命線,這是一個很難迴避的問題,不管我們網站做的如何優秀,假如使用者很難找到它,那一切都將會是百搭,而在前端設計裡要加入SEO的思考,這必然會導致整個架構的重大變化。這個問題我會在以網站靜態化角度審視前後端分離方案時候重點講下。
前端MVC討論到這裡我們會發現我們的談論裡缺了一環那就是MVC的M層模型層,web前端要侵入到模型層了,這不就等於web前端要造反了,它不僅僅想改變從屬服務端的悲慘命運,還要搶奪服務端的部分功能,讓服務端成為瀏覽器對應的儲存系統,這不是無異於虎口奪食,在時下服務端如此強勢的大環境下,這種想法簡直就是活得不耐煩了,哈哈,當然這是戲言了,做技術做工程還是要講求個合理性和邏輯性的,技術和工程都是實在的東西很講道理的,只要道理站得住腳怎麼個做法都是其次,回到問題本身,我個人覺得在PC端討論web前端做模型層其實往往利大於弊,就安全而言,模型層意味有大量業務邏輯推移到web前端,那麼安全的保障難度會加大,就技術難度而言,web前端做模型層會讓javascript程式設計巨複雜,所以要做這個抉擇時候一定要結合業務做仔細的權衡,其實我現在接觸的一些說包含模型層能力的前端框架在實際運用裡模型層的功能還是使用太少,不過這個問題如果放到移動端,或者是PC和移動端融合可能就會有些不同,這個問題我將在本系列的終篇裡再談談,這裡也不累述了。
說到這裡需要總結下了,前端的MVC不應該等於單頁面開發,前端MVC也不是把ajajx用到極致,根據實際業務場景,我們需要適當的把同步請求和非同步請求結合起來。如果前端MVC裡包含了更多同步請求,那麼對於MVC裡的C層即控制層就會有更高的要求。前後端分離主題還有個下篇,下篇裡我還會提到一種前後端分離方案那就是nodejs的運用,而nodejs的運用就是和控制層有密切的關係,上篇裡我提到nodejs是前後端分離方案的催化劑,其實我個人認為nodejs參入的前後端分離方案才是更加完美些的前後端分離方案,這個完美的評價原因之一就是從前端承擔控制層作用角度思考的,所以前端控制層這個內容我將放在下篇討論。
好了,本篇寫完了,從本篇我們可以看到前端MVC的歷史很早,它的出現早於nodejs,這就說明前端MVC其實並不是什麼新技術,只不過是現在才被大家重視起來,完善它的人也越來越多。從本篇我們還發現前端MVC其實並不完美,問題很多,最致命的就是對網路爬蟲的不友好,所以我們需要考慮到SEO技術參入其中的前後端分離方案。
相關文件:
關於大型網站技術演進的思考(一)--儲存的瓶頸(1)
關於大型網站技術演進的思考(二)--儲存的瓶頸(2)
關於大型網站技術演進的思考(三)--儲存的瓶頸(3)
關於大型網站技術演進的思考(四)--儲存的瓶頸(4)
關於大型網站技術演進的思考(五)--儲存的瓶頸(5)
關於大型網站技術演進的思考(六)--儲存的瓶頸(6)
關於大型網站技術演進的思考(七)--儲存的瓶頸(7)
關於大型網站技術演進的思考(八)--儲存的瓶頸終篇(8)
關於大型網站技術演進的思考(九)--網站靜態化處理--總述(1)
關於大型網站技術演進的思考(十)--網站靜態化處理—動靜整合方案(2)
關於大型網站技術演進的思考(十一)--網站靜態化處理—動靜分離策略(3)
關於大型網站技術演進的思考(十二)--網站靜態化處理—快取(4)
關於大型網站技術演進的思考(十三)--網站靜態化處理—CSI(5)
關於大型網站技術演進的思考(十四)--網站靜態化處理—前後端分離—上(6)
關於大型網站技術演進的思考(十五)--網站靜態化處理—前後端分離—中(7)
關於大型網站技術演進的思考(十六)--網站靜態化處理—前後端分離—下(8)
關於大型網站技術演進的思考(十七)--網站靜態化處理—滿足靜態化的前後端分離(9)
關於大型網站技術演進的思考(十八)--網站靜態化處理—反向代理(10)
關於大型網站技術演進的思考(十九)--網站靜態化處理—web前端優化—上(11)
關於大型網站技術演進的思考(二十)--網站靜態化處理—web前端優化—中(12)
關於大型網站技術演進的思考(二十一)--網站靜態化處理—web前端優化—下【終篇】(13)
相關文章
- 關於大型網站技術演進的思考(十六)--網站靜態化處理—前後端分離—下(8)網站後端
- 關於大型網站技術演進的思考(十四)--網站靜態化處理—前後端分離—上(6)網站後端
- 關於大型網站技術演進的思考(十七):網站靜態化處理—滿足靜態化的前後端分離(9)網站後端
- 關於大型網站技術演進的思考(十七)--網站靜態化處理—滿足靜態化的前後端分離(9)網站後端
- 關於大型網站技術演進的思考(十一)--網站靜態化處理—動靜分離策略(3)網站
- 關於大型網站技術演進的思考(十三)--網站靜態化處理—CSI(5)網站
- 關於大型網站技術演進的思考(十八):網站靜態化處理—反向代理(10)網站
- 關於大型網站技術演進的思考(十二)--網站靜態化處理—快取(4)網站快取
- 關於大型網站技術演進的思考(十八)--網站靜態化處理—反向代理(10)網站
- 關於大型網站技術演進的思考(九)--網站靜態化處理--總述(1)網站
- 關於大型網站技術演進的思考(十)--網站靜態化處理—動靜整合方案(2)網站
- 關於大型網站技術演進的思考(二十):網站靜態化處理—web前端優化—中(12)網站Web前端優化
- 關於大型網站技術演進的思考(二十)--網站靜態化處理—web前端優化—中(12)網站Web前端優化
- 關於大型網站技術演進的思考(十九):網站靜態化處理—Web前端優化—上(11)網站Web前端優化
- 關於大型網站技術演進的思考(十九)--網站靜態化處理—web前端優化—上(11)網站Web前端優化
- 關於大型網站技術演進的思考(二十一):網站靜態化處理—Web前端優化(下)(13)網站Web前端優化
- 關於大型網站技術演進的思考(二十一)--網站靜態化處理—web前端優化—下【終篇】(13)網站Web前端優化
- 關於大型網站技術演進的思考(七):儲存的瓶頸(7)網站
- 關於大型網站技術演進的思考(七)--儲存的瓶頸(7)網站
- 關於大型網站技術演進的思考(二)--儲存的瓶頸(2)網站
- 關於大型網站技術演進的思考(一)--儲存的瓶頸(1)網站
- 關於大型網站技術演進的思考(三):儲存的瓶頸(3)網站
- 關於大型網站技術演進的思考(一)—儲存的瓶頸(1)網站
- 關於大型網站技術演進的思考(六)--儲存的瓶頸(6)網站
- 關於大型網站技術演進的思考(五)--儲存的瓶頸(5)網站
- 關於大型網站技術演進的思考(四)--儲存的瓶頸(4)網站
- 關於大型網站技術演進的思考(三)--儲存的瓶頸(3)網站
- 關於大型網站技術演進的思考(二):儲存的瓶頸(2)網站
- 關於大型網站技術演進的思考(一):儲存的瓶頸(1)網站
- 關於大型網站技術演進的思考(八):儲存的瓶頸(8)網站
- 前後端,靜態網站和動態網站, 的理解後端網站
- 大型網站技術架構的演進網站架構
- 關於大型網站技術演進的思考(八)--儲存的瓶頸終篇(8)網站
- 大型網站架構改進歷程(9):網站靜態化處理–總述(1)網站架構
- 大型網站的技術架構演進過程網站架構
- 關注網際網路後端技術-MySQL在大型網站的應用架構演變後端MySql網站應用架構
- 大型網站技術架構(二)--大型網站架構演化網站架構
- 大型網站技術架構(一)--大型網站架構演化網站架構