
快魚(yú)吃慢魚(yú)的商業(yè)時(shí)代,生存法則就是 “快”!,而我今天要闡述的“快”所指的,不只是單純的開(kāi)發(fā)效率環(huán)節(jié),同時(shí)也涵蓋了協(xié)作效率、研發(fā)資源調(diào)度、組織過(guò)程資產(chǎn)等部分組合在一起的整體效率問(wèn)題
當(dāng)聊起前端,很多人會(huì)覺(jué)得非常簡(jiǎn)單,隨便拿個(gè)記事本也可以做個(gè)頁(yè)面,很多人正是因?yàn)榍岸说牡烷T檻才開(kāi)始踏上前端之路,而現(xiàn)在,各大前端技術(shù)社區(qū)卻呈現(xiàn)一片迷茫之聲,多少有志青年被迫淪為擺爛的碼農(nóng),框架的使用者,工具的使用者,在三天一新框架的行業(yè)內(nèi)卷下,哭喊著 學(xué)不動(dòng)了,十年的經(jīng)驗(yàn),水平卻停留在了工作后的第三年,而職業(yè)天花板肉眼可見(jiàn)——國(guó)內(nèi)鮮有研發(fā)負(fù)責(zé)人的崗位是由前端負(fù)責(zé)人擔(dān)任的。同時(shí)各大工廠都在哭喊:前端缺少人手。
我曾和很多前端從業(yè)者聊過(guò)對(duì)這個(gè)行業(yè)的理解,最普遍的認(rèn)知出奇的一致—— 易懂難精,門檻低,天花板也低
讓我們不妨盤(pán)一盤(pán)整個(gè)的來(lái)龍去脈:
起初,只有原生代碼,前端修著各種Bug和背著無(wú)盡的兼容兼容問(wèn)題艱難前行。
接下來(lái),非?!靶疫\(yùn)”的有了很多諸如JQuery之類的簡(jiǎn)單又給力的各種前端庫(kù),隨手就可以完成開(kāi)發(fā)需求,普通的開(kāi)發(fā)者要不了多久就成了一個(gè)團(tuán)隊(duì)的主力開(kāi)發(fā)者。
當(dāng)一些人以為前端不過(guò)如此,駐足享樂(lè)之時(shí),前端領(lǐng)域卻以爆炸式的增長(zhǎng)出現(xiàn)在各種論壇,頭條和Twitter 上。
和每個(gè)新興的領(lǐng)域一樣,造山造神造輪子,前端也不再是美工和“頁(yè)面仔”們的玩具,很多服務(wù)端開(kāi)發(fā)的人也踏入了這片新大陸,轟轟烈烈的跑馬圈地,給力的推動(dòng)了這個(gè)領(lǐng)域的發(fā)展。
oop 、設(shè)計(jì)模式、 MVC、前端模板、微服務(wù)、中間件各種服務(wù)端的陳舊的概念套在了前端的馬車上依然锃光瓦亮,熠熠生輝 。
PC時(shí)代還沒(méi)有終結(jié),便進(jìn)入了移動(dòng)互聯(lián)網(wǎng)時(shí)代,終端設(shè)備和交互方式同時(shí)發(fā)生了變化。
新的平臺(tái)新的時(shí)代,帶來(lái)了更多的商機(jī),激烈的市場(chǎng)競(jìng)爭(zhēng)也日以繼夜地進(jìn)行著。
在這種背景下,刀耕火種的編碼方式再也無(wú)法跟上激烈競(jìng)爭(zhēng)的市場(chǎng)變化。無(wú)數(shù)的舊有web項(xiàng)目,像磊高的鳥(niǎo)卵,隨時(shí)都會(huì)崩塌,沒(méi)人敢動(dòng)。
我們開(kāi)始重構(gòu),同時(shí)也背負(fù)了就有項(xiàng)目的技術(shù)債務(wù),還有來(lái)自移動(dòng)端的各種新特性和兼容問(wèn)題, 很多前端團(tuán)隊(duì)曾一度被吐槽:
為什么一個(gè)小的需求,需要這么久?
技術(shù)的挑戰(zhàn)對(duì)于商業(yè)需求,是不可見(jiàn)的。我們能做的是,找到瓶頸,提高效率!
就像住宅,
以前住山洞. 只需要鋪點(diǎn)稻草。
現(xiàn)在我們要蓋摩天大樓,我們需要 工程化!
今天的話題就從工程效率開(kāi)始:
- 工程效率
所謂提升效率,是一個(gè)相對(duì)概念,實(shí)際開(kāi)發(fā)中,很多效率消耗是看不見(jiàn)的,卻占用很多的時(shí)間,藏匿了很多的風(fēng)險(xiǎn),所以首要任務(wù)是找到瓶頸,再找個(gè)趁手的兵器去解決掉這些的重復(fù)且易出錯(cuò)的流程。
shell ,grunt ,gulp , webpack, yeoman,vite, rollup, parcel ......
這些是搭建前端自動(dòng)化工作流的常用工具:
還遠(yuǎn)不止這些,很多公司也都在做自己的構(gòu)建工具,毋庸細(xì)表。
主要解決的是以下問(wèn)題:
- 性能
前端自動(dòng)化有很大一部分工作是為了性能,yahoo在很早以前就總結(jié)了前端的34條優(yōu)化原則。
```
1. 盡量減少 HTTP 請(qǐng)求次數(shù)
1. 減少DNS查找次數(shù)
1. 避免跳轉(zhuǎn)
1. 可緩存的 AJAX
1. 推遲加載內(nèi)容
1. 預(yù)加載
1. 減少DOM元素?cái)?shù)量
1. 根據(jù)域名劃分頁(yè)面內(nèi)容
1. 使 iframe 的數(shù)量最小
1. 不要出現(xiàn) 404 錯(cuò)誤
1. 使用內(nèi)容分發(fā)網(wǎng)絡(luò)
1. 為文件頭指定Expires或Cache-Control
1. Gzip壓縮文件內(nèi)容
1. 配置ETg
1. 盡早刷新輸出緩沖
1. 使用GET來(lái)完成AJAX請(qǐng)求
1. 把樣式表置于頂部
1. 避免使用CSS表達(dá)式(Expression)
1. 使用外部JavaScript和CSS
1. 削減JavaScript和CSS
1. 用代替@import
1. 避免使用濾鏡
1. 把腳本置于頁(yè)面底部
1. 剔除重復(fù)腳本
1. 減少 DOM 訪問(wèn)
1. 開(kāi)發(fā)智能事件處理程序
1. 減小Cookie體積
1. 對(duì)于頁(yè)面內(nèi)容使用無(wú)coockie域名
1. 優(yōu)化圖像
1. 優(yōu)化 CSS Spirite
1. 不要在 HTML 中縮放圖像
1. favicon.ico 要小而且可緩存
1. 保持單個(gè)內(nèi)容小于 25K
1. 打包組件成復(fù)合文本
````
這其中,很多都是可以在自動(dòng)化工具的構(gòu)建過(guò)程中做到的,性能有了初步保障。
流程
一個(gè)項(xiàng)目在開(kāi)發(fā)過(guò)程中存在很多流程,它們重復(fù)頻次高且容易出錯(cuò):創(chuàng)建項(xiàng)目
創(chuàng)建頁(yè)面
創(chuàng)建頁(yè)面相關(guān)資源
創(chuàng)建模塊
創(chuàng)建模塊相關(guān)資源
詳細(xì)設(shè)計(jì)
創(chuàng)建接口文檔
創(chuàng)建模擬接口
接口聯(lián)調(diào)
編譯
單元測(cè)試
推送至聯(lián)調(diào)機(jī)
提測(cè)
預(yù)上線
上線
回滾
監(jiān)控
協(xié)作
協(xié)作著重點(diǎn)是:與PM協(xié)作,與后端協(xié)作
與PM協(xié)作:
前端團(tuán)隊(duì)需要跟其他團(tuán)隊(duì)緊密協(xié)作,溝通協(xié)作也是制約因素之一。在過(guò)去的項(xiàng)目中,你是否經(jīng)理過(guò)由于溝通誤差導(dǎo)致的無(wú)效開(kāi)發(fā),甚至線上事故。
我發(fā)現(xiàn)技術(shù)團(tuán)隊(duì)正在忙碌的時(shí)候,產(chǎn)品團(tuán)隊(duì)有新的需求往往又不知道我們的人力狀況,這對(duì)他在指定產(chǎn)品迭代計(jì)劃不利,導(dǎo)致PM單方面制定了很多不合理的“時(shí)間倒推型”項(xiàng)目,研發(fā)團(tuán)隊(duì)集體持續(xù)加班。實(shí)際上某些情況下本可以避免的,畢竟,人困馬乏非常態(tài)用兵之道。
對(duì)于我們團(tuán)隊(duì)的人力投入狀況,以及人力釋放的計(jì)劃,完全可以用工具 來(lái)顯示。進(jìn)一步的,PM可以在此申請(qǐng)項(xiàng)目,申請(qǐng)人力。但前提是,團(tuán)隊(duì)需要把技術(shù)架構(gòu)統(tǒng)一,使得開(kāi)發(fā)者更方便的跨越產(chǎn)品線做技術(shù)支持,對(duì)于業(yè)務(wù)的深刻理解實(shí)際上是一種組織過(guò)程資產(chǎn),需要團(tuán)隊(duì)內(nèi)部串講與共享。
與后端協(xié)作-前后端分離
互聯(lián)網(wǎng)伊始,并沒(méi)有如今這么明細(xì)的分工,開(kāi)發(fā)人員包辦了所有開(kāi)發(fā)任務(wù)。
回看那時(shí)的業(yè)務(wù)形態(tài),多半是 新聞系統(tǒng),企業(yè)網(wǎng)站,還有就是BBS。界面和交互基本都是千篇一律。
直到web2.0概念興起,掛起了頁(yè)面重構(gòu)風(fēng),前后端的分工越來(lái)越明確。
時(shí)至今日,前后端分離變成了熱議的話題。
聯(lián)調(diào)過(guò)程一直是WEB開(kāi)發(fā)的痛點(diǎn),在工作流中集成解決方案,可以更快定位問(wèn)題,減少溝通成本。
基于nodejs的SSR與服務(wù)層實(shí)踐:
很多公司都在行動(dòng)。最典型的是“某寶、某里”公司,nodejs接管了許多產(chǎn)品線的httpserver,做業(yè)務(wù)接口聚合,越來(lái)越多的服務(wù)端邏輯,被前端團(tuán)隊(duì)接管。后端變成了純粹的數(shù)據(jù)輸出層。
筆者曾在某浪公司也推動(dòng)過(guò)nodejs的前后端分離解決方案,遇到了一些阻力。 究其原因是多方面的:
服務(wù)端編程并非掌握一門服務(wù)端語(yǔ)言這么簡(jiǎn)單,前端團(tuán)隊(duì)的服務(wù)端開(kāi)發(fā)基本技能不夠扎實(shí)。
nodejs的人力來(lái)自前端團(tuán)隊(duì),但就我所在的團(tuán)隊(duì)而言,短時(shí)間內(nèi)并不是每個(gè)前端都可以勝任服務(wù)端開(kāi)發(fā)。開(kāi)發(fā)和維護(hù)都容易出現(xiàn)人力瓶頸(曾經(jīng)就有杭州的一個(gè)nodejs項(xiàng)目接過(guò)來(lái)以后變成了爛尾,后來(lái)還是被改回了php)
技術(shù)負(fù)責(zé)人鮮有nodejs語(yǔ)言和項(xiàng)目的把控能力,一旦項(xiàng)目出現(xiàn)技術(shù)瓶頸,將很難把控。
原本后端的工作交接給前端來(lái)做,后端剩余人力又當(dāng)如何安排?當(dāng)然,也考慮過(guò)請(qǐng)后端的同學(xué)學(xué)習(xí)使用nodejs,但收效甚微。也許是他們找不到理由學(xué)習(xí)和使用nodejs。
這種架構(gòu)雖然在有歷史架構(gòu)包袱的公司很難普及。但是一些新團(tuán)隊(duì)大膽的采用nodejs堆棧,推行全棧工程師文化(這里的全棧僅僅等于client端+server端開(kāi)發(fā),更深的全棧是不局限語(yǔ)言的,不同的需求,采用不同的技術(shù)解決方案)。
不過(guò)也有落地成功的,比如某知名技術(shù)社區(qū)“某SDN”使用nodejs支撐了全站消息通知服務(wù)。某“出行巨頭“公司,甚至用nodejs支撐了整個(gè)金融系統(tǒng)的券服務(wù)與活動(dòng)系統(tǒng)。
充分說(shuō)明了,不是語(yǔ)言的問(wèn)題,事在人為。
基于其它服務(wù)端語(yǔ)言的SSR:
筆者曾有幸在某度工作過(guò)兩年,當(dāng)時(shí)的前后端分離方案是基于前端寫(xiě)php的starty模板,前端開(kāi)發(fā)需要依賴php環(huán)境。當(dāng)然如果沒(méi)有別的方案,這樣的架構(gòu)當(dāng)年也是跑的可以。只是溝通和成本變得昂貴。
某東電商的前后端分離也與此類似,只是京東是基于java的。寫(xiě)的是java體系下的模板語(yǔ)言。 好在京東的前端工程化把模板環(huán)境集成了進(jìn)去,使用Nodejs就可以支撐java模板。做的比較完善。如同F(xiàn)is一樣,京東的前端團(tuán)隊(duì)推出了 “jdf” 自成一體。(npmjs.com 上面可以搜索到)
相關(guān)的技術(shù)也在快速迭代—— 云函數(shù)、serverLess、graphQL
技術(shù)積累與知識(shí)共享
- 知識(shí)共享
做過(guò)業(yè)務(wù)開(kāi)發(fā)的人,都知道,每次的項(xiàng)目都會(huì)遇到一些奇葩的問(wèn)題,尤其是前端領(lǐng)域,這種情況更普遍。知識(shí)共享的目的是希望可以有一個(gè)地方搜索別人是否遇到同樣的問(wèn)題
由于業(yè)務(wù)形態(tài)不同,在搜索引擎和stackoverflow未必能找到答案,所以需要我們自己的要有知識(shí)共享庫(kù),它將隨著時(shí)間推移避免更多人踩同樣的坑。
這在前端工程化里是個(gè)弱需求,但從長(zhǎng)遠(yuǎn)來(lái)看它,不可或缺。前端工作流最好提供一個(gè)更簡(jiǎn)潔的方式,讓開(kāi)發(fā)者可以快捷的提交到知識(shí)庫(kù)中。后續(xù)可以在郵件收到關(guān)注問(wèn)題的互動(dòng)信息。
-
組件生態(tài)
組件化,也叫模塊化,插件化,是一種分治思想。
組件化之路其實(shí)也是軟件世界的進(jìn)化之路,前端亦是如此,從面相 對(duì)象編程到模塊化開(kāi)發(fā),越來(lái)越多的框架涌現(xiàn),讓人目不暇接。
>我不想討論如何做模塊化開(kāi)發(fā),因?yàn)檫@不是工程化的重點(diǎn)。
當(dāng)你選中一個(gè)框架,決定將后續(xù)的業(yè)務(wù)代碼,按照它的規(guī)范進(jìn)行模塊開(kāi)發(fā), 那么問(wèn)題來(lái)了:
- 如何提交這些組件
- 如何迭代組件版本
- 如何解決組件依賴
- 別人如何使用你的組件
- 一個(gè)標(biāo)準(zhǔn)的組件包含哪些部分
- 如何沉淀出優(yōu)秀組件
當(dāng)你解決掉這些問(wèn)題,我就認(rèn)為你已經(jīng) 建立了一個(gè)組件生態(tài)環(huán)境
當(dāng)項(xiàng)目以堆積木的方式開(kāi)發(fā),才能有。
前端自動(dòng)化測(cè)試
前端的自動(dòng)化測(cè)試一直都有爭(zhēng)議,問(wèn)題癥結(jié)在于投入產(chǎn)出比,以及覆蓋率問(wèn)題。
從工具方面其中涌現(xiàn)了許多給力的測(cè)試框架:
Mocha& Chai
JavaScript 在很長(zhǎng)一段時(shí)間內(nèi)是非常煩人的。測(cè)試任何代碼通常都被認(rèn)為是惱人的,但它卻是每個(gè)開(kāi)發(fā)人員都應(yīng)該做的事情。每個(gè)開(kāi)發(fā)人員似乎總是蔑視和忽略它,而不測(cè)試他們的代碼。這個(gè)惱人的東西有一個(gè)解決辦法,那就是 Mocha 和 Chai。兩個(gè)庫(kù)的名字都來(lái)自美味的熱飲料,它們都能幫你測(cè)試代碼,但方式不同。
Mocha 是一個(gè) JavaScript 測(cè)試框架,使得你在 node 模塊和瀏覽器 app 中測(cè)試異步代碼變得更容易。Mocha 測(cè)試可以串聯(lián)運(yùn)行,可以為正確的測(cè)試用例添加異常跟蹤的能力。
Chai 是一個(gè)行為驅(qū)動(dòng)開(kāi)發(fā)/測(cè)試驅(qū)動(dòng)開(kāi)發(fā)的斷言庫(kù),可以搭配 Mocha 使用。它可以把你需要測(cè)試的東西用可讀的風(fēng)格簡(jiǎn)單地表達(dá)出來(lái)。
何時(shí)使用 Mocha & Chai?總是!請(qǐng)測(cè)試你的代碼,讓世界變得更美好。
Karma
既然已經(jīng)把 Mocha 和 Chai 包含在這個(gè)列表中了,如果不包含用來(lái)運(yùn)行這些測(cè)試或設(shè)置持續(xù)集成測(cè)試的測(cè)試運(yùn)行器,那將是不完整的。Karma 是一款旨在幫助你在不同的瀏覽器上自動(dòng)運(yùn)行測(cè)試的工具。它可以幫助你在所有瀏覽器上運(yùn)行 Mocha 和 Chai 測(cè)試。
不是每個(gè)瀏覽器都運(yùn)行在所有平臺(tái),但幸運(yùn)的是可以使用一些免費(fèi)工具來(lái)測(cè)試其他瀏覽器,看看 Browser Screenshots。如果你正在 OS X 上運(yùn)行代碼,想測(cè)試 Edge 或 IE,可以 免費(fèi) 使用這個(gè)工具。
在前端工具中,的每次編譯任務(wù)集成自動(dòng)測(cè)試使得每一次的修改更加放心,但是,很顯然這里面有個(gè)測(cè)試用例和覆蓋率的成本問(wèn)題,這是一個(gè)博弈的過(guò)程.
我的想法是不推薦在所有業(yè)務(wù)代碼中都去寫(xiě)測(cè)試用例,只在通用性較強(qiáng)和比較關(guān)鍵的,重復(fù)迭代的模塊中使用。
開(kāi)源貢獻(xiàn)
不重復(fù)造輪子!除非你的輪子是革命性的。
在這個(gè)技術(shù)領(lǐng)域“物產(chǎn)豐富”的時(shí)代,往往會(huì)發(fā)現(xiàn)互聯(lián)網(wǎng)上能找到很多你原本想要自己做的東西,你唯一需要考慮的是如何使用,如何按照自己需求去迭代。
開(kāi)源是這個(gè)時(shí)代最好的禮物,可以通過(guò)開(kāi)源快速滿足項(xiàng)目需求,交流技術(shù),認(rèn)識(shí)更多更優(yōu)秀的人。
如今對(duì)于程序員的社交平臺(tái) 非github莫屬了。
一個(gè)高產(chǎn)的團(tuán)隊(duì),不僅要滿足業(yè)務(wù)需求,還需要有開(kāi)源精神。
不但要把自己團(tuán)隊(duì)產(chǎn)出的資源共享,也需要與你使用的開(kāi)源項(xiàng)目一起迭代,積極提交PR(pull request)
github如今也變成了招聘技術(shù)人才的絕佳平臺(tái),從他的代碼上基本可以基本了解這個(gè)人的技術(shù)能力,甚至性格和追求。
代碼審查
關(guān)于代碼審查,很多團(tuán)隊(duì)都表示難成其重,成本太高。作為學(xué)習(xí)使用。
也有作為開(kāi)發(fā)流程的一部分,強(qiáng)制執(zhí)行的。
在這里,我想談的是,如何建立一份代碼審查清單:
常規(guī)項(xiàng)
代碼能夠工作么?它有沒(méi)有實(shí)現(xiàn)預(yù)期的功能,邏輯是否正確等。
所有的代碼是否簡(jiǎn)單易懂?
代碼符合你所遵循的編程規(guī)范么?這通常包括大括號(hào)的位置,變量名和函數(shù)名,行的長(zhǎng)度,縮進(jìn),格式和注釋。
是否存在多余的或是重復(fù)的代碼?
代碼是否盡可能的模塊化了?
是否有可以被替換的全局變量?
是否有被注釋掉的代碼?
循環(huán)是否設(shè)置了長(zhǎng)度和正確的終止條件?
是否有可以被庫(kù)函數(shù)替代的代碼?
是否有可以刪除的日志或調(diào)試代碼?
安全
所有的數(shù)據(jù)輸入是否都進(jìn)行了檢查(檢測(cè)正確的類型,長(zhǎng)度,格式和范圍)并且進(jìn)行了編碼?
在哪里使用了第三方工具,返回的錯(cuò)誤是否被捕獲?
輸出的值是否進(jìn)行了檢查并且編碼?
無(wú)效的參數(shù)值是否能夠處理?
文檔
是否有注釋,并且描述了代碼的意圖?
所有的函數(shù)都有注釋嗎?
對(duì)非常規(guī)行為和邊界情況處理是否有描述?
第三方庫(kù)的使用和函數(shù)是否有文檔?
數(shù)據(jù)結(jié)構(gòu)和計(jì)量單位是否進(jìn)行了解釋?
是否有未完成的代碼?如果是的話,是不是應(yīng)該移除,或者用合適的標(biāo)記進(jìn)行標(biāo)記比如‘TODO’?
測(cè)試
代碼是否可以測(cè)試?比如,不要添加太多的或是隱藏的依賴關(guān)系,不能夠初始化對(duì)象,測(cè)試框架可以使用方法等。
是否存在測(cè)試,它們是否可以被理解?比如,至少達(dá)到你滿意的代碼覆蓋(code coverage)。
單元測(cè)試是否真正的測(cè)試了代碼是否可以完成預(yù)期的功能?
是否檢查了數(shù)組的“越界“錯(cuò)誤?
是否有可以被已經(jīng)存在的API所替代的測(cè)試代碼?
你同樣需要把特定語(yǔ)言中有可能引起錯(cuò)誤的問(wèn)題添加到清單中。
這個(gè)清單故意沒(méi)有詳盡的列出所有可能會(huì)發(fā)生的錯(cuò)誤。你不希望你的清單是這樣的,太長(zhǎng)了以至于從來(lái)沒(méi)人會(huì)去用它。僅僅包含常見(jiàn)的問(wèn)題會(huì)比較好。
優(yōu)化你的清單
把使用清單作為你的起點(diǎn),針對(duì)特定的使用案例,你需要對(duì)其進(jìn)行優(yōu)化。一個(gè)比較棒的方式就是讓你的團(tuán)隊(duì)記錄下那些在代碼審查過(guò)程中臨時(shí)發(fā)現(xiàn)的問(wèn)題,有了這些數(shù)據(jù),你就能夠確定你的團(tuán)隊(duì)常犯的錯(cuò)誤,然后你就可以量身定制一個(gè)審查清單。確保你刪除了那些沒(méi)有出現(xiàn)過(guò)的錯(cuò)誤。(你也可以保留那些出現(xiàn)概率很小,但是非常關(guān)鍵的項(xiàng)目,比如安全相關(guān)的問(wèn)題)。
得到認(rèn)可并且保持更新
基本規(guī)則是,清單上的任何條目都必須明確,而且,如果可能的話,對(duì)于一些條目你可以對(duì)其進(jìn)行二元判定。這樣可以防止判斷的不一致。和你的團(tuán)隊(duì)分享這份清單并且讓他們認(rèn)同你清單的內(nèi)容是個(gè)好主意。同樣的,要定期檢查你的清單,以確保各條目仍然是有意義的。
有了一個(gè)好的清單,可以提高你在代碼審查過(guò)程中發(fā)現(xiàn)的缺陷個(gè)數(shù)。這可以幫助你提高代碼標(biāo)準(zhǔn),避免質(zhì)量參差不齊的代碼審查。
小結(jié)
高產(chǎn)的前端團(tuán)隊(duì),最終還是取決于人,工具自動(dòng)化,組件的生態(tài),質(zhì)量把控, 這一系列的努力,才能讓一個(gè)團(tuán)隊(duì)保持激情和戰(zhàn)斗力。
開(kāi)源社區(qū)的使用、互動(dòng)和參與迭代,甚至走出公司做技術(shù)交流的活動(dòng),讓團(tuán)隊(duì)技術(shù)視野保持在業(yè)界水準(zhǔn)。