嘿,我最近接到一個 Web 項目,不過老實說,我這兩年沒怎麼接觸 Web 編程,據說 Web 技術已經發生了一些變化。據說你是這裏對新技術最瞭解的 Web 開發工程師?前端
準確地說,我是一名「前端工程師」。不過你算是找對人了。我對今年的技術別提多熟了,前端可視化、音樂播放器、能踢足球的無人機,你儘管問吧。我剛去 JS 大會和 React 大會逛了一圈,沒有什麼新技術是我不知道的。ios
厲害。是這樣的,我要開發一個網頁,用來展現用戶的最新動態。我想我應該經過後端接口獲取數據,而後用一個 table 來展現數據,用戶能夠對數據進行排序。若是服務器上的數據變化了,我還須要更新這個 table 。個人思路是用 jQuery 來作。ajax
可別用 jQuery !如今哪還有人用 jQuery 。如今是 2016 年了,你絕對應該用 React 。數據庫
哦,好吧, React 是什麼?npm
React 是一個很是厲害的庫, Facebook 的牛人寫的。它能讓頁面更可控,性能極高,並且使用起來很簡單。編程
聽起來確實不錯。我能用 React 展現服務器傳來的數據嗎?後端
固然能夠,你只須要添加兩個依賴,一個是 React ,一個是 React DOM瀏覽器
額,等下,爲何是兩個庫?服務器
React 是我說的庫, React DOM 是用來操做 DOM 的。由於這些 DOM 是用 JSX 寫的,因此須要一個專門的庫來操做。babel
JSX ? JSX 是什麼?
JSX 是對 JS 的擴展,它看起來跟 XML 差很少,能夠用來寫 HTML ,你能夠認爲 JSX 是一種更優雅的 HTML 寫法。
爲何不用 HTML 了……?
如今但是 2016 年啊,沒有直接寫 HTML 的。
對哦。好吧,加了這兩個依賴,是否是就能夠開始用 React 了?
不行哦。你須要添加 Babel ,而後才能用 React 。
Babel 是另外一個庫?
嗯, Babel 是一個轉譯工具, Babel 能把你寫的 JS 轉譯成任意版本的 JS 。你不必定非要用 Babel ,可是若是你不用的話,你就只能寫 ES5 的語法了。你知道的,如今是 2016 年,你怎麼能不使用 ES2016+ 的語法呢? ES2016+ 多麼酷啊。
ES5 是啥? ES2016+ 又是啥?我有點暈。
ES5 就是 ECMAScript 5 。大部分人都會使用 ES5 ,由於大部分瀏覽器都支持 ES5 。
ECMAScript 是啥……
你曉得的, JS 是 1995 年誕生的,而 JS 的標準是 1999 制定出來的。那時候 JavaScript 還叫作 Livescript,只能運行在網景的瀏覽器裏。那時真是混亂的年代,如今好了,咱們有了 JS 的 7 個版本的規範。
7 個版本?那 ES5 和 ES2016+ 是?
分別是第 5 個版本和第 7 個版本。
誒,那第六個版本呢?
你說的是 ES6 。每一個版本都是上一個版本的超集,因此你直接使用最新的 ES2016+ 就行了。
對哦。爲何不用 ES6 呢?
好吧,你能夠用 ES6 ,可是你就用不到 async 和 await 這麼酷的語法了。用 ES2016+ 比較好。用 ES6 的話你就只能用 generator 來控制異步任務流了。
不知道你在說什麼……你說了太多我聽不懂的名詞了。我只是想從服務器取點數據,我之前用 jQuery 挺好的,從 CDN 引入 jQuery ,我就能用 AJAX 獲取數據了,如今不能這樣作嗎?
大哥,都 2016 年了,沒人用 jQuery 好嗎。全部人都知道用 jQuery 只會造出「意大利麪條」同樣的代碼(不可維護)
好吧,因此我如今要加載三個庫才能獲取並展現數據。
對的,其實你能夠用「模塊管理器」把這三個庫「打包」成一個文件。
哦,什麼是模塊管理器……
不一樣平臺的模塊管理器不一樣啦。前端的模塊管理器通常指管理 AMD 或者 CommonJS 模塊的東西。
好……吧,什麼是 AMD 和 CommonJS ?
是兩個定義。咱們有不少方式來描述 JS 中多個庫或類的交互方式,好比 exports 和 requires 。你能夠按照 AMD 或者 CommonJS 的 API 來書寫 JS ,而後用 Browserify 將它們打包。
聽起來頗有道理。不過,什麼是 Browserify ?
是一個工具,用來將 CommonJS 形式的 JS 文件打包起來,放到瀏覽器裏運行。用 npm 倉庫的人發明了 CommonJS。
npm 倉庫是什麼……
是一個公開的倉庫,用於放置可依賴的模塊。
就像一個 CDN 麼?
不太同樣。它更像是一個數據庫,每一個人都能在上面發佈代碼,也能下載上面的代碼。你能夠在開發的時候將這些代碼下載到本地來使用,必要的時候也能上傳到 CDN。
聽起來像是 Bower !
是的,不過如今是 2016 年了,沒有人用 Bower 了……
好吧,我知道了,因此我應該用 npm 來安裝依賴。
對的。我舉個例子吧,若是你要使用 React ,你直接用 npm 安裝 React ,而後在代碼裏導入 React 就能夠了。大部分 JS 庫都能這麼安裝。
嗯, Angular 也能夠。
Angular 是 2015 年的事情了。不過今年 Angular 還沒死,還有 VueJS 和 RxJS 等等,你想學一學麼?
仍是用 React 吧。我剛纔已經學了夠多東西了。因此我用 npm 安裝 React 而後用 Browerify 來打包就行了?
是的。
這麼作看起來有點過於複雜啊。
確實。這就是爲何你應該使用 Grunt 、 Gulp 或者 Broccoli 這樣的任務管理工具,它們能自動運行 Browserify。不對,你如今能夠用 Mimosa 。
你在說什麼……
任務管理工具。不過咱們如今已經不用了。去年咱們還在用,後來改爲了 Makefiles ,可是如今咱們用的都是 Webpack。
我覺得只有 C/C++ 項目纔會用 Makefiles 。
是的,不過顯然咱們作 Web 開發的,喜歡先把事情搞複雜,而後迴歸到最樸素的狀態。每一年咱們都是這麼搞的。你就看着吧,過不了兩年,咱們就能夠在網頁上寫彙編了。
唉,你剛纔說的 Webpack 是什麼?
另外一種模塊管理工具,同時也是一個任務管理工具。你能夠認爲它是 Browserify 的增強版。
哦,好吧,爲何 Webpack 是增強版?
額,可能並無增強吧。 Webpack 告訴你應該如何管理你的依賴, Webpack 容許你使用不一樣的模塊管理器,不僅是 CommonJS ,甚至支持 ES6 模塊。
這都是哪跟哪啊,我都被繞暈了。
你們都被繞暈了,不過等 SystemJS 出來了就行了。
天吶,又一個 JS 庫,這是什麼鬼?
呵呵,不像 Browserify 和 Webpack 1.x , SystemJS 是一個動態的模塊加載器。
等下,剛纔不是說應該把全部依賴打包成一個文件嗎?
話是這麼說,可是等 HTTP/2 普及以後,不打包反而更好。
那爲何咱們不直接在頁面裏添加 React 的三個依賴文件呢?
不行。你能夠從 CDN 加載這些文件,可是你仍是要在本地用 Babel 轉譯。
唉,這麼鹺?
是的,你不能在生產環境上運行 babel ,你應該在發佈到生產環境以前,運行一系列的任務,包括壓縮、混淆、內聯化 CSS 、延遲加載 script ……
我懂了我懂了。既然我不能直接用 CDN ,那麼我應該怎麼作?
我會考慮用 Webpack + SystemJS + Babel 來轉譯 Typescript 。
Typescript ?咱們不是在說 JavaScript 嗎?!
Typescript 也是 JavaScript 呀,它比 JS 更好用,是 JS 的超集,它是基於 ES6 的,就是咱們剛纔談論的 ES6,你還記得吧。
ES2016+ 已是 ES6 的超集了,怎麼又冒出來一個 Typescript ?
是這樣的, Typescript 能讓咱們寫出「強類型」的 JS ,從而減小運行時的錯誤。 2016 年,咱們應該讓 JS 支持強類型了。
顯然 Typescript 能夠作到。
Flow 也能夠作到,區別是 Typescript 須要編譯,而 Flow 只是檢查語法。
唉, Flow 是?
是一個靜態類型檢查器,就是 Facebook 的人寫的。使用 OCaml 寫的,函數式編程很叼的。
OCaml ?函數式編程?
現在大牛都用這些東西,都 2016 年了,你懂的,函數式編程、高階函數、柯里化、純函數這些概念。
不知道你在說什麼。
一開始你們都不知道。這麼說吧,你只須要知道函數式編程比面向對象編程厲害, 2016 年咱們就指着函數式編程了。
等下,我大學裏學過面向對象編程,當時我以爲它還不錯。
Java 在被 Oracle 買下來以前也挺不錯啊。個人意思是,面向對象之前是不錯,如今依然有人用它,可是如今全部人都發覺狀態變換是很難維護的,因此你們都開始用「不可變對象」和函數式編程了。 Haskell 的人已經用這套東西用了好久了,不過幸運的是 Web 開發領域裏有 Ramda 這樣的庫,讓咱們用 JS 就能夠進行函數式編程了。
你剛剛是否是又拋出了幾個名詞? Ramnda 又是什麼?
不是 Ramnda ,是 Ramda ,跟 Lambda 表達式有點像。是 David Chambers 寫的庫。
誰?
David Chambers ,大神一個。 blablabla
我不得不打斷你一下了。這些東西看起來都不錯,可是我以爲它們都太複雜,並且不必。我只是想獲取數據而後展現,我很肯定這種狀況下我不須要掌握這些知識。
回到 React 吧,用 React 我怎麼從服務器獲取數據?
額, React 沒有提供這個功能,你只能用 React 展現數據。
服了啊。那我怎麼獲取數據?
你用 Fetch API 就能夠了。
啥玩意?這個 API 的名字很爛啊。
我也以爲是啊。 Fetch API 是瀏覽器提供的異步請求接口。
哦,那不就是 AJAX 。
AJAX 只是使用 XMLHttpRequest 對象,可是 Fetch API 可讓你用 Promise風格來發起異步請求,幫你擺脫「回調地獄」。
回調地獄?
是的,每次你發起一個異步請求,就得等待它響應。這時你就得在函數裏使用一個函數,這種嵌套調用就是回調地獄。
好吧。 Promise 解決了這個問題麼?
是的。用 Promise 來管理回調,你就能夠寫出更易讀的代碼,更容易測試的代碼。甚至能夠同時發起多個請求,而後等待它們所有返回。
Fetch 也能作到嗎?
是的。但前提是你的用戶使用了新版的瀏覽器,否則的話你就須要加一個 Fetch 的 「 polyfill 」,或者使用 Request 、 Bluebird 或者 Axios 這些庫。
天吶我到底須要多少個庫?
這是 JS ,同一件事情有上千個庫在作。咱們瞭解庫,並且咱們有最好的庫,咱們有海量的庫,要什麼有什麼。
你剛纔說的幾個庫都是幹什麼的?
這幾個庫操做 XMLHttpRequest 而後返回 Promise 對象。
好像 jQuery 的 ajax 方法作的是一樣的事吧……
從 2016 年起咱們就不用 jQuery 了。用 Fetch ,大不了加個 Polyfill ,要否則用 Bluebird 、 Request 或者 Axios 都行。而後用 await 和 async 管理 Promise ,這樣才能控制好異步任務。
這是你第三次說 await 了,那是什麼東西?
await 能讓你攔住一個異步調用,讓你更好地控制異步返回的數據,大大加強了代碼的可讀性。 await 很是好用,你只須要在 Babel 裏添加 stage-3 配置,或者添加 syntax-async-functions 和 transform-async-to-generator 插件就能夠了。
聽起來像是瘋了。
沒瘋。爲了使用 await ,把 Typescript 編譯以後再用 Babel 轉譯一道的人才是瘋了。
啥玩意? Typescript 不支持 await ?
下個版本就支持了。
我已經無話可說了。
你看其實很簡單。用 Typescript 寫代碼,用 Fetch 發起異步請求,全部代碼編譯成 ES6 ,而後用上 Babel 的 stage-3 配置項,把 ES6 轉譯成 ES5 。全部代碼用 SystemJS 加載。若是你用不了 Fetch ,就加個 polyfill ,或者用 Bluebird 、Request 或者 Axios ,這樣你就能夠用 await 來處理 Promise 了。
看了咱們對於「簡單」的理解是不一樣的。好吧,有了這些,我終於能夠獲取數據而後用 React 展現數據了,對吧?
你的網頁須要處理狀態變動嗎?
唔,不用吧。我只是想展現數據。
那就好,否則我就得跟你解釋 Flux ,以及 Flux 的一些實現,好比 Flummox、Alt 、 Fluxible 。不過說真的你應該用 Redux 。
你說的這些我就當耳旁風了。再說一次,我只想展現數據。
這樣啊,若是你只是想展現數據,其實你不須要 React 。你只須要一個模板引擎。
你逗我呢?
我只是告訴你你能夠用什麼技術。
別說了,真的。
我想說,即便只是用一個模板引擎,我仍是會用 Typescript + SystemJS + Babel 的。
我只是想在頁面上展現數據,你就告訴我用哪一個模板引擎就行了。
有不少,你用過哪個?
額,過久沒用了,不記得了。
jTemplates 、 jQote 仍是 PURE ?
額,不記得,還有別的麼?
Transparency? JSRender? MarkupJS? KnockoutJS? 這一個支持雙向綁定。
還有嗎?
PlatesJS? jQuery-tmpl? Handlebars? 還有些人在用。
有點像。有哪些跟最後一個比較像的?
Mustache, underscore? 我記得連 Lodash 都有一個模板引擎,不過這是 2014 年的事情了。
額,也許是再新一點的庫?
Jade? DustJS?
沒用過
DotJS? EJS?
沒用過。
Nunjucks? ECT?
沒用過。記不起來了,要是你的話,你用哪一個?
我應該會用 ES6 原生的模板字符串
我猜猜,只有 ES6 支持。
對的。
須要用 Babel
對的。
須要用 npm 安裝
對的。
須要用 Browserify 或者 Webpack ,或者 SystemJS
對的。
若是沒用 Webpack 的話,我還須要一個任務管理工具。
對的。
可是因爲我要用函數式編程和強類型語言,因此我首先要用上 Typescript 或者 Flow 。
對的。
若是我要用 await ,那我就必須用 Babel 轉譯。
對的。
而後我就能用上 Fetch 、 Promise 和各類炫酷的東西。
嗯,別忘了加上 Fetch 的 Polyfill ,由於 Safari 不支持 Fetch 。
你猜怎麼着,咱們就聊到這吧。我不作了,我不作 Web 了,我也不想再碰 JS 了。
沒事,過不了幾年,咱們都會用 Elm 或者 WebAssembly 了。
我要回後端去了,我受不這些變更、版本更新、編譯和轉譯了, JS 社區若是以爲有人能跟上它的腳步,那這個社區就是瘋了。
我理解你。我建議你去 Python 社區。
爲何?
據說過 Python 3 嗎?