用Gulp、Babel等為瀏覽器構建ES6環境

劉健超-J.c發表於2016-07-15

ECMAScript 6 是 JavaScript 的最新版本,它帶來了很多新特性——一些是社群乞求已久的,一些是頗具爭議的。但不管你如何看待 ES6,都應該學習並使用它——因為就是這麼酷。由於能在伺服器端控制 JavaScript 版本,所以 ES6 在 node.js 或其它服務端框架執行良好,但在客戶端中則不盡人意了。從一個複雜的 angular 或 ember 應用到一個簡單的靜態頁面基本都含有幾行 jQuery 程式碼。

但為何在瀏覽器中應用 ES6 會如此艱難呢?因為對於客戶端的 JavaScript,它能否執行完全取決於瀏覽器對它的支援程度。而且這不是你所能控制的,也許你的瀏覽器支援 ES6,但更多瀏覽器的支援程度很低,甚至完全不支援。即使現代瀏覽器最終都支援 ES6,我們仍不得不對使用舊瀏覽器的使用者負責。所以距離我們能安全地編寫 ES6 程式碼,並讓瀏覽器直接執行的日子,還有很長一段時間。

難道這就讓我們向命運低頭嗎?難道註定要因為瀏覽器不得不接受舊版本的 JavaScript 嗎?不,我們不必接受這種限制!我們還有別的選擇——現在最佳的選擇是編寫 ES6 程式碼,並將其轉譯(transpile)或編譯為 ES5 程式碼(相容所有現代瀏覽器,如IE9+)。Babel 是主流的轉譯工具,它讓轉譯過程變得簡單,我們打算讓這過程自動化,所以我們甚至可以不用考慮上述的限制!

長話短說

如果你只想要簡潔的描述和本文所用到的純程式碼,下面就是:

我們將會建立一個 gulpfile 去監聽檔案的更改,並用 Babel 將 ES6 程式碼自動轉換到 CommonJS,然後用 Browserify 將 CommonJS 轉為 合法的 ES5。當然,我們也會新增額外的外掛,如 UglifyJS (為了最小化),source maps 和 livereload —— 因為這些工具都超級有用。

簡單粗暴,下面是完整的 gulpfile 檔案:

這沒你想象中糟糕吧!我們在上面嘗試了很多不同的東西。如果你有興趣學習它們,我會鼓勵你繼續往下閱讀,去了解它們是如何執行和為什麼會這樣執行的,這無疑會為瀏覽器構建出更可靠的 ES6 程式碼。

開始我們的 Gulpfile

我們將選擇 gulp 作為自動化構建工具。gulp 是基於 JavaScript 編寫的工具,它能執行特定任務,並監聽檔案是否被更改。當然,這取決於你在本地專案的目錄下的 gulpfile.js 配置檔案。除了 gulp,還有其它自動化構建工具(grunt 也是流行的構建工具),但由於 gulp 基於 node 的流(streams)實現,因此速度更快。

首先,我們初始化 package.json,並本地安裝 gulp(如果你未曾安裝,也可全域性安裝):

然後,建立一個空白的 gulpfile.js,並填充如下骨架:

上面沒什麼特別的地方。我們建立了空的 buildwatchdefault 任務。build 任務應包含所有構建 JavaScript 程式碼的邏輯。watch 任務監控 src/js 資料夾下的檔案是否被更改(構建後的檔案會放在 dist/js 下)。

執行以上這些任務:

到目前為止一切良好,對吧?下面就實際新增 ES6-to-ES5 構建處理。

執行 Babel 和 Browserify

在“長話短說”中我們簡單討論到,結合使用 babelbrowserify 將 ES6 程式碼轉成瀏覽器能執行的 ES5 程式碼。Babel 能將 ES6 轉為 CommonJS,而 CommonJS 是現今 JavaScript 最常用的模組模式(特別是在 node.js)。但現今瀏覽器仍不能識別 CommonJS。因此,我們需要使用 browserify 將 CommonJS 轉為合法的 ES5。有了這兩個工具,我們能走得更順利。

然而我們不能直接使用 babel。取而代之的是 babelify 庫,它是作為 browserify 的轉換器——這意味著在 browserify 編譯前,它會預處理 JavaScript。那我們先安裝這些包(package):

現在,為了構建 ES6 程式碼,我們將 gulpfile 檔案更改為:

這就是構建 JavaScript 程式碼的全部東西。我們簡單地告訴 browserify,我們想改變的檔案(此案例中,是 src/js/app.js),另外在程式碼被 browserify 處理(打包)前,使用預設值為 “es2015” 的 babel 對程式碼進行轉譯。自 babel v6.0.0 版本後,babel 需要指定預設值,然後根據預設值對 JavaScript 程式碼進行相應轉譯。 儘管這操作看起來有點麻煩,但這讓開發者對整個處理過程有更多的控制權。由於我們想根據 es2015 的標準進行構建處理,我們需要通過 NPM 安裝 babel-preset-es2015。

在檔案被 browserify 處理後,將它們打包進一個單獨檔案(此案例中,也只有一個檔案)。你可能想知道 vinyl-source-stream 是什麼。gulp 是基於 node 流(stream)的,更具體地說,是基於 vinyl streams 的,這是一種虛擬的檔案格式。Browserify 返回一個可讀的 stream,但不是 vinyl stream。因此我們必須用 vinyl-source-stream 對 stream 進行相應轉化,以確保 gulp 後續邏輯能繼續執行。這是一個額外的外掛,但它小巧且職責單一。

在 gulpfile 僅 20 行程式碼下,我們就能正式構建 ES6 程式碼為合法的 ES5 程式碼了。如果要編寫生產環境的 JavaScript 程式碼,那麼在這之前,還要 uglify(醜化壓縮)、source maps 和 livereload。

新增 Uglify、Source Maps 和 LiveReload

將 ES6  程式碼轉為合法的 ES5 程式碼只是一件事,但將其投入到生產環境則需確保程式碼是被壓縮的和擁有 source map 檔案。為了新增這些功能,我們要為 gulpfile 檔案新增以下工具:

  • UglifyJS:醜化並壓縮 JavaScript 檔案。
  • Source Maps:這會有助於為壓縮後的指令碼進行除錯。Source maps 將壓縮後的檔案程式碼對映到未壓縮檔案的具體位置。這對生產環境下的程式碼進行除錯(debugging)變得更容易了。當然,source maps 檔案只會在開發者工具的 console 視窗開啟時才會下載,所以普通使用者是不會下載它們的。
  • LiveReload:這工具在開發中特別有用。若其監聽的檔案發生變化時,它會自動重新整理你的瀏覽器。還有個比較受歡迎的替代工具是 BrowserSync 。

先新增 UglifyJS。我們需要安裝以下包(packages):

並修改 gulpfile 檔案:

我們新增了 gulp-uglify 和 vinyl-buffer。gulp-uglify 是 gulp 的一個外掛,它能壓縮 JavaScript 程式碼。但 vinyl-buffer 有何用呢?由於 gulp-uglify 現在不支援 stream,而支援 buffer。vinyl-buffer 能將 stream 轉為 buffer,讓 gulp-uglify 能正常執行。

最後階段了,讓我們為 gulpfile 新增 source maps 和 livereload。同樣地,先安裝包(packages):

OK,下面是我們最後一次修改 gulpfile 檔案了:

在壓縮 JavaScript 程式碼前,要先初始化 source map。這就能讓壓縮後的程式碼對映到原來的程式碼上。然後,將 source map 作為單獨一個檔案儲存在 maps/ 目錄下。現在,每當你想檢視壓縮後的 JS 程式碼所對應的行數時,source map 就能告訴你其相應程式碼在未壓縮檔案的所在行數,這無疑讓 debug 更輕鬆。

最後,讓 livereoload 監聽每個檔案的變化,讓每次構建迭代後都會重新整理瀏覽器。為了以最簡單的方式充分利用 livereload,可安裝相應瀏覽器外掛——我最喜歡的 Chrome 的外掛

就這樣吧!我們能正式用這 gulpfile 檔案了。

結語

如果你遵循上述步驟(或只是複製了文章開頭的 gulpfile 檔案),那麼你就擁有一個執行良好的、能將 ES6 程式碼轉譯成現代瀏覽器所識別的 ES5 程式碼的自動化構建系統(有一些不必要但很好的外掛,如最小化和 source map)。我知道這裡面有些知識點可能比較複雜,而如果你只是想為瀏覽器編寫 ES5 程式碼,你大可不必深究它。但掌握它,能讓你成為一個更好的開發人員。畢竟,你是在熟悉優雅的前端構建工具。

另外,我強烈建議你看看 ES6 文件,瞭解某些新特效能有效提高你的工作效率。就我個人而言,我對新的 class API 充滿怨言(因為 JavaScript 是基於原型鏈繼承的,而不是基於類。你可以看看我的相關 文章),但對模組模式系統(module pattern system)則喜愛有加,而且我打算經常使用它。如果你打算緊追語言的最新迭代版本,babel 和 gulp 能助你一臂之力。

打賞支援我翻譯更多好文章,謝謝!

打賞譯者

打賞支援我翻譯更多好文章,謝謝!

任選一種支付方式

用Gulp、Babel等為瀏覽器構建ES6環境 用Gulp、Babel等為瀏覽器構建ES6環境

相關文章