JavaScript前端構(gòu)建工具原理的理解
前言
最近有幸在前端團(tuán)隊(duì)里面做了一次關(guān)于 webpack 的技術(shù)分享。在分享的準(zhǔn)備過程中,為了能讓大家更好的理解 webpack,特意對(duì)市面上以前和現(xiàn)在流行的構(gòu)建工具做了一個(gè)梳理總結(jié)。在整理和分享的過程中,獲益匪淺,對(duì)前端構(gòu)建工具有了新的認(rèn)識(shí)。在這里,將自己的一些思考總結(jié)寫出來,希望也能給到對(duì)構(gòu)建工具同樣感興趣的同學(xué)一點(diǎn)幫助。
本文的目錄結(jié)構(gòu)如下:
- 構(gòu)建工具的前世今生
- js 模塊化的發(fā)展史和構(gòu)建工具的變化
- 結(jié)束語
構(gòu)建工具的前世今生
談到構(gòu)建工具,大家首先想到的肯定就是 Webpack
以及現(xiàn)在最??的 Vite
。Webpack
,功能強(qiáng)大,生態(tài)豐富,從面世到今天,一直是很受大家歡迎;Vite
采用 unbundle
構(gòu)建模式,帶來了極致的開發(fā)體驗(yàn),給開發(fā)人員以新的選擇。
在這兩個(gè)構(gòu)建工具之外,還有其他的構(gòu)建工具,如和 Webpack
、Vite
類似的 Rollup
、Parcel
、Esbuild
,自動(dòng)化構(gòu)建工具 grunt
、gulp
,以及更加久遠(yuǎn)的 YUI Tool
。
這些工具的存在,構(gòu)成了前端構(gòu)建工具的發(fā)展史。
YUI Tool + Ant
YUI tool
是 07 年左右出現(xiàn)的一個(gè)構(gòu)建工具,功能比較簡(jiǎn)單,用于壓縮混淆 css
和 js
代碼,需要配合 java
的 Ant
使用。
當(dāng)時(shí) web 應(yīng)用開發(fā)主要采用 JSP
,還不像現(xiàn)在這樣前后端分離,通常是由 java 開發(fā)人員來編寫 js、css 代碼,前端代碼都是和后端 java 代碼放在一起的。因此前端代碼的壓縮混淆也就基于 java 實(shí)現(xiàn)了。
Grunt / Gulp
Grunt
/ Gulp
都是運(yùn)行在 node
環(huán)境上的自動(dòng)化工具。
在開發(fā)過程中,我們可以將一些常見操作如解析 html
、es6 代碼轉(zhuǎn)換為 es5
、less / sass 代碼轉(zhuǎn)換為 css 代碼
、代碼檢查
、代碼壓縮
、代碼混淆
配置成一系列任務(wù),然后通過 Grunt
/ Gulp
自動(dòng)執(zhí)行這些任務(wù)。
Grunt
和 Gulp
的不同點(diǎn):
使用
Grunt
的過程中,會(huì)產(chǎn)生一些中間態(tài)的臨時(shí)文件。一些任務(wù)生成臨時(shí)文件,其它任務(wù)可能會(huì)基于臨時(shí)文件再做處理并生成最終的構(gòu)建后文件,導(dǎo)致出現(xiàn)多次I/O
。Gulp
有文件流的概念,通過管道將多個(gè)任務(wù)和操作連接起來,不會(huì)產(chǎn)生臨時(shí)文件,減少了I/O
操作,流程更清晰,更純粹,大大加快了構(gòu)建的速度。
Webpack / Rollup / Parcel
Webpack
、Rollup
、Parcel
統(tǒng)稱為靜態(tài)模塊打包器
。
這一類構(gòu)建工具,通常需要指定入口 - entry
,然后以 entry
為起點(diǎn),通過分析整個(gè)項(xiàng)目?jī)?nèi)各個(gè)源文件之間的依賴關(guān)系,構(gòu)建一個(gè)模塊依賴圖 - module graph
,然后再將 module graph
分離為三種類型的 bundle
: entry
所在的 initial bundle
、lazy load
需要的 async bundle
和自定義分離規(guī)則的 custome bundle
。
這幾個(gè)構(gòu)建工具各有優(yōu)勢(shì):
Webpack
大而全,配置靈活,生態(tài)豐富,是構(gòu)建工具的首選。Parcel
號(hào)稱零配置,使用簡(jiǎn)單,適合不太需要定制化構(gòu)建的項(xiàng)目使用。Rollup
推崇ESM
標(biāo)準(zhǔn)開發(fā),打包出來的代碼干凈,適用于組件庫開發(fā)。
Vite / Esbuild
新一代構(gòu)建工具。
esbuild
, 基于 go
語言實(shí)現(xiàn),代碼直接編譯成機(jī)器碼(不用像 js 那樣先解析為字節(jié)碼,再編譯為機(jī)器碼),構(gòu)建速度比 webpack
更快。
vite
, 開發(fā)模式下借助瀏覽器對(duì) ESM
的支持,采用 nobundle
的方式進(jìn)行構(gòu)建,能提供極致的開發(fā)體驗(yàn);生產(chǎn)模式下則基于 rollup
進(jìn)行構(gòu)建。
js 模塊化的發(fā)展史和構(gòu)建工具的變化
javascript
語言設(shè)計(jì)之初,只是作為一個(gè)簡(jiǎn)單的腳本語言用來豐富網(wǎng)站的功能,并不像 java
、c++
那樣有 module
的概念,發(fā)展到現(xiàn)在的模樣,也經(jīng)歷了相當(dāng)長(zhǎng)的時(shí)間。
這段時(shí)間,可以簡(jiǎn)單歸納為:
青銅時(shí)代
- no module;白銀時(shí)代
- cjs、amd、cmd、umd、esm 相繼出現(xiàn);黃金時(shí)代
- 組件模塊化;
不同的時(shí)代,構(gòu)建工具也不同。
青銅時(shí)代
由于沒有 module
的概念, javascript
無法在語言層面實(shí)現(xiàn)模塊之間的相互隔離
、相互依賴
,只能由開發(fā)人員手動(dòng)處理。
相應(yīng)的,早期的 web
開發(fā)也比較簡(jiǎn)單甚至簡(jiǎn)陋:
- 通過
對(duì)象
、iife(或者閉包)
的方式實(shí)現(xiàn)模塊隔離
; - 通過手動(dòng)確定
script
的加載順序
確定模塊之間的依賴關(guān)系
。 jsp
開發(fā)模式,沒有專門的前端,html
、js
、css
代碼通常也由后端開發(fā)人員編寫。
為了節(jié)省帶寬
和保密
,通常需要對(duì)前端代碼做壓縮混淆
處理。這個(gè)時(shí)候,構(gòu)建工具為 YUI Tool
+ Ant
。
白銀時(shí)代
chrome v8
引擎 和 node
的橫空出世,給前端帶來了無限的可能。
同時(shí),javascript
的模塊化標(biāo)準(zhǔn)也有了新的發(fā)展:
commonjs
規(guī)范,適用于node
環(huán)境開發(fā)。amd
、cmd
規(guī)范,適用于瀏覽器
環(huán)境。umd
,兼容amd
、commonjs
,代碼可以同時(shí)運(yùn)行在瀏覽器
和node
環(huán)境。ESM
,即ES6 module
(這個(gè)時(shí)候還不是很成熟);
同時(shí)還出現(xiàn)了 less
、sass
、 es6
、 jslint
、 eslint
、typescript
等新的東西, 前端角色也開始承擔(dān)越來越重要的作用,慢慢的獨(dú)立出來。
有了 node
提供的平臺(tái),大量的工具開始涌現(xiàn):
requirejs
提供的r.js
插件,可以分析 amd 模塊依賴關(guān)系
、合并壓縮 js
、優(yōu)化 css
;less
/sass
插件,可以將less
/sass
代碼轉(zhuǎn)化為css
代碼;babel
,可以將es6
轉(zhuǎn)化為es5
;typescript
,將ts
編譯為js
;jslint
/eslint
,代碼檢查;- ...
這個(gè)時(shí)候,我們可以將上面的的這些操作配置成一個(gè)個(gè)任務(wù),然后通過 Grunt
/ Gulp
自動(dòng)執(zhí)行任務(wù)。
黃金時(shí)代
基于 Angular
、Vue
、React
三大框架和 Webpack
的使用,組件模塊化
成為前端開發(fā)的主流模式。同時(shí) ESM
規(guī)范也原來越成熟,被更多的瀏覽器支持。
以 React
和 Webpack
為例,通常我們會(huì)將一個(gè)應(yīng)用涉及到的所有的功能拆分為一個(gè)個(gè)組件,如路由組件、頁面組件、表單組件、表格組件等,一個(gè)組件對(duì)應(yīng)一個(gè)源文件,然后通過 Webpack
將這些源文件打包。在開發(fā)過程中,還會(huì)通過 Webpack
開啟一個(gè) local server
,實(shí)時(shí)查看代碼的運(yùn)行效果。
Webpack
是一個(gè)靜態(tài)模塊打包器,它會(huì)以 entry
指定的入口文件為起點(diǎn),分析整個(gè)項(xiàng)目?jī)?nèi)各個(gè)源文件之間的依賴關(guān)系,構(gòu)建一個(gè)模塊依賴圖 - module graph
,然后將 module graph
分離為多個(gè) bundle
。在構(gòu)建 module graph
的過程中,會(huì)使用 loader
處理源文件,將它們轉(zhuǎn)化為瀏覽器可以是識(shí)別的 js
、css
、image
、音視頻
等。
隨著時(shí)間的發(fā)展, Webpack
的功能越來越來強(qiáng)大,也迎來諸多對(duì)手。
Webpack1 | | Rollup 出現(xiàn)(推崇 ESM 規(guī)范,可以實(shí)現(xiàn) tree shaking, 打包出來的代碼更干凈) | | Webpack2(也實(shí)現(xiàn)了 tree shaking, 但是配置還是太繁瑣了) | | Parcel (號(hào)稱 0 配置) | | Webpack4(通過 mode 確定 development 和 production 模式,各個(gè)模式有自己的默認(rèn)配置) | | Webpack5(持久化緩存、module federation) Esbuild(采用 go 語言開發(fā),比 Webpack 更快) Vite(推崇 ESM 規(guī)范,開發(fā)模式采用 nobundle,更好的開發(fā)體驗(yàn))
豐富的構(gòu)建工具,形成了百花綻放的局面,可用于不同的情形,給開發(fā)人員帶來了越來越多的選擇。
結(jié)束語
目前來看,構(gòu)建工具在整個(gè)前端體系中占據(jù)的位置是越來越重要。只會(huì) Webpack 甚至不懂構(gòu)建工具已經(jīng)無法滿足日常開發(fā)。這就需要我們時(shí)時(shí)學(xué)習(xí),緊跟時(shí)代的腳步,了解最新的技術(shù),不斷前進(jìn)。
以上就是JavaScript前端構(gòu)建工具原理的理解的詳細(xì)內(nèi)容,更多關(guān)于JavaScript前端構(gòu)建工具的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
微信小程序 scroll-view實(shí)現(xiàn)上拉加載與下拉刷新的實(shí)例
這篇文章主要介紹了微信小程序 scroll-view實(shí)現(xiàn)上拉加載與下拉刷新的實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-01-01微信小程序中使元素占滿整個(gè)屏幕高度實(shí)現(xiàn)方法
這篇文章主要介紹了微信小程序中使元素占滿整個(gè)屏幕高度實(shí)現(xiàn)方法的相關(guān)資料,需要的朋友可以參考下2016-12-12Meta開源JavaScript內(nèi)存泄漏監(jiān)測(cè)工具M(jìn)emLab安裝使用
這篇文章主要為大家介紹了Meta開源JavaScript內(nèi)存泄漏監(jiān)測(cè)工具M(jìn)emLab安裝使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09