對(duì) JavaScript 構(gòu)建工具的 6 個(gè)預(yù)測(cè)
JavaScript 前端工具的生態(tài)系統(tǒng)充滿著變數(shù)和競(jìng)爭(zhēng),且只有最好的工具才會(huì)存活下來(lái)。
生產(chǎn)中使用的代碼與開(kāi)發(fā)中的有所不同. 在生產(chǎn)中,我們需要構(gòu)建一些能運(yùn)行得夠快、能管理各種依賴關(guān)系、能自動(dòng)執(zhí)行任務(wù)、能加載外部模塊等功能的包。而那些將開(kāi)發(fā)中的代碼轉(zhuǎn)為生產(chǎn)代碼的 JavaScript 工具我們就稱之為 構(gòu)建工具。
我們可以通過(guò)各個(gè)構(gòu)建步驟以及其重要性來(lái)解釋前端代碼需要被“構(gòu)建”的原因。
前端代碼構(gòu)建步驟
前端代碼的構(gòu)建涉及下面的四個(gè)步驟:
1、轉(zhuǎn)譯
通過(guò)轉(zhuǎn)譯,開(kāi)發(fā)者可以使用到語(yǔ)言最新、最熱門的更新和擴(kuò)展,并保持瀏覽器的兼容性等。下面是使用 Babel 的一個(gè)例子:
// 數(shù)組映射中的箭頭函數(shù)語(yǔ)法
const double = [1, 2, 3].map((num) => num * 2);
// 轉(zhuǎn)譯后
const double = [1, 2, 3].map(function(num) {
return num * 2;
});
2、分包
分包是處理所有 import
與require
語(yǔ)句的過(guò)程;找到相匹配的 JavaScript 代碼片段、包和庫(kù);將它們添加到適當(dāng)?shù)挠蛑?;然后將它們打包到一個(gè)大的 JavaScript 文件中。常用的分包器包括 Browserify、Webpack 與 Parcel。
3、壓縮
壓縮是通過(guò)刪除空白和代碼注釋來(lái)減少最終的文件大小。在壓縮過(guò)程中,我們還可以更進(jìn)一步添加代碼混淆步驟,混淆會(huì)更改變量名和方法名,使代碼變得晦澀難懂,因此一旦代碼交付到客戶端,它就不是那么容易能讓人讀懂。下面是一個(gè)使用 Grunt 的例子:
// 壓縮前
const double = [1, 2, 3].map(function(num) {
return num * 2;
});
// 壓縮后
const double=[1,2,3].map(function(num){return num*2;});
4、打包
完成上面的所有步驟之后, 我們需要將這些具有兼容性、且經(jīng)過(guò)分包、壓縮/混淆過(guò)的文件放置到某個(gè)地方。打包正是這樣一個(gè)過(guò)程,它將上述步驟所產(chǎn)生的結(jié)果放置到開(kāi)發(fā)者指定的某個(gè)位置上,這通常是通過(guò)打包器完成的。
前端構(gòu)建工具
前端工具及構(gòu)建工具可以分為以下幾類:
- 包管理: NPM、Yarn
- 轉(zhuǎn)譯器: Babel 等
- 打包器: Webpack、Parcel、Browserify
- 壓縮混淆: UglifyJS、Packer、Minify 等
JavaScript 生態(tài)系統(tǒng)中有各種各樣的構(gòu)建工具可以使用,包括下面的這些:
Grunt 和 Bower
Grunt 是作為命令行工具引入的,它僅提供一個(gè)腳本來(lái)指定和配置相關(guān)構(gòu)建任務(wù)。Bower 作為包管理器,提供了一種客戶端包的管理方法而緊追其后。這兩者,再加上 NPM,它們經(jīng)常在一起使用,它們看上去似乎可以滿足大多數(shù)的自動(dòng)化需求,但 Grunt 的問(wèn)題在于它無(wú)法提供給開(kāi)發(fā)者配置更復(fù)雜任務(wù)的自由,而 Bower 使開(kāi)發(fā)者管理的程序包是平常的兩倍,因?yàn)樗鼘⑶岸税⒑笈_(tái)包分開(kāi)了(例如,Bower 組件與 Node 模塊)。
Grunt 與 Bower 的未來(lái): Grunt 與 Bower 正在退出 JavaScript 工具生態(tài),但是還有一些替代品。
Gulp 和 Browserify
Gulp 是在 Grunt 發(fā)布一年半之后才發(fā)布的。但 Gulp 卻讓大家感到很自然、舒服。用 JavaScript 來(lái)寫構(gòu)建腳本與用 JSON 來(lái)寫相比更自由。你可以在 Gulp 的構(gòu)建腳本中編寫函數(shù)、即時(shí)創(chuàng)建變量、在任何地方使用條件語(yǔ)句 —— 但就這些,并不能說(shuō)讓我們的感覺(jué)變得特別自然和舒適,只能說(shuō)這只是其中的一個(gè)可能的原因。Browserify 和 Gulp 可以配合使用,Browserify 允許 NPM 包(用于后端 Node 服務(wù)器)被直接帶入到前端,就這一點(diǎn)已經(jīng)直接讓 Bower 廢了。而正是這種用一個(gè)包管理器來(lái)處理前后端包的方式讓人感到更自然和更好。
Gulp 的未來(lái): Gulp 可能會(huì)被改進(jìn),以便匹配當(dāng)前流行的構(gòu)建工具,但這完全取決于創(chuàng)造者的意愿。Gulp 仍在使用中,只是不再像以前那么流行了。
Webpack 和 NPM/Yarn 腳本
Webpack 是現(xiàn)代前端開(kāi)發(fā)工具中最熱門的寵兒,它是一個(gè)開(kāi)源的 JavaScript 模塊打包器。Webpack 主要是為處理 JavaScript 而創(chuàng)造的,但如果包含相應(yīng)的加載器,它也可以轉(zhuǎn)換 HTML、CSS 和圖片等前端資源。通過(guò) Webpack,你也可以像 Gulp 一樣編寫構(gòu)建腳本,并通過(guò) NPM/Yarn 來(lái)執(zhí)行它們。
Webpack 的未來(lái): Webpack 是目前 JavaScript 工具生態(tài)系統(tǒng)中最熱門的工具,最近幾乎所有的 JavaScript 庫(kù)都在使用 React 和 Webpack。Webpack 目前處于第四個(gè)版本,不會(huì)很快消失。(LCTT 譯注:Webpack 目前已經(jīng)發(fā)布了第五個(gè)版本了,且還在火熱更新中)
Parcel
Parcel 是一個(gè) Web 應(yīng)用打包器,于 2018 年推出,因其開(kāi)發(fā)者體驗(yàn)而與眾不同。Parcel 能利用處理器多核功能提供極快的打包性能,且還零配置。但 Parcel 還是一個(gè)新星,對(duì)于一些大型應(yīng)用,其采用率并不高。相比之下,開(kāi)發(fā)人員更喜歡使用 Webpack,因?yàn)?Webpack 有更廣泛的支持和可定制性。
Parcel 的未來(lái): Parcel 非常容易使用,如果你統(tǒng)計(jì)打包和構(gòu)建時(shí)間,它會(huì)比 Webpack 更快,而且它還提供了更好的開(kāi)發(fā)者體驗(yàn)。Parcel 沒(méi)有被大量采用的原因可能是它仍然比較新。在前端構(gòu)建工具的生態(tài)系統(tǒng)中,Parcel 的前景會(huì)非常光明,它將會(huì)存在一段時(shí)間。
Rollup
Rollup 是 JavaScript 的一個(gè)模塊分包器,它可將一小段代碼編譯為更大更復(fù)雜的庫(kù)或應(yīng)用。Rollup 一般建議用來(lái)構(gòu)建 JavaScript 庫(kù),特別是那種導(dǎo)入和依賴的第三方庫(kù)較少的那種庫(kù)。
Rollup 的未來(lái): Rollup 很酷,且正在被迅速采用。它有很多強(qiáng)大的功能,將在很長(zhǎng)一段時(shí)間內(nèi)作為前端工具生態(tài)系統(tǒng)的一個(gè)組成部分而存在。
了解更多
JavaScript 前端工具的生態(tài)系統(tǒng)充滿著變數(shù)和競(jìng)爭(zhēng),且只有最好的工具才能存活下來(lái)。在不久的將來(lái),我們的構(gòu)建工具將具有更少(或沒(méi)有)的配置,更方便的定制化,更好的擴(kuò)展性的和更好的構(gòu)建速度。
該用什么樣的構(gòu)建工具用于你的前端項(xiàng)目,你需要根據(jù)具體的項(xiàng)目需求來(lái)做出決定。至于選擇什么樣的工具,才是最合適自己的,大多數(shù)時(shí)候,需要我們自己作出取舍。