如果你正在籌劃新的前端項(xiàng)目或者重構(gòu)現(xiàn)有項(xiàng)目,,那么你需要認(rèn)識(shí)到現(xiàn)在的前端開(kāi)發(fā)環(huán)境已經(jīng)今非昔比,,這其中有太多的選擇了:React、Flux,、Angular,、Aurelia、Mocha,、Jasmine,、Babel、TypeScript,、Flow…… 它們的本意是將開(kāi)發(fā)簡(jiǎn)單化,,卻無(wú)形中提高了學(xué)習(xí)成本,也給未來(lái)項(xiàng)目的維護(hù)帶來(lái)了不確定性,。 好在這一現(xiàn)象正在退熱,,優(yōu)勝劣汰,優(yōu)秀的項(xiàng)目慢慢沉淀下來(lái),開(kāi)發(fā)方式也越來(lái)越清晰,。有些開(kāi)發(fā)者正在嘗試使用基于上述技術(shù)的框架進(jìn)行開(kāi)發(fā),,也在一定程度上減少了學(xué)習(xí)成本。 本文中主要介紹了一些我在 web 應(yīng)用開(kāi)發(fā)中所涉及和推崇的技術(shù),,其中有一些技術(shù)上存在爭(zhēng)議,,所以我對(duì)于每一技術(shù)都只做簡(jiǎn)單的介紹和分析。所有的這些觀(guān)點(diǎn)都是基于我個(gè)人的經(jīng)驗(yàn)和對(duì)社區(qū)的接觸總結(jié)而來(lái)的,,所以各位還請(qǐng)按需各取所用,。 ReactReact 可謂風(fēng)頭正盛一時(shí)無(wú)兩:
雖然比起 Ember,、Aurelia 和 Angular 這些功能豐富的框架,React 不是全能手,,但 React 的開(kāi)發(fā)環(huán)境更加健壯,。就目前而言,使用 React 已經(jīng)不是一個(gè)技術(shù)選擇,,而是一個(gè)商業(yè)行為,,它能提供更高效和更有效的生產(chǎn)力。
Redux現(xiàn)在,,我們已經(jīng)具有了開(kāi)發(fā)視圖層的能力,,接下來(lái),我們需要使用其他工具管理應(yīng)用程序中的狀態(tài)和生命周期,,在這里推薦的工具就是:Redux,。 為了配合 React,F(xiàn)acebook 開(kāi)發(fā)了管理單向數(shù)據(jù)流的工具 Flux,,雖然 Flux 基本上實(shí)現(xiàn)了對(duì)單項(xiàng)數(shù)據(jù)流的支持,,但是同時(shí)也帶了其他問(wèn)題,比如如何保存狀態(tài),、何處發(fā)起 Ajax 請(qǐng)求等等,。 為了解決這些問(wèn)題,又衍生了一系列效仿 Flux 模式的框架:Fluxible,、Reflux,、Alt,、Flummox、Lux,、Nuclear,、Fluxxor…… 目前來(lái)說(shuō)被開(kāi)發(fā)社區(qū)廣泛支持的一個(gè)實(shí)現(xiàn)就是 Redux。 在 Redux 中,,大多數(shù)的組件都是純函數(shù)式的組件,,也只有一個(gè)集中的存儲(chǔ)和資源中心。Redux 的實(shí)例方法負(fù)責(zé)整個(gè)數(shù)據(jù)的操作和維護(hù),。相比 Flux 來(lái)說(shuō),,Redux 的思路更加清晰。 更重要的是,,Redux 非常易于學(xué)習(xí)。Redux 的作者 Dan Abramov 是一個(gè)優(yōu)秀的教師,,他制作了一系列深入淺出的 Redux 視頻教程,。通過(guò)觀(guān)看這些視頻,即可成為一個(gè) Redux 方面的專(zhuān)家,。我曾經(jīng)見(jiàn)識(shí)到一個(gè)零基礎(chǔ)的 React 團(tuán)隊(duì)在短短幾周內(nèi)迅速開(kāi)發(fā)出了測(cè)試版產(chǎn)品,,且代碼非常穩(wěn)健和老練。 Redux 周邊的生態(tài)系統(tǒng)和 Redux 本身一樣健壯,。從神奇的 devtool 到強(qiáng)大的記憶化工具 reselect,,Redux 開(kāi)發(fā)社區(qū)為開(kāi)發(fā)者提供了應(yīng)有盡有的工具。 開(kāi)發(fā)者可能會(huì)本能地去嘗試抽象出一個(gè) Redux 模板,,這么做有諸多好處,,但請(qǐng)?jiān)谡J(rèn)清需求的基礎(chǔ)上來(lái)封裝模板,而不要盲目的去嘗試,。 ES6 和 Babel是時(shí)候拋棄 CoffeeScript 了,,這是因?yàn)樗闹T多特性已在 ES6 中出現(xiàn)類(lèi)似的語(yǔ)法,而 ES6 是實(shí)施標(biāo)準(zhǔn),,代表了 JavaScript 未來(lái)的發(fā)展方向,。 目前最新的瀏覽器已經(jīng)支持了 ES6 的大部分特性。Babel 是一個(gè)強(qiáng)大的轉(zhuǎn)換工具,,用于將 ES6 轉(zhuǎn)換為 ES5,。此外,根據(jù)目標(biāo)瀏覽器可以調(diào)整代碼轉(zhuǎn)換的程度,。 那么是否有類(lèi)型系統(tǒng)呢,?TypeScript 和 Flow 都為 JavaScript 提供了靜態(tài)類(lèi)型系統(tǒng),使用靜態(tài)類(lèi)型檢查,,可以有效捕獲錯(cuò)誤,,減少測(cè)試量,。目前來(lái)說(shuō),我建議對(duì)此持觀(guān)望態(tài)度,。 TypeScript 在盡力讓 JavaScript 向 C# 或 Java 的方向發(fā)展,,但缺少了許多高級(jí)的類(lèi)型系統(tǒng)特性,比如代數(shù)數(shù)據(jù)類(lèi)型(algebraic data types),。此外,,它不能像 Flow 一樣有效地處理 null。 相比而言,,F(xiàn)low 更加強(qiáng)大,,捕獲的錯(cuò)誤類(lèi)型也更多,但難于配置,。此外,,它對(duì) JavaScript 新特性的支持弱于 Babel,也不支持 Windows 系統(tǒng),。 就我個(gè)人的角度而言,,在前端開(kāi)發(fā)中類(lèi)型系統(tǒng)并不是至關(guān)重要的一環(huán)(此處可能有爭(zhēng)議)。在類(lèi)型系統(tǒng)更加健壯且對(duì) Babel 更友好之前,,還是讓我們靜觀(guān)其變吧,。 ESLint另一個(gè)無(wú)可爭(zhēng)議的工具是 ESLint。ESLint 支持 ES6 語(yǔ)法,,還提供了 React 插件,,已經(jīng)不單單是一個(gè)代碼審查工具了。目前來(lái)說(shuō),,JSLint 已經(jīng)過(guò)時(shí)了,,ESLint 可以替代 JSHint 和 JSCS 獨(dú)樹(shù)一幟了。 開(kāi)發(fā)者可以根據(jù)自己的需求配置 ESLint,,不過(guò)在這里我建議根據(jù) AirBNB 的開(kāi)發(fā)規(guī)范進(jìn)行配置,,也可以直接使用 ESLint airbnb config。當(dāng)然這份規(guī)范中尚有不足之處,,但保持團(tuán)隊(duì)整體代碼的一致性,,可以有效提高代碼的可讀性。 當(dāng)你熟悉了 ESLint 之后,,建議開(kāi)發(fā)者深入地嘗試其中的規(guī)則,。ESLint 捕獲的錯(cuò)誤越多,產(chǎn)品的穩(wěn)定性越高,。 NPM,,CommonJS 和 ES6 modules忘記 Bower 吧,用 NPM 接管一切,。類(lèi)似 Browserify 和 Webpack 的構(gòu)建工具間接提高了 NPM 在 web 開(kāi)發(fā)中的地位,。使用 NPM,,版本管理將會(huì)更加簡(jiǎn)單,也將更多地與 Node.js 生態(tài)系統(tǒng)接觸,。目前對(duì)于 CSS 的處理尚不足夠完善,。 你可能會(huì)考慮如何在部署服務(wù)器上執(zhí)行構(gòu)建呢?與 Ruby 的 Bundler 有所不同,,NPM 使用了通配符檢索文件,,且第三方包可以在代碼開(kāi)發(fā)中以及項(xiàng)目發(fā)布前做任意修改。使用 shrinkwrap 文件可以?xún)鼋Y(jié)項(xiàng)目中的第三方依賴(lài),,我建議使用 User 的 shrinkwrap,,提高輸出的一致性。此外,,開(kāi)發(fā)者也可以考慮使用類(lèi)似Sinopia 的工具托管自己的私有 NPM 服務(wù)器,。 Babel 會(huì)將 ES6 module 語(yǔ)法轉(zhuǎn)換為 CommonJS。CommonJS 是一種歷經(jīng)實(shí)踐的語(yǔ)法,,這意味著穩(wěn)定和通用,,此外,使用類(lèi)似 tree shaking (Webpack 2.0 和 Rollup 已經(jīng)支持該特性)的機(jī)制我們還能實(shí)現(xiàn)靜態(tài)代碼分析,。 Webpack除非你樂(lè)意在頁(yè)面添加數(shù)百個(gè)腳本標(biāo)簽,否則的話(huà)你應(yīng)該嘗試用構(gòu)建工具來(lái)打包頁(yè)面的資源了,。此外,,你還需要某些工具讓瀏覽器支持 NPM 第三方包。在這里,,我推薦你使用 Webpack,。 一年之前對(duì)于上述工作,開(kāi)發(fā)者還有諸多工具可以選擇,,比如基于 JavaScript 的 RequireJS,、Browserify 和 Webpack 解決方案,此外還有號(hào)稱(chēng)能對(duì) ES6 的模塊進(jìn)行最佳優(yōu)化的 RollupJS. 在嘗試了所有的工具之后,,我強(qiáng)烈建議開(kāi)發(fā)者選擇 Webpack:
Webpack 也非常善于處理大型的單頁(yè)應(yīng)用,,支持代碼分割和惰性加載,。 但是值得注意的是,Webpack 的學(xué)習(xí)曲線(xiàn)異常陡峭,。不過(guò)一旦你學(xué)會(huì)了它,,那么你就掌握了最強(qiáng)大的構(gòu)建系統(tǒng)。 那么 Gulp 和 Grunt 呢,?相比而言,,Webpack 更善于處理各類(lèi)資源,。如果你需要執(zhí)行其他類(lèi)型的構(gòu)建任務(wù),那么 Gulp 和 Grunt 還是有用的,。對(duì)于類(lèi)似運(yùn)行 Webpack 的基本任務(wù),,我建議直接使用 NPM 腳本。 Mocha + Chai + Sinon在 JavaScript 中,,有大量可選的單元測(cè)試工具,,每一個(gè)都很穩(wěn)定和健壯。如果你只是用于單元測(cè)試,,那么現(xiàn)有工具完全可以勝任你的需求,。 常見(jiàn)的測(cè)試工具有 Jasmine、Mocha,、Tape,、Ava、Jest 等,,它們各有所長(zhǎng),。 我對(duì)一個(gè)測(cè)試框架的要求有如下幾條:
第一條標(biāo)準(zhǔn)就排除了 Ava 和 Jest,。 我喜歡 Chai 斷言是因?yàn)槠浞N類(lèi)豐富,、功能齊全的插件,喜歡 Mocha 是因?yàn)槠鋵?duì)異步的良好支持,。強(qiáng)烈建議使用 Dirty Chai 避免某些問(wèn)題,。Webpack 的 mocha-leader 插件允許開(kāi)發(fā)者自動(dòng)執(zhí)行測(cè)試。 對(duì)于 React 而言,,開(kāi)發(fā)者可以參考一下 AirBNB 的 Enzyme 和 Teaspoon,。 我非常鐘愛(ài) Mocha 的特性,如果你想要的只是最基礎(chǔ)的功能,,可以參考這篇文章了解一下 Tape,。 LodashJavaScript 并沒(méi)有一個(gè)類(lèi)似 Java 或 .NET 的核心工具庫(kù),所以開(kāi)發(fā)者大都會(huì)從外部引用一個(gè)外部工具庫(kù),。 目前來(lái)說(shuō),,Lodash 是此類(lèi)工具中的佼佼者。此外,,由于它惰性執(zhí)行的特性,,也讓它是目前性能最佳的工具之一。使用 Lodash 時(shí)無(wú)需引用全部資源,,開(kāi)發(fā)者可以按需使用其中的函數(shù),。在 4.x 版本中,Lodash 為偏愛(ài)函數(shù)式編程的開(kāi)發(fā)者提供了一個(gè)“函數(shù)式開(kāi)發(fā)”模式,。 如果你熟悉函數(shù)式編程,,你可以了解一下 Ramda,。如果你決定使用這個(gè)庫(kù),可能需要引用一些 Lodash 函數(shù),。 fetch許多基于 React 的應(yīng)用程序都不再使用 jQuery 了,。除非你正在維護(hù)一個(gè)陳舊的項(xiàng)目或者用到的第三方庫(kù)依賴(lài)了 jQuery,否則已經(jīng)沒(méi)有必要使用它了,。 我喜歡讓項(xiàng)目保持簡(jiǎn)潔,,在代碼中只使用 fetch 。fetch 基于 promise,,F(xiàn)irefox 和 Chrome 都封裝了該接口,。對(duì)于其他瀏覽器,則需要提供一個(gè)膩?zhàn)幽_本,。我建議使用 isomorphic-fetch 在各個(gè)瀏覽器和服務(wù)端保持功能的一致性,。 當(dāng)然也可以其他優(yōu)秀的第三方庫(kù)異步獲取數(shù)據(jù),但我覺(jué)得 fetch 已經(jīng)夠用了,。 同構(gòu) JavaScript同構(gòu) JavaScript 是指同時(shí)運(yùn)行在客戶(hù)端和服務(wù)端的 JavaScript,,常用于在服務(wù)端預(yù)先渲染頁(yè)面,提高性能,,便于 SEO,。使用 React 可以實(shí)現(xiàn)同構(gòu) JavaScript,但是并不簡(jiǎn)單,,它提高了程序的復(fù)雜度,,限制了開(kāi)發(fā)者可選的工具和第三方庫(kù)。 如果你正在構(gòu)建一個(gè) B2C 的站點(diǎn),,比如電商網(wǎng)站,那么你可能就需要使用同構(gòu) JavaScript,。不過(guò),,對(duì)于內(nèi)部站點(diǎn)或者 B2B 程序,性能就不是最重要的了,,則同構(gòu) JavaScript 也就不是太重要了,。 API最近每個(gè)人好像都在思考如何處理 API。每個(gè)人都在隨波逐流的使用 RESTfull API,,SOAP 已經(jīng)成為了過(guò)去時(shí),。目前業(yè)界存在各種 API 協(xié)議,比如 HATEOAS,、JSON API,、HAL、GraphQL 等,。 GraphQL 賦予了客戶(hù)端進(jìn)行任意查詢(xún)的能力,。搭配 Relay,,可以更好地處理客戶(hù)端的狀態(tài)和緩存。不過(guò),,創(chuàng)建 GraphQL 的服務(wù)端接口的難度還較大,,且大多數(shù)的文檔都是面向 Node.js 的。 Netflix 的 Falcor 看起來(lái)提供了和 GraphQL/Relay 相似的能力,,同時(shí)還降低了服務(wù)端的需求,,但它目前尚處于開(kāi)發(fā)者預(yù)覽狀態(tài),尚未應(yīng)用于實(shí)際開(kāi)發(fā),。 所有已知的規(guī)范都各有缺陷,,有些過(guò)于復(fù)雜,有些只能處理數(shù)據(jù)讀取而不嗯那個(gè)更新,,有些和 REST 差異顯著,。許多開(kāi)發(fā)者選擇自己開(kāi)發(fā),但是還會(huì)遇到上述的問(wèn)題,。 我不認(rèn)為上述有一個(gè)完美的解決方案,,但我對(duì) API 有一個(gè)自己的認(rèn)知:
到目前為止,,我還沒(méi)有發(fā)現(xiàn)滿(mǎn)足上述所有條件的解決方案,。 如果你正在使用 RESFful,建議參考 Swagger 來(lái)編寫(xiě) API,。 ElectronElectron 可以使用前端技術(shù)構(gòu)建桌面程序,,GitHub 團(tuán)隊(duì)出品的 Atom 編輯器就是基于 Electron 創(chuàng)建的。本質(zhì)上,,Electron 內(nèi)部封裝了一個(gè) Node.js,,可以打開(kāi) Chrome 窗口渲染 UI,還可以訪(fǎng)問(wèn)操作系統(tǒng)本地的 API,,并且沒(méi)有瀏覽器中的沙盒機(jī)制,。開(kāi)發(fā)者可以通過(guò) Electron 打包和分發(fā)應(yīng)用程序。 這是創(chuàng)建跨平臺(tái)軟件最簡(jiǎn)單的方式,,而且還可以利用上述的所有工具,。此外,Electron 有完整的文檔和活躍的開(kāi)發(fā)社區(qū),。 你可能聽(tīng)說(shuō)過(guò) nw.js 的大名,,雖然它已經(jīng)存在了多年,但相比來(lái)說(shuō),,Electron 更加穩(wěn)定和易用,。 這里有一個(gè)基于 Electron、React 和 hot reload 的模板,嘗試一下吧,。 延伸下面是一些我在 Twitter 上關(guān)注的對(duì)象:
建議閱讀 Pate Hunt 的 Learning React! Dan Abramov 發(fā)布一系列的視頻教程 Getting started with Redux,,強(qiáng)烈推薦,!此外,Dan 還發(fā)布過(guò)一個(gè)關(guān)注列表,,比上述更加詳細(xì),。 Mark Erikson 的 React/Redux links 集合也是很好的學(xué)習(xí)材料。 按需使用JavaScript 的生態(tài)環(huán)境發(fā)展迅速,,正日益強(qiáng)大起來(lái),。React 的最佳實(shí)踐正在固化,周邊工具的職責(zé)和能力也日益清晰,。 最重要的事情就是要牢記:保持簡(jiǎn)潔,,按需使用。 如果你的應(yīng)用程序只有兩三屏,,那么就無(wú)需使用路由系統(tǒng),;如果你正在創(chuàng)建一個(gè)單頁(yè)應(yīng)用,那么甚至不需要 Redux,,只需要 React 自己的 state 屬性即可,;如果你正在創(chuàng)建一個(gè)簡(jiǎn)單的 CRUD 程序,那么你就不需要使用 Relay,;如果你正在學(xué)習(xí) ES6,,并不需要深入地了解 Async/Await 或裝飾器;如果你剛剛開(kāi)始學(xué)習(xí) React,,并不需要使用熱重載和服務(wù)端渲染,;如果你剛剛接觸 Webpack,你就不需要分離代碼和合并多個(gè)資源,;如果你剛剛學(xué)習(xí) Redux,,你不需要理解使用 Redux-Form 和 Redux-Sagas。 保持簡(jiǎn)潔,,每次只做一件事,! |
|
來(lái)自: 精髓_感知力 > 《江河湖海-輕重急緩》