過(guò)去,前端開(kāi)發(fā)不像現(xiàn)在這么復(fù)雜,也不像現(xiàn)在這么令人興奮。畢竟每天都有新工具、新框架和新插件出現(xiàn),需要我們不斷學(xué)習(xí)。所幸,我們Grab的網(wǎng)頁(yè)設(shè)計(jì)團(tuán)隊(duì)一直都走在前端開(kāi)發(fā)的前沿,已經(jīng)在自家網(wǎng)頁(yè)應(yīng)用中融入了現(xiàn)代JavaScript系統(tǒng)。
但是,新員工和后端工程師可能還不太了解現(xiàn)代JavaScript系統(tǒng)。因此,在研發(fā)新功能或者修復(fù)漏洞時(shí),會(huì)有些吃力。這時(shí),公司就必須指導(dǎo)他們學(xué)習(xí)前端開(kāi)發(fā)知識(shí),幫助他們減少使用系統(tǒng)時(shí)遇到的問(wèn)題,以最快的速度把代碼介紹給用戶。
在這份學(xué)習(xí)指南中,我們以Grab目前使用的工具為基礎(chǔ),從前端開(kāi)發(fā)的每個(gè)方面出發(fā),向大家推薦了幾種值得學(xué)習(xí)的庫(kù)和框架。
使用須知
1.熟練掌握核心編程概念;
2.熟悉基本命令行操作和Git這類源代碼本版控制系統(tǒng);
3.擁有網(wǎng)頁(yè)開(kāi)發(fā)經(jīng)驗(yàn),利用Ruby on Rails和Django這類框架開(kāi)發(fā)過(guò)服務(wù)器端渲染的網(wǎng)頁(yè)應(yīng)用;
4.了解網(wǎng)頁(yè)運(yùn)作過(guò)程,熟悉HTTP這類網(wǎng)絡(luò)協(xié)議。
下面,我們就開(kāi)始詳細(xì)介紹:
NO.1 單頁(yè)面應(yīng)用程序(即Single-page App,以下簡(jiǎn)稱SPA)
現(xiàn)如今,網(wǎng)頁(yè)開(kāi)發(fā)人員不再把所開(kāi)發(fā)的產(chǎn)品叫做網(wǎng)站,而是叫做網(wǎng)頁(yè)應(yīng)用。雖然二者沒(méi)有嚴(yán)格區(qū)分,但后者的交互性和動(dòng)態(tài)性更強(qiáng),能讓用戶自行操作并且收到特定回應(yīng)。
以前,瀏覽器會(huì)收到來(lái)自服務(wù)器的HTML。當(dāng)用戶訪問(wèn)另一個(gè)URL地址時(shí),需要全頁(yè)刷新,服務(wù)器也會(huì)發(fā)送全新HTML。這就是所謂的服務(wù)器端渲染。
但是,在現(xiàn)代SPA中,客戶端渲染已經(jīng)取代了服務(wù)器端渲染。瀏覽器會(huì)先從服務(wù)器上加載出最初圖像,和包括框架、庫(kù)和應(yīng)用代碼在內(nèi)的腳本,以及整個(gè)應(yīng)用所需的樣式表。當(dāng)用戶訪問(wèn)其他頁(yè)面時(shí),頁(yè)面將不會(huì)進(jìn)行整體刷新,而是通過(guò)HTML5 History API對(duì)頁(yè)面地址進(jìn)行更新。以JSON形式呈現(xiàn)出來(lái)的新頁(yè)面所需的新數(shù)據(jù),將會(huì)通過(guò)向服務(wù)器發(fā)出的AJAX請(qǐng)求,由瀏覽器檢索進(jìn)行檢索。接著,SPA會(huì)通過(guò)原先在頁(yè)面中下載好的JavaScript,來(lái)對(duì)頁(yè)面數(shù)據(jù)進(jìn)行動(dòng)態(tài)更新。
SPA的優(yōu)點(diǎn)
1.應(yīng)用針對(duì)用戶操作給出的反應(yīng)更加靈敏,不會(huì)由于頁(yè)面整體刷新而出現(xiàn)閃退;
2.向服務(wù)器發(fā)送的HTTP請(qǐng)求減少,無(wú)需在每一頁(yè)進(jìn)行重復(fù)下載;
3.用戶和服務(wù)器劃分明確,無(wú)需修改服務(wù)器代碼就可以輕松為新用戶創(chuàng)建不同平臺(tái)。另外,只要不違背API規(guī)則,還可以分別對(duì)用戶和服務(wù)器的技術(shù)堆棧進(jìn)行修改。
SPA的缺點(diǎn)
1.最開(kāi)始的加載任務(wù)較重,包括框架和應(yīng)用代碼等;
2.需要對(duì)服務(wù)器進(jìn)行額外的配置操作,讓它將所有請(qǐng)求匯集到同一個(gè)進(jìn)入點(diǎn);
3.SPA依靠JavaScript來(lái)呈現(xiàn)內(nèi)容,但并不是所有搜索引擎都能夠在爬蟲(chóng)過(guò)程中執(zhí)行JavaScript。這一點(diǎn),無(wú)疑會(huì)對(duì)應(yīng)用的搜索引擎優(yōu)化帶來(lái)負(fù)面影響。
NO.2 新時(shí)代JavaScript
在深入研究開(kāi)發(fā)JavaScript網(wǎng)頁(yè)應(yīng)用的各個(gè)方面之前,首先要熟悉網(wǎng)絡(luò)語(yǔ)言,即JavaScript或者ECMAScript。JavaScript用途非常廣泛,可以用來(lái)開(kāi)發(fā)網(wǎng)頁(yè)服務(wù)器、本機(jī)移動(dòng)應(yīng)用和桌面應(yīng)用。
在2015年之前,最近的一次網(wǎng)絡(luò)語(yǔ)言更新,是2011年的ECMAScript 5.1。但是最近幾年,JavaScript突然取得了不少進(jìn)展。2015年,ECMAScript 2015(之前叫做ECMAScript 6)問(wèn)世。與此同時(shí),大量全新句法結(jié)構(gòu)的出現(xiàn),也使得代碼編寫更加簡(jiǎn)單。當(dāng)然了,也不是所有瀏覽器都全面引入了ES2015。
因此,正式開(kāi)始研發(fā)應(yīng)用之前,一定要熟悉掌握ES5和ES2015。目前,ES2015是相對(duì)較新的。不少開(kāi)源代碼和Node.js應(yīng)用還是用ES5寫的。所以說(shuō),如果你想在瀏覽器控制臺(tái)中進(jìn)行漏洞調(diào)試,那應(yīng)該還不能使用ES2015句法。不過(guò),下面我們即將要介紹的,不少現(xiàn)代庫(kù)中的文件編制和代碼示例,卻是用ES2015寫的。在Grab,我們選擇使用ES2015來(lái)享受JavaScript句法更新升級(jí)之后,所帶來(lái)的超高生產(chǎn)能力。
簡(jiǎn)單地說(shuō),在開(kāi)發(fā)應(yīng)用之前,你至少需要花上一兩天的時(shí)間,來(lái)回顧ES5、探索ES2015。當(dāng)然了,最好是能夠花上三四天的時(shí)間,來(lái)進(jìn)一步研究其中的句法。
NO.3 用戶界面——React
如果非要說(shuō)出近年來(lái)前端系統(tǒng)引入頻率最高的JavaScript 項(xiàng)目,那應(yīng)該是React。React是由Facebook工程師創(chuàng)建并且開(kāi)源的一個(gè)庫(kù)。開(kāi)發(fā)人員可以在這個(gè)庫(kù)中,為自家網(wǎng)頁(yè)界面編寫不同組件并且進(jìn)行結(jié)合。
React帶來(lái)了不少激進(jìn)創(chuàng)意,鼓勵(lì)開(kāi)發(fā)人員從各個(gè)角度重新思考,以便找到最佳方式。多年來(lái),網(wǎng)頁(yè)開(kāi)發(fā)人員一直認(rèn)為,HTML、JavaScript和CSS應(yīng)該分開(kāi)來(lái)寫。但React卻是恰恰相反,它鼓勵(lì)你在JavaScript當(dāng)中編寫HTML和CSS。雖然一開(kāi)始聽(tīng)上去,這是個(gè)瘋狂的想法,但嘗試過(guò)后就會(huì)有全新的發(fā)現(xiàn)。具體說(shuō)來(lái),React有如下幾個(gè)特征:
1.闡述性:說(shuō)白了,就是你只需要描述自己的想法,不需要落實(shí)。以往開(kāi)發(fā)人員都必須要通過(guò)一系列步驟,來(lái)操控DOM才可以讓應(yīng)用從一種狀態(tài)變?yōu)榱硪环N狀態(tài)。但在React當(dāng)中,你只需要簡(jiǎn)單地在各個(gè)組件中改變狀態(tài)就行。因?yàn)檎麄€(gè)呈現(xiàn)出來(lái)的結(jié)果,會(huì)根據(jù)各個(gè)組件的狀態(tài),自動(dòng)進(jìn)行更新和升級(jí)。
2.可維護(hù)性:通過(guò)改變各個(gè)組件來(lái)改變整體,能夠保證重復(fù)使用。我們發(fā)現(xiàn),定義一個(gè)組件的屬性和部類,能夠讓React代碼自行完成文件編制。這樣一來(lái),讀者就能夠清楚地知道使用該組件都需要些什么。
3.高效能性:我們只知道React使用的是虛擬DOM,卻不知道它為什么要使用虛擬DOM。現(xiàn)代JavaScript引擎的運(yùn)行速度非??欤瑹o(wú)論是從DOM中讀取內(nèi)容,還是向DOM寫內(nèi)容,都需要花費(fèi)很長(zhǎng)時(shí)間。但是,React卻提供了一種速度較快的虛擬表現(xiàn)形式。
4.易學(xué)習(xí)性:React學(xué)起來(lái)非常簡(jiǎn)單,需要掌握的API比較少,而且這些API基本都是保持不變的。作為最大的社區(qū)之一,React擁有眾多能夠靈活使用的工具和開(kāi)源用戶界面組件,而且可以直接在網(wǎng)上找到大量學(xué)習(xí)資源。
NO.4 狀態(tài)管理——Flux或Redux
隨著應(yīng)用中的內(nèi)容越來(lái)越多,你會(huì)發(fā)現(xiàn)應(yīng)用的結(jié)構(gòu)也變得越來(lái)越亂。有可能應(yīng)用中的各個(gè)組件需要分享和顯示共同數(shù)據(jù),但上面介紹的React卻無(wú)法找到一種合適的方式來(lái)解決這個(gè)問(wèn)題。畢竟,React只負(fù)責(zé)處理視圖層面的問(wèn)題,并不能處理其他層面的結(jié)構(gòu)問(wèn)題,比如說(shuō)在MVC模式當(dāng)中,除了視圖以外的模型和控制器層面的問(wèn)題。為此,Facebook就開(kāi)發(fā)了一套叫做Flux的應(yīng)用架構(gòu)。它在充分利用單向數(shù)據(jù)流的基礎(chǔ)之上,補(bǔ)充和完善了React的可組合視圖組件。簡(jiǎn)單說(shuō)來(lái),Flux架構(gòu)有以下幾個(gè)特征:
1.單向數(shù)據(jù)流:提高應(yīng)用的可預(yù)測(cè)性,能夠輕松掌握更新升級(jí)的具體進(jìn)度;
2.職責(zé)和范圍的分離:Flux架構(gòu)中的每一部分都有特定的責(zé)任,彼此之間是絲毫不掛鉤的;
3.能夠與表述性編程完美配合:無(wú)需特別明示不同狀態(tài)之間的轉(zhuǎn)換視圖就可以針對(duì)視圖進(jìn)行升級(jí)。
鑒于從本質(zhì)上來(lái)講,Flux并不是一個(gè)框架,所以開(kāi)發(fā)人員已經(jīng)嘗試過(guò)各種方法,以便將Flux模式付諸實(shí)踐。因此,Redux就誕生了。Redux結(jié)合了Flux、Command模式和Elm架構(gòu)的創(chuàng)意,事實(shí)上就是一個(gè)狀態(tài)管理庫(kù)?,F(xiàn)如今的開(kāi)發(fā)人員,都習(xí)慣性地將其與React配套使用。具體說(shuō)來(lái),Redux有以下幾個(gè)核心概念:
1.應(yīng)用的狀態(tài)都是利用單一的舊式JavaScript對(duì)象來(lái)描述的;
2.可以通過(guò)調(diào)度某一行為操作來(lái)改變狀態(tài);
3.縮減器或者折疊器能夠利用當(dāng)下的狀態(tài)和行為操作,來(lái)生產(chǎn)新的狀態(tài)。
當(dāng)然了,雖然概念聽(tīng)上去比較簡(jiǎn)單,但功能卻非常強(qiáng)大,它們能夠讓應(yīng)用:
1.由用戶提出在服務(wù)器上完成狀態(tài)改變;
2.在應(yīng)用當(dāng)中追蹤、登錄和回溯所有變化;
3.更加便利地使用撤銷和重做功能。
NO.5 帶有風(fēng)格的編碼——CSS Module
所謂CSS就是層疊樣式表,專門指用來(lái)描述HTML元素樣式的規(guī)則。想要寫出比較好的CSS,是件很困難的事情,一般需要多年經(jīng)驗(yàn)和不斷嘗試。其實(shí),一開(kāi)始,CSS是專門為網(wǎng)頁(yè)文件設(shè)計(jì)的,并不是為網(wǎng)頁(yè)應(yīng)用設(shè)計(jì)的,更別說(shuō)偏向于組件架構(gòu)的網(wǎng)頁(yè)應(yīng)用了。因此,經(jīng)驗(yàn)豐富的前端開(kāi)發(fā)人員就想盡一切辦法,希望能夠指導(dǎo)人們利用SMACSS和BEM來(lái)為那些比較復(fù)雜的項(xiàng)目寫出組織性和條理性較強(qiáng)的CSS。
如果在此之前,你從來(lái)沒(méi)有接觸過(guò)CSS,那么Codecademy網(wǎng)站上的HTML & CSS課程,可以在很大程度上幫助你學(xué)習(xí)入門知識(shí)。隨后,你可以了解有關(guān)Sass預(yù)處理程序的知識(shí)。Sass預(yù)處理程序是CSS語(yǔ)言的延伸,在之前的基礎(chǔ)之上進(jìn)行了句法完善。總而言之,你可以花上三四天的時(shí)間,先去了解CSS方法,再去學(xué)習(xí)CSS模塊,盡量綜合利用SMACSS或BEM方法以及CSS模塊,來(lái)開(kāi)發(fā)出帶有自己風(fēng)格的應(yīng)用。
NO.6 可維護(hù)性
與編寫代碼相比,人們用眼睛看代碼的次數(shù)更多。在Grab這種規(guī)模較大的公司更是如此,各位工程師都在忙著不同的項(xiàng)目。因此,我們非??粗鼐幊檀a的可讀性、可維護(hù)性和穩(wěn)定性。當(dāng)然了,想要同時(shí)保證這三點(diǎn),也是有方法可以利用的,比如說(shuō)廣泛測(cè)試、一致的編程風(fēng)格,以及類型檢查。
NO.7 測(cè)試——Jest + Enzyme
Jest是由Facebook開(kāi)發(fā)的一個(gè)測(cè)試庫(kù),主要目的就是減少測(cè)試過(guò)程中可能出現(xiàn)的問(wèn)題。在Facebook進(jìn)行的項(xiàng)目當(dāng)中,它提供了非常順暢的使用體驗(yàn)。不同測(cè)試可以同時(shí)進(jìn)行,以便縮短拿到結(jié)果的時(shí)間。在默認(rèn)情況和監(jiān)測(cè)模式下,只會(huì)運(yùn)行那些針對(duì)發(fā)生了改變的文件的測(cè)試。而其中,我們特別喜歡的一個(gè)功能,叫做Snapshot Testing,即快照測(cè)試。Jest能夠?qū)?span lang="EN-US">React組件和Redux狀態(tài)生成的結(jié)果保存下來(lái),并且還能夠以序列化文件的形式保存下來(lái)。這樣一來(lái),就避免了手動(dòng)操作。
雖然React也有測(cè)試功能,但是Facebook開(kāi)發(fā)的Enzyme能夠通過(guò)一個(gè)類似jQuery的API,讓你更加方便地生成、維護(hù)和操作React組件的產(chǎn)出結(jié)果。經(jīng)驗(yàn)豐富的開(kāi)發(fā)人員,會(huì)推薦你使用Enzyme來(lái)測(cè)試React組件。
總之,Jest和Enzyme能夠在簡(jiǎn)化前端測(cè)試代碼編寫過(guò)程的同時(shí),為開(kāi)發(fā)人員帶來(lái)更多樂(lè)趣。這樣一來(lái),開(kāi)發(fā)人員也就會(huì)更加愿意編寫測(cè)試代碼。不僅如此,由于職責(zé)和界面定義明確,React組件以及Redux的行為操作和縮減器,測(cè)試起來(lái)也就會(huì)更加容易。
NO.8 檢查JavaScript出現(xiàn)的問(wèn)題 — ESLint
所謂linter,就是一種對(duì)編程代碼進(jìn)行靜態(tài)分析并且及時(shí)找出問(wèn)題的工具,能夠在預(yù)防錯(cuò)誤出現(xiàn)的同時(shí),保證同一種編碼風(fēng)格。而ESLint就是其中一種檢查JavaScript編碼問(wèn)題的工具,具有比較明顯的擴(kuò)張性和定制性。如果開(kāi)發(fā)團(tuán)隊(duì)想要編寫帶有個(gè)別風(fēng)格的代碼,那也可以自行編寫查錯(cuò)規(guī)則。
在大多數(shù)情況下,使用ESLint就像在項(xiàng)目文件夾里修改配置文件一樣簡(jiǎn)單。如果你不自己寫的話,那要學(xué)的知識(shí)并沒(méi)有多少。你只要在出錯(cuò)時(shí)及時(shí)發(fā)現(xiàn),然后找到合適的解決方法。