本命年一定要記得穿紅褲衩:2015年總結

天鑲發表於2016-02-23

年終總結結果到這個時間才寫,其實也是無奈。本來計劃過年寫的,沒想到Steam竟然開了個農曆春節特惠,然後就被各種遊戲打了,辣雞平臺,斂我錢財,頹我精神,耗我青春,害我單身

以下全都是個人看法,如果有不認同的地方,請大吼一聲“傻逼寫的啥”然後關閉頁面

轉職

本命年終於快過去了,不知道是不是因為沒有穿紅褲衩,這一年有很多不順心的事情,不過也有很多好事。這一年最重要的事情就是順利從一隻學生狗轉職為一隻社畜。四月份畢業之後以前端工程師的職位入職天貓,到現在也差不多工作一年了。這裡寫一下幹這行以來對於“前端”這個行業的看法和感悟。

前端工程師在校園裡是一個複雜度和地位都被嚴重低估的職位。老師們對發展迅猛的前端技術不夠了解,更是有不少“師兄師姐”在介紹自己找工作經驗時“xx天速成就找到一份前端工作”、“公司招聘前端也不問會什麼,就問你肯不肯踏實幹這行,肯幹進去再教你”。當然學校裡的專案裡也會有頁面,但由於老師和學生對前端各種技術的陌生,大多數都是使用jQuery堆積程式碼完成功能了事。在大家眼裡,寫頁面沒啥技術含量。

前端的很多基礎知識,都無法在學校學到。學校老師交給學生的大多都是基礎知識,比如演算法、資料結構、編譯原理、作業系統、計算機網路這些,而針對於特定領域就很少涉及了。見過學校開設C、C++、Java、PHP等語言的課程,卻從來沒有看到過開設JavaScript、CSS、HTML的課程。網頁設計的選修課倒是有(我報了,很遺憾整個教室只有20人不到),但這裡所謂的網頁設計並不是前端那一套技術棧,而是Dreamweaver使用入門。前端技術棧在校園裡沒有普及。

就這樣產生了一個很有意思的現象:大堆公司喊缺前端,而學生們並不知道前端是什麼,怎麼去學習前端知識(最近兩年稍微好點了),他們更多的是去學Java、C++,走著師兄師姐們走過的道路。有幸現在已經有百度這種大公司注意到了這點,到高校裡開了不少前端知識講座,還在GitHub上搞了培訓專案。

希望各個大公司的前端部門能夠更多的走進校園,給對前端感興趣的小朋友們一點指導。

React

去年上半年4月份入職打雜了一段時間之後,就開始學習React並且進行了一些實戰演練:

  1. 產出一篇文章輕鬆入門React和Webpack,意外的很受好評,segmentfault上超過了200的收藏,tmall的github部落格上也有不少評論。可惜現在文章中已經有很多不適用了,babel大版本到6發生了不少變化,本地除錯也改成中介軟體了

  2. 把自己的部落格lingyu.wang改成了全React實現,程式碼在這裡,用react-router做了個單頁面應用,底層依然基於hexo,自己給hexo寫了個generate外掛把所有資料生成json而不直接生成頁面,為了練手已經喪心病狂了,SEO什麼的完全不在乎

  3. 寫了一些腳手架和元件,亂七八糟參見玩具箱

由於負責天貓最複雜的前端應用之一的開發和維護,有不少老程式碼,也由於遷移成本太大沒有辦法在Java層上插入Node.js中間層,各種模組之間各種耦合,中間也寫了篇用React做重構時的一些思考。當時專案裡存在以下幾種耦合:

  1. 最蛋疼的就是壓根就沒有模組化,所有程式碼都在一個檔案裡,2k+行的jQuery那種。最老式的寫法,也是在學校專案裡看到最多的方式,選擇器拿到DOM然後操作綁事件,大多多年前的程式碼或者是後端兼職寫的。基本上沒有可維護性。解決這種基本上就靠推倒重寫了,考慮投入產出比看懂它的成本還不如重新寫一個來得快

  2. 稍微好一點的是增加了模組化,但模組內部和之前思路沒什麼區別,只是把上面那種程式碼分開多個檔案放了。不同的模組在模組內部操作相同的HTML,一旦其中一個模組改變了HTML結構,其他模組直接就bug了…

  3. 再好一點增加了前端模板引擎,各個模組都在內部使用模板引擎渲染自己的HTML,模組初始化傳入一個容器,只要容器不衝突,模組之間就不會基於HTML耦合。模組會暴露一些介面,通過模組管理器獲取例項相互之間直接相互呼叫,這樣依舊是強依賴,兩個模組互相依賴,一旦其中一個換了,介面變了,另外一個模組也需要改變自己的程式碼。

  4. 模組內部完全黑盒,只要一個容器,裡面的內容由模組自己控制。模組有資料的入口和出口,入口就是一些由父模組或頁面傳入的配置,出口則是一些由父模組或頁面傳入模組回撥函式,回撥函式裡面附帶傳出的資料,而HTML相互之間無法互相修改,改了就報錯。沒錯這就是React

最後重構的方案定下來是React+AMD+Gulp(你沒有看錯,沒有打包,沒有webpack),之所以不打包主要是有老程式碼,元件頁都沒釋出到npm上,而且由於阿里的CDN支援combo,所以也就不做打包了,至於使用React做重構,主要是由於以下幾個原因:

  1. 使用React實現的模組和元件完全黑盒,Web Component理念,標籤使用方便快捷。不會引入新的維護成本

  2. 元件容易抽離,形成沉澱。我曾經把一部分新業務使用React實現,其中的不少元件稍加完善就沉澱出一些基礎元件,沒有剝離成本

  3. 模組相互之間不會汙染,沒辦法直接修改其他模組的DOM,改了就報錯,然後QA就提著刀殺過來了

  4. 商家應用,允許全非同步,富互動功能型頁面,效能不太爛都能接受

目前新業務已經完全基於React開發,元件庫也基本上沉澱出來了,而老業務也在通過一次次需求像React遷移

模組的實現和通訊

個人比較傾向於完全區分模組和元件這兩個概念。元件是完全沒有業務邏輯的功能單元,比如下拉框啊、日期選擇啊這種,元件只專注自身的功能。元件可能會有巢狀,但當發生了巢狀時,對外就是一個元件,父元件內部的子元件對外將完全不可見,它的行為也將完全由父元件控制。元件是複用的單元,應當更多的形成沉澱。而模組則包含業務邏輯,同時模組還承載了一個比較重要的功能:和其他模組通訊。

所以大體上一個應用就是:應用被劃分為多個業務模組,這些模組邏輯上是扁平的,他們採用統一的通訊機制進行通訊,一個模組上的資料發生變更時,會通知一個全域性的通訊中心,採用pub-sub機制將資料遞交給其他模組,其他模組拿到資料後影響自己的渲染。模組內部使用了很多的元件,但模組內部所有渲染使用的資料都由模組直接進行管控,樹形傳遞給各個元件。可以這麼想,模組內部類似Redux例項,而頁面上有多個Redux例項,它們再通過一個統一的pub-sub中心進行通訊。為什麼不整個應用直接做一個Redux例項呢?主要是因為要考慮到跨BU合作和新老多種技術相容。模組內部想怎麼玩怎麼玩,可以是React實現,可以使Vue實現,可以是原生js實現。模組作為一個通訊單元只要符合統一pub-sub通訊介面即可。

這套理念也確實實現並且落地到了不少頁面中,但這樣玩顯然還不夠過癮。React終究是前端在玩,前端寫React元件、模組和頁面很爽,但是數量大了一樣要加班一樣爽不起來。這裡就在考慮有沒有可能降低門檻,把事情交給別人來做,比如後端。首先元件肯定是前端來寫了,沒多少後端能寫好前端元件的,如果能寫好,他就不是後端而是全棧了,這種人就應該果斷拉過來幹前端堵缺口。那麼有沒有可能把模組和頁面交給他們來寫,而前端只提供一些元件呢?

讓後端寫,最重要的一點就是給模板賦能,畢竟後端只能接觸到模板。這麼一想,這不特麼就是React和MVVM相結合麼,把React的Virtual DOM或者說JSX標籤和MVVM的DOM模板一樣寫到HTML上,多麼Web Component化啊。這裡說一下為什麼不直接用MVVM比如Vue,而是用React。MVVM確實對後端開發工程師很友好,但這些元件是我們平常開發前端應用(前端部分前端自己負責的複雜業務)時沉澱下來的,這麼一大批元件讓我們再去重寫一份MVVM的太蛋疼了,後期維護兩份也比較吃力。就這樣開始嘗試,經過一段時間調研後,發現react-templates,可以把模板字串轉化為React.createElement,當時用browserify給它打了一個包,尼瑪壓縮後好像有500K+(未gzip),它是針對Node.js的。於是乎把它整個程式碼大體上進行了重寫,移除了lodash,自己重寫了使用的一些工具方法,然後又重寫了模板解析部分,採用瀏覽器的XML解析器,又移除了esprima等語法校驗,然後又加了一堆定製化,最後壓縮後20K左右(未gzip),終於可以在頁面上用了…最後大體上就實現了一套這樣的方案:

  • 一堆日常沉澱的React元件

  • 一個全域性的pub-sub通訊工具負責模組的通訊

  • 一個React實現的Module負責充當模組的角色

Module內部使用React Templates字串模板編譯成Virtual DOM的函式來進行渲染,可以通過一些“控制指令”來控制渲染結果,元件上面可以通過一些“通訊指令”來遞交元件的資料給Module這個模組。而Module模組資料發生變更後會觸發整個模組重繪,資料又會重新傳遞下來給元件並變更元件的渲染結果。

Module外部則是通過全域性的pub-sub通訊工具來負責模組通訊,Module負責與這個通訊工具進行直接互動來進行資料通訊。通訊建立橋接的方式也是在Module上定義一些“通訊指令”

最後,整個系統都採用React Templates來實現,整個頁面實現和通訊全部寫在模板上,頁面上只有一堆元件(可以在模板裡動態require,模板會在編譯期提取然後拉取完成了才進行初始化)。沒有任何業務js邏輯存在。

這樣實現了好幾個頁面我已經成功上線跑了幾個月了,還有幾個正在實現中,看上去很美好。但後來還是發現了一些問題:模組通訊過程太複雜,一個完整的資料流轉過程通過指令很難很直觀的展現,一個看起來很簡單的互動中間可能會經過4-5步資料流轉,甚至包括一些alert、confirm等等,想讓後端寫不太可能,連其他前端都看不太懂資料如何流轉。這一塊還有太多可以優化的地方。

流程自動化

去年下半年我參與了部門統一使用的前端流程自動化工具的維護及改造,同時負責了商家端通用元件的腳手架的開發和維護。花了不少時間在前端流程自動化上。前端經過這麼多年的發展,頁面上承載的互動、功能、邏輯不斷增加,專案逐漸變得龐大,維護和開發成本也隨之增加,但依然招不到人。__這裡順帶打個廣告,如果想來天貓前端的請發郵件至lingyucoder@gmail.com__。流程自動化也就愈發重要。最理想的狀況就是,只要是機械能夠完成的工作,人就不要參與了。用一些指令碼代替簡單重複的勞動,這樣我們也就可以少加點班了。

Node.js

Node.js給前端開發流程自動化帶來了福音。從目前部門前端開發流程來看,主要就是以下幾個步驟,括號裡是對應的開源工具:

  1. 建立專案(Yeoman)

  2. 構建以及監聽檔案變化自動構建(Gulp、Webpack、Grunt,Grunt估計現在用的很少了)

  3. 本地除錯,資源代理(Koa、Express+各種定製的中介軟體)

  4. 自動化測試、程式碼覆蓋率測試(mocha、istanbul、should/chai/expect、phntomjs、karma)

  5. 文件自動化生成(自己基於AST提取,或者直接用jsdoc之類的工具)

  6. 自動化校驗、釋出(一些指令碼)

這裡主要聊聊構建、本地除錯和自動化測試

構建

現在的構建過程已經不再像以前那樣壓縮一下就簡單,構建過程中往往會拿程式碼生成語法樹然後做各種操作:

  1. Babel爽爽寫ES6甚至ES7

  2. 將程式碼中的註釋轉化為監控打點(istanbul我記得就是基於語法樹給每個語法分支包一層打點層,彙總資料)

  3. 將程式碼中的註釋提取生成文件(React元件自動生成props文件就是這種方式)

  4. 將commonjs規範的程式碼轉化為各種各樣的模組化解決方案(AMD、KMD、UMD等等)

  5. 提取模組間的依賴關係,梳理應用模組依賴關係,繪製模組依賴樹

  6. Webpack打包

  7. 各種語法檢查(eslint,jshint),有時候還會有一些定製化的校驗

現在大家都比較中意webpack,依賴打包使得資源請求數大幅度減少(使用不支援combo的CDN服務的公司肯定很開心)。我個人還是對於webpack有一些顧慮,主要有兩點

  1. 不太贊同瀏覽器內使用的資源也釋出到npm上。瀏覽器上和Node.js通用的程式碼可能也就不到5%(lodash啊,underscore啊,moment啊這種),在npm上找到一個模組還要確認到底哪個場景下可用。使用的即便是這些可以共用的庫,也會有一個很蛋疼的問題:Node.js的模組往往大而全實現儘可能多的功能,而頁面使用的模組則是儘可能小而美,資源載入量儘可能少。比如只用到時間格式化和反格式化就引入一整個moment(moment真特麼大,我一般就格式化反格式化,喜歡用fecha),對於Node.js也許沒什麼壓力,但對於頁面就很蛋疼了。現在rollup試圖解決這個問題,還是比較值得看好的

  2. 不同版本重複打包的問題。這個問題比較頭疼。如果一個專案依賴了兩個元件,而這兩個元件引用了一個庫的兩個不同版本,這個庫就會被打包兩份,於是乎程式碼量就duang一下增大了。目前依舊沒有看到比較好的方式來解決。雖然可以用peerDependencies對一些基礎庫(比如React這種)做一下處理,也只是緩解一些罷了。

另外吐槽一句,webpack配置真繁瑣啊,個人目前傾向的方案是使用webpack+gulp,webpack負責打包和構建,其他的工作依舊交給gulp,我喜歡stream(不是steam)

本地除錯

前端資源本地除錯其實挺簡單的,就是把線上使用的資源代理到本地資源。由於現在一般都會使用CDN來承載這些資源(如果你們公司不用CDN,請找你們老闆撥點經費買個CDN服務吧),大致上也就是幾個步驟:

  1. 把CDN的域名通過host指向本地

  2. 在本地80(HTTP)或443(HTTPS)埠開啟對應的代理服務,根據請求查詢本地資源返回

  3. 如果涉及需要開啟多個服務,將各個服務開在不同的埠後在80或443埠加個nginx層做轉發

目前部門裡面用的是Koa+中介軟體實現了這裡面所有的內容。Koa現在也2.0了,使用新版本的Promise的co,用起來還是很爽的

如果一旦涉及到本地模板的除錯,就很蛋疼了,基本上是模擬資料,這裡懶得扯了。

自動化測試

對於自動化測試這一塊,在學生時代一直覺得測試麻煩,沒啥收益。但實際上自動化測試對於開發效率提升很大。之前參與部門統一構建工具的改造,有任何修改就跑一遍測試用例和程式碼覆蓋率,效率非常高,還非常容易形成沉澱,一旦有bug,就把bug會發生的場景也做成一個測試用例,方便後人接手。而且把程式碼接入像travis這樣的持續整合平臺後,程式碼質量更有保證了,任何一次push都會自動觸發測試,即便是pull request裡的程式碼也可以保證質量。現在寫程式碼覆蓋率低於90%就覺得各種不爽,一定要提到90%以上。

對於Node.js的模組,測試很方便,除了命令列工具可能需要加像sinon這樣的模組來監聽stdio以外,其他的基本上都能直接在程式碼中模擬環境。由於個人寫Node.js程式碼喜歡拆分的很細,每個邏輯單元都用co、curry做包裝,所以特別喜歡使用mocha+should,should 8.0+直接支援Promise,爽歪歪,

對於瀏覽器裡跑的程式碼,測試和覆蓋率就比較麻煩了,首先模擬環境比較蛋疼,大致上3種方案:

  1. 構建一個測試頁面,人肉直接到虛擬機器上開各種瀏覽器跑測試頁面(比如f2etest),這個問題就是不好持續化整合,人肉工作較多

  2. 使用phantomjs構建一個偽造的瀏覽器跑單元測試,大致上就是先用gulp-istanbul給程式碼打點,然後拿mocha-phantomjs跑包含測試用例的頁面,最後通過hook拿到結果用istanbul生成視覺化的覆蓋率頁面,蛋疼就是phantomjs畢竟是Qt的webkit,不是真實環境,phantomjs也是各種坑

  3. 通過karma呼叫本機各種瀏覽器進行測試,這個現在還沒玩的很6,還在研究中。還是有不少問題沒解決,畢竟用的mac,去哪兒找IE 8,囧,更別說移動端那麼多機型

對於測試個人一直堅持一個觀點:基於投入產出比來做測試。由於維護測試用例也是一大筆開銷(畢竟沒有多少測試會專門幫前端寫業務測試用例,而前端使用的流程自動化工具更是沒有測試參與了)對於像基礎元件啊,基礎模型啊之類的不常變更且複用較多的部分,可以考慮去寫測試用例來保證質量,但對於迭代較快的業務邏輯以及生存時間不長的活動頁面之類的就別花時間寫測試用例了,維護測試用例的時間大了去了,不如喝杯茶冷靜下讓QA他們去測吧。

學習

這一年由於轉職社畜各種忙的要死,導致沒有多少時間靜下心來看書了,文章也寫得少了。於是更傾向於每天水一水我的github(中間一大段空白因為3DS到貨了,鏖戰怪物獵人4G,這遊戲真特麼好玩),寫一些腳手架啊、元件啊、小工具啊啥的。之前覺得一些開源的logger不好用,就自己寫了個linglog,之前負責一個業務變更比較多總是打tag釋出,就寫了個自動釋出程式publishy,它會在釋出前做一些校驗防止我沒有commit或者沒有add之類的。還有像React元件自動化提取props做文件弄了個react-prop-table,以及對應的配套的markdown內容段自動更新gulp外掛gulp-insert-md。對應還有一些less依賴關係解析啥的弄了less-tree,然後有個需求要在模組更新時自動輸出最新更新有哪些變動於是有了changelogy,然後還有幾個自己弄得帶單元測試、程式碼覆蓋率測試、travis持續整合、eslint等的腳手架:React元件腳手架generator-lingyu-react-component, Node模組腳手架generator-lingyu-node-modules, gulp外掛腳手架generator-lingyu-gulp-plugin, 命令列工具腳手架generator-lingyu-cli-modules。寫這些玩意過程中學到了不少Node.js的姿勢,雖然離一個真正的Node.js工程師差的太遠

另外一點是入職後全面從sublime切到atom了,python苦手還是傷不起,我們用atom有外掛需求找不到自己寫一個,比如之前給xtemplate模板寫了個atom語法高亮和snippet外掛atom-language-xtpl,感覺比之前用sublime爽多了

還花了點錢買了SnippetsLab這個軟體,用來放一些程式碼片段超好用,我在裡面放了不少自己平常寫的一些小的工具函式,比如clone啊,unique啊,param和unparam啊這種,需要的時候就搜一下複製出來,方便快捷

生活

今年玩的遊戲不多,因為3DS到貨了,先說幾個3DS遊戲:

  1. 怪物獵人,沉迷了一段時間,甚至一整天一整天的和各種龍做鬥爭。現在怪物獵人累計遊戲時間應該有250小時了…

  2. 口袋妖怪X:硬著頭皮啃英文,擼寵系統好棒,每天擼一擼自己的寵,看到他們開心的樣子自己也開心。通了一週目就懶得啃英文了

  3. 牧場物語,在同事推薦下玩了,模擬經營農場,種菜、種果樹、養各種動物賣錢…玩了幾十個小時吧,玩不下去了…後面每天刷牛擠牛奶,擼雞一天就結束了…沒領悟到遊戲的樂趣

  4. 路易吉鬼屋,超級瑪麗裡的弟弟被拉到鬼屋裡探險的故事,樂趣就是看路易吉這個大寫的慫貨被各種鬼嚇尿…解密遊戲,其實挺好玩的

  5. 馬里奧賽車:和跑跑道具賽差不多,玩道具賽,道具比較少,賽道也少,難度也低。

  6. 勇氣默示錄:回合制RPG,還在龜速通關中,畫面很棒,3D的人物很Q,相當不錯的遊戲

然後說一些PC的:

  1. 俠客風雲傳:情懷!絕對的情懷!作為一個當年武林群俠傳的狂熱愛好者,俠客風雲傳我通關了至少6次,乞丐、東廠、盟主、霸圖、天王各種都通了一遍。湘雲還是一如既往的女神,希望徐大早日重製金庸群俠傳

  2. 仙6:這個戰鬥系統特麼什麼鬼…沒有玩下去的動力啊

  3. 堡壘(bastion):很精緻的遊戲,畫面唯美,歌曲好聽,劇情不長但很好玩。

  4. 進化之地2(evoland2):尼瑪一個遊戲能這麼玩我算是長見識了,集DQ、塞爾達傳說、超級瑪麗、拳皇、雙截龍、炸彈人、遊戲王、洛克人、1943等等於一身的遊戲也沒誰了

  5. 阿瑪拉王國:和老滾有點像,不過比老滾有打擊感,重要的是有WOW那種裝備系統。老滾的裝備系統是個鬼…可惜沒有老滾那麼多mod,畢竟少女卷軸

  6. 饑荒:這遊戲太特麼難了,一到冬天就死…得找個大神帶我

春節剁手買了昆特牌3和龍騰世紀,有時間玩一玩。最後重申一句:辣雞平臺,斂我錢財,頹我精神,耗我青春,害我單身

感情

看他們的總結都有這個,於是我加上了

光棍年數++

總結

前端發展太快,要學的太多。本來去年計劃學React Native的,結果只寫了個Demo…Electron也是隻跑了個HelloWorld…Node.js的伺服器也只是搭了個簡單的…canvas也是隻寫了一些小Demo。希望新的一年技術不掉隊,能夠多學點這些之前想學沒學的東西。另外希望能夠沉澱出自己的元件庫,以後快速搭建一個頁面也方便一些

相關文章