2016年裡做前端是怎樣一種體驗

發表於2016-10-10

問:最近我接手了一個新的Web專案,不過老實說我已經好久沒碰過這方面的程式碼了。聽說前端的技術棧已經發生了極大的變革,不知道你現在是不是仍然處於最前沿的開發者陣列?
答:準確來說,過去俗稱的寫網頁的,現在應該叫做Front End Engineer,我確實屬於這所謂的前端工程師。並且我才從JSConf與ReactConf面基回來,因此我覺得我覺得我還是瞭解目前Web前端領域最新的面貌的。

問:不錯不錯,我的需求其實也不復雜,就是從後端提供的REST風格的EndPoint來獲取使用者活動資料並且將其展示在前端介面上。並且需要以列表形式展示,同時,列表要支援篩選排序等操作,對了,還要保證前端資料和服務端保持一致。按照我現在的理解,我打算用jQuery來抓取與展現資料,你覺得咋樣?
答:不不不,現在估計已經沒多少人使用jQuery了吧。你可以試試React,畢竟這是2016年了啊。

問:額,好吧,那啥是React啊?
答:這是個非常不錯的源自Facebook的前端庫,它能夠幫你便捷地響應介面事件,同時保證專案層級的可控性與還說得過去的效能。

問:不錯不錯,那我是不是就可以用React來展示資料了呢?
答:話是這麼說沒錯,不過你需要新增React與React DOM依賴項到你的頁面中去。

問:等等,React不是一個庫嗎?為啥要新增兩個依賴呢?
答:不要急,前者是React的核心庫,後面呢算是DOM操作的輔助庫,這樣就能讓你用JSX來描述你的介面佈局了。

問:JSX?啥是JSX?
答:JSX是一個類似於XML的JavaScript語法擴充套件,它是另一種描述DOM的方式,可以認為是HTML的替代品。

問:等等,HTML咋啦?
答:都2016了,直接用HTML早就過時了。

問:好吧,那是不是我把兩個庫新增到專案中我就可以使用React了?
答:額,還要一些小的工具,你需要新增Babel到你的專案中,這樣你就能用了。

問:又是一個庫?Babel又是什麼鬼?
答:你可以把Babel認為是一個轉譯工具,可以將某個特定版本的JavaScript轉譯為任意版本的JavaScript。你可以選擇不使用Babel,不過那也就意味著你只能用煩人的ES5來編寫你的專案了。不過既然都是2016了,我建議你還是使用最新的ES2016+語法吧。

問:ES5?ES2016+?我已經迷茫了,ES5,ES2016+又是啥?
答:ES5是ECMAScript 2015的縮寫,也是現在被絕大部分瀏覽器所支援的JavaScript語法。

問:ECMAScript?
答:是的,你應該知道JavaScript最早於1995年提出,而後在1999年第一個正式版本定稿。之後的十數年裡JavaScript的發展一直很凌亂,不過經過七個版本之後已經逐步清晰了。

問:7個版本?那麼ES5與ES2016+又是第幾個版本呢?
答:是的,分別指第五個版本與第七個版本。

問:等等,那第六個版本呢?
答:你說ES6?估計我剛才沒有講明白,ECMAScript的每個版本都是向前相容的,當你使用ES2016+的時候也就意味著你在使用之前所有版本的所有特性啦。

問:原來是這樣啊,那為啥一定要用ES2016+而不是ES6呢?
答:是的,你可以使用ES6,不過如果你要使用async與await這些特性,你就要去用ES2016+了。否則你就還不得不去使用ES6的Generator來編寫非同步程式碼了。

問:我現在徹底迷糊了,我只是想簡單地從服務端載入些資料而已,之前只需要從CDN載入下jQuery的依賴庫,然後用Ajax方法來獲取資料即可,為啥我現在不能這麼做呢?
答:別傻了,每個人都知道一味使用jQuery的後果就是讓你的程式碼變得一團亂麻,這都2016了,沒人再想去面對這種頭疼的程式碼了。

問:你說的是有道理,那現在我是不是就把這三個庫載入進來,然後用HTML的Table來展示這些資料?
答:嗯,你可以選擇一個模組打包工具將這三個依賴庫打包到一個檔案中。

問:額,啥是模組打包工具啊?
答:這個名詞在不同的環境下指代也不同,不過在Web開發中我們一般將支援AMD與CommonJS的工具稱為模組打包工具。

問:AMD與CommonJS又是?
答:它們是用於描述JavaScript庫與類之間互動的介面標準,你有聽過exports與requires嗎?你可以根據AMD或者CommonJS的規範來定義多個JavaScript檔案,然後用類似於Browserify的工具來打包它們。

問:原來是這樣,那Browserify是啥呢?
答:Browserify最早是為了避免人們把自己的依賴一股腦放到NPM Registry中構建的,它最主要的功能就是允許人們將遵循CommonJS規範的模組打包到一個檔案中。

問:NPM Registry?
答:這是一個很大的線上倉庫,允許人們將程式碼與依賴以模組方式打包釋出。

問:就像CDN一樣?
答:還是有很大差異的,它更像一個允許人們釋出與下載依賴庫的中心倉庫。

問:哦,我懂了,就像Bower一樣啊。
答:對噠,不過2016年了,同樣沒啥人用Bower了。

問:嗯嗯,那我這時候應該從npm庫中下載依賴了是吧?
答:是的,譬如如果你要用React的話,你可以直接用Npm命令來安裝React,然後匯入到你的專案中,現在絕大部分主流的JavaScript庫都支援這種方式了。

問:嗯嗯,就像Angular一樣啊。
答:不過Angular也是2015年的流行了,現在像VueJS或者RxJS這樣的才是小鮮肉,你想去學習它們嗎?

問:不急不急,我們還是先多聊聊React吧,貪多嚼不爛。我還想確定下,是不是我從npm下載了React然後用Browserify打包就可以了?
答:是的。

問:好的,不過每次都要下載一大堆依賴然後打包,看起來好麻煩啊。
答:是的,不過你可以使用像Grunt或者Gulp或者Broccoli這樣的任務管理工具來自動執行Browserify。對了,你還可以用Mimosa。

問:Grunt?Gulp?Broccoli?Mimosa?我們到底在討論啥?
答:不方,我們在討論任務管理工具,不過同樣的,這些工具也是屬於2015年的弄潮兒。現在我們流行使用Webpack咯。

問:Makefiles?聽起來有點像是一個C或者C++專案啊。
答:沒錯,不過很明顯Web的演變之路就是把所有事情弄複雜,然後再回歸到最基礎的方式。估計不出你點你就要在Web中寫彙編程式碼了。

問:額,你剛才好像提到了Webpack?
答:是的,這是一個兼顧了模組打包工具與任務執行器的打包工具,有點像Browserify的升級版本。

問:嗷嗷,這樣啊,那你覺得哪個更好點呢?
答:這個因人而異了,不過我個人是更加偏好於Webpack,畢竟它不僅僅支援CommonJS規範,還支援ES6的模組規範。

問:好吧,我已經被CommonJS/ES6這些東西徹底搞亂了。
答:很多人都是這樣,多了,你可能還要去了解下SystemJS。

問:天哪,又是一個新名詞,啥是SystemJS呢?
答:不同於Browserify與Webpack 1.x,SystemJS是一個允許你將多個模組分封於多個檔案的動態模組打包工具,而不是全部打包到一個大的檔案中。

問:等等,不過我覺得按照網路優化規範我們應該將所有的庫打包到一個檔案中。
答:是的,不過HTTP/2快要來了,併發的HTTP請求已經不是夢。

問:額,那時候是不是就不需要新增React的依賴庫了?
答:不一定,你可以將這些依賴庫從CDN中載入進來,不過你還是需要引入Babel的吧。

問:額,我剛才好像說錯了話。
答:是的,如果按照你所說的,你需要在生產環境下將所有的babel-core引入,這樣會無端端增加很多額外的效能消耗。

問:好吧,那我到底應該怎麼做呢?
答:我個人建議是用TypeScript+Webpack+SystemJS+Babel這一個組合。

問:TypeScript?我一直以為我們在說的是JavaScript!
答:是的,TypeScript是JavaScript的超集,基於ES6版本的一些封裝。你應該還沒忘記ES6吧?

問:我以為我們剛才說到的ES2016+就是ES6的超集了。為啥我們還需要TypeScript呢?
答:因為TypeScript允許我們以靜態型別語言的方式編寫JavaScript,從而減少執行時錯誤。都2016了,新增些強型別不是壞事。

問:原來TypeScript是做這個的啊!
答:是的,還有一個就是Facebook出品的Flow。

問:Flow又是啥?
答:Flow是Facebook出品的靜態型別檢測工具,基於函數語言程式設計的OCaml構建。

問:OCamel?函數語言程式設計?
答:你沒聽過嗎?函數語言程式設計?高階函式?Currying?純函式?

問:我一無所知。
答:好吧,那你只需要記得函數語言程式設計在某些方面是優於OOP的,並且我們在2016年應該多多使用呦。

問:等等,我在大學就學過了OOP,我覺得挺好的啊。
答:是的,OOP確實還有很多可圈可點的地方,不過大家已經認識到了可變的狀態太容易引發未知問題了,因此慢慢的所有人都在轉向不可變資料與函數語言程式設計。在前端領域我們可以用Rambda這樣的庫來在JavaScript中使用函數語言程式設計了。

問:你是不是專門一字排開名詞來了?Ramda又是啥?
答:當然不是啦,Rambda是類似於Lambda的庫,源自David Chambers。

問:David Chambers?
答:David Chambers是個很優秀的程式設計師,他是Rambda的核心貢獻者之一。如果你要學習函數語言程式設計的話,你還應該關注下Erik Meijer。

問:Erik Meijer?
答:另一個函數語言程式設計領域的大神與佈道者。

問:好吧,還會讓我們回到React的話題吧,我應該怎麼使用React來抓取資料呢?
答:額,React只是用於展示資料的,它並不能夠幫你抓取資料。

問:我的天啊,那我怎麼來抓取資料呢?
答:你應該使用Fetch來從服務端獲取資料。

問:Fetch?
答:是的,Fetch是瀏覽器原生基於XMLHttpRequests的封裝。

問:那就是Ajax咯?
答:AJAX一般指僅僅使用XMLHttpRequests,而Fetch允許你基於Promise來使用Ajax,這樣就能夠避免Callback hell了。

問:Callback Hell?
答:是的,每次你向伺服器發起某個非同步請求的時候,你必須要新增一個非同步回撥函式來處理其響應,這樣一層又一層地回撥的巢狀就是所謂的Callback Hell了。

問:好吧,那Promise就是專門處理這個哩?
答:沒錯,你可以用Promise來替換傳統的基於回撥的非同步函式呼叫方式,從而編寫出更容易理解與測試的程式碼。

問:那我現在是不是直接使用Fetch就好了啊?
答:是啊,不過如果你想要在較老版本的瀏覽器中使用Fetch,你需要引入Fetch Polyfill,或者使用Request、Bluebird或者Axios。

問:來啊,互相傷害吧,你還是直接告訴我我還需要了解多少個庫吧!
答:這可是JavaScript啊,可是有成千上萬個庫的。而且不少庫還很大呢,譬如那個嵌了一張Guy Fieri圖片的庫。

問:你是說Guy Fieri?我聽說過,那Bluebird、Request、Axios又是啥呢?
答:它們可以幫你執行XMLHttpRequests然後返回Promises物件。

問:難道jQuery的AJAX方法不是返回Promise嗎?
答:請忘掉jQuery吧,用Fetch配合上Promise,或者async/await能夠幫你構造合適的控制流。

問:這是你第三次提到Await了,這到底是個啥啊?
答:Await是ES7提供的關鍵字,能夠幫你阻塞某個非同步呼叫直到其返回,這樣能夠讓你的控制流更加清晰,程式碼的可讀性也能更上一層樓。你可以在Babel中新增stage-3 preset,或者新增syntax-async-functions以及transform-async-to-generator這兩個外掛。

問:好麻煩啊。
答:是啊,不過更麻煩的是你必須先預編譯TypeScript程式碼,然後用Babel來轉譯await。

問:為啥?難道TypeScript中沒有內建?
答:估計在下一個版本中會新增該支援,不過目前的1.7版本的TypeScript目標是ES6,因此如果你還想在瀏覽器中使用await,你必須要先把TypeScript編譯為ES6,然後使用Babel轉譯為ES5。

問:我已經無話可說了。
答:好吧,其實你也不用想太多,首先你基於TypeScript進行編碼,然後將所有使用Fetch的模組轉譯為ES6,然後再使用Babel的stage-3 preset來對await等進行Polyfill,最後使用SystemJS來完成載入。如果你打算使用Fetch的話,還可以使用Bluebird、Request或者Axios。

問:好,這樣說就清晰多了,是不是這樣我就達到我的目標了?
答:額,你的應用需要處理任何的狀態變更嗎?

問:我覺得不要把,我只是想展示資料。
答:那還行,否則的話你還需要了解Flux、Redux等等一系列的東西。

問:我不想再糾結於這些名詞了,再強調一遍,我只是想展示資料罷了。
答:好吧,其實如果你只是想展示資料的話,你並不需要React,你只需要一個比較好的模板引擎罷了。

問:你在開玩笑?
答:不要著急,我只是告訴你你可以用到的東西。

問:停!
答:我的意思是,即使你僅僅打算用個模板引擎,還是建議使用下TypeScript+SystemJS+Babel。

問:好吧,那你還是推薦一個模板引擎吧!
答:有很多啊,你有對哪種比較熟悉嗎?

問:唔,好久之前用了,記不得了。
答:jTemplates?jQote?PURE?

問:沒聽過,還有嗎?
答:Transparency?JSRender?MarkupJS?KnockoutJS?

問:還有嗎?
答:PlatesJS?jQuery-tmpl?Handlebars?

問:好像最後一個有點印象。
答:Mustache?underscore?

問:好像更晚一點的。
答:Jade?DustJS?

問:不。
答:DotJS?EJS?

問:不。
答:Nunjucks?ECT?

問:不。
答:Mah?Jade?

問:額,還不是。
答?難道是ES6原生的字串模板引擎。

問:我估計,這貨也需要ES6吧。
答:是啊。

問:需要Babel?
答:是啊。

問:是不是還要從npm下載核心模組?
答:是啊。

問:是不是還需要Browserify、Webpack或者類似於SystemJS這樣的模組打包工具?
答:是啊。

問:除了Webpack,還需要引入工作管理員。
答:是啊。

問:我是不是還需要某個函數語言程式設計語言,或者強型別語言?
答:是啊。

問:然後如果用到await的話,還需要引入Babel?
答:是啊。

問:然後就可以使用Fetch、Promise了吧?
答:別忘了Polyfill Fetch,Safari目前還不能原生支援Fetch。

問:是不是,學完這些,就OK了?
答:額,目前來看是的,不過估計過幾年我們就需要用Elm或者WebAssembly咯~

問:我覺得,我還是乖乖去寫後端的程式碼吧。
答:Python大法好!

相關文章