Snowpack,新時(shí)代前端構(gòu)建的先鋒
大家好,我是三元同學(xué)。
今天給大家介紹一個(gè)非常厲害的前端構(gòu)建工具——Snowpack。也許你之前聽(tīng)說(shuō)過(guò)前端領(lǐng)域非常多的打包工具,諸如 Webpack、Rollup,或者Parcel,甚至是現(xiàn)在在前端圈大火的 Bundleless 構(gòu)建工具Vite,但大家也許并沒(méi)有注意到 Snowpack。
其實(shí)它在 2019 年 2 月就在開(kāi)源社區(qū)誕生了,可以說(shuō)是業(yè)界最早提出并實(shí)現(xiàn)的 Bundleless 方案,如今在社區(qū)已經(jīng)有了不小的影響力,Github 上的 star 已經(jīng)超過(guò)了兩萬(wàn),而尤大本人也承認(rèn)早期 Vite 的設(shè)計(jì)也確實(shí)受到了 Snowpack 的啟發(fā)。不管怎么說(shuō),Snowpack 本身是一個(gè)非常優(yōu)秀的方案,背后的開(kāi)發(fā)團(tuán)隊(duì)是一支非常值得 respect 的團(tuán)隊(duì),我想很有必要將這個(gè)方案分享給大家。
時(shí)代先鋒隊(duì)——Pika
Snowpack 的開(kāi)發(fā)團(tuán)隊(duì)名為Pika,團(tuán)隊(duì)的技術(shù)緊跟時(shí)代的最前沿,在開(kāi)發(fā) Snowpack 這個(gè)新時(shí)代前端構(gòu)建工具的同時(shí),也率先提出了Skypack這種造福大眾的針對(duì) ESM 格式第三方庫(kù)的 CDN 服務(wù)(后續(xù)再跟大家詳細(xì)介紹這個(gè)服務(wù)到底有多吸引人)。
他們有一個(gè)使命: 讓 Web 項(xiàng)目構(gòu)建速度加快 90%。
作為走在時(shí)代前沿的他們,始終貫穿著一句研發(fā)宗旨:
- You should be able to use a bundler because you want to, and not because you need to.
換句話說(shuō),在現(xiàn)在的 Web 開(kāi)發(fā)時(shí)代,打包不再是必需的選項(xiàng),而只是一種優(yōu)化的手段,不用打包也能運(yùn)行你的應(yīng)用?,F(xiàn)代 Web 構(gòu)建要變天了,未來(lái)即將進(jìn)入一個(gè) Bundleless(顧名思義,更少的打包,更快的構(gòu)建速度)的時(shí)代,Web 領(lǐng)域在經(jīng)歷之前一系列的工程化改革之后,現(xiàn)在即將又要迎來(lái)一場(chǎng)翻天覆地的革新浪潮,而 Snowpack 之父——Pika 團(tuán)隊(duì)就是跨時(shí)代的弄潮兒,Snowpack 就是 Pika 團(tuán)隊(duì)創(chuàng)造新時(shí)代而打響的第一槍!
Why?
Snowpack 為什么會(huì)誕生?Web 構(gòu)建為什么會(huì)進(jìn)入 Bundleless 的時(shí)代?為什么 Pika 團(tuán)隊(duì)寧愿傾其所有去改變當(dāng)下 Web 項(xiàng)目的構(gòu)建現(xiàn)狀?在真正介紹 Snowpack 之前,這些問(wèn)題,必須得弄清楚。
在很久很久以前,開(kāi)發(fā)前端網(wǎng)頁(yè),似乎并沒(méi)有現(xiàn)在這么繁雜的工具鏈和框架,僅僅寫(xiě)一些原生的 HTML 代碼、CSS 和一些 JavaScript 代碼,那個(gè)時(shí)候怎么啟動(dòng)項(xiàng)目?直接打開(kāi) HTML 文件!我改動(dòng)了代碼怎么看到更新?直接刷新網(wǎng)頁(yè)!一切看上去都是那么的絲滑,所見(jiàn)即所得,可以說(shuō)那個(gè)時(shí)候的前端,足夠開(kāi)門(mén)見(jiàn)山,足夠簡(jiǎn)單粗暴,簡(jiǎn)單得甚至讓人有些懷念。
直到后來(lái),隨著前端的邏輯越來(lái)越復(fù)雜,對(duì)模塊化的需求越來(lái)越強(qiáng)烈,逐漸出現(xiàn)了 CommonJS(2009 年)、AMD(2010 年)、UMD(2011 年)這些模塊規(guī)范,底層的規(guī)范出現(xiàn)并穩(wěn)定之后必然會(huì)有上層的工具來(lái)實(shí)現(xiàn),由此出現(xiàn)了一系列的工程化方案:
- 模塊加載器,比如 SeaJS
- 包管理器,比如 npm
- 打包器,比如 Browserify、Gulp、Webpack
更重要的是,09 的時(shí)候 Ryan Dahl 寫(xiě)出了一個(gè)叫 Node.js 的東西,給 JS 帶來(lái)了全新的可能,以前 Java、C++ 能寫(xiě)的工具,用 JS 照樣能寫(xiě)了! 也就是從這個(gè)時(shí)候開(kāi)始,前端開(kāi)始變復(fù)雜了,各種工具鏈開(kāi)始亂花漸欲迷人眼,尤其是在 2015 年 ESModule 標(biāo)準(zhǔn)的誕生,再次將工程化方案之爭(zhēng)推上風(fēng)口浪尖,最后的勝出者很明顯了,就是在座各位如今幾乎天天能遇到的Webpack、Babel,這兩個(gè)東西,甚至已經(jīng)成為了如今前端工程化的代名詞了。
Babel 不用多說(shuō),是鼎鼎有名的 JavaScript 編譯器,在讓人眼花繚亂的語(yǔ)法標(biāo)準(zhǔn)中,它能夠?qū)㈧`活地一份 JS 代碼從一種語(yǔ)法標(biāo)準(zhǔn)轉(zhuǎn)換到另一種語(yǔ)法標(biāo)準(zhǔn)。
Webpack 是干什么的呢?它給自己的定位其實(shí)很簡(jiǎn)單,就是一個(gè)模塊打包器。
它的理念是:萬(wàn)物皆模塊。
不管代碼里面依賴(lài)關(guān)系多復(fù)雜,按照它的模塊導(dǎo)入導(dǎo)出語(yǔ)法來(lái)寫(xiě),寫(xiě)完之后把入口扔給它,它給你理清所有的依賴(lài)關(guān)系,最后打包到一起,給你一份產(chǎn)物,甭管這份產(chǎn)物你能不能看得懂,你大可以放心,瀏覽器看得懂,并且代碼性能和安全性也都還不錯(cuò)。
當(dāng)然,作為打包器,Rollup包括Parcel現(xiàn)在也都是很亮眼的存在,不過(guò)在 Webpack 強(qiáng)大的生態(tài)和業(yè)界落地基礎(chǔ)面前,二位就相形見(jiàn)絀了。
但總體來(lái)說(shuō),對(duì)于這樣的打包器而言,一定是有潛在的性能風(fēng)險(xiǎn)的,因?yàn)樗臉?gòu)建時(shí)間是和項(xiàng)目的整體規(guī)模成正比的,也就是說(shuō),項(xiàng)目規(guī)模的變大難以避免構(gòu)建時(shí)長(zhǎng)不斷增加,現(xiàn)在的前端項(xiàng)目可以說(shuō)要多復(fù)雜有多復(fù)雜,你可以盡情地想象打包器的這種性質(zhì)帶來(lái)的后果。
果然,這一天還是來(lái)了。
五年前,我用 Webpack 打包,啟動(dòng)還挺快的。
五年后,我還是在用 Webpack 打包,團(tuán)隊(duì)多了 20 個(gè)人,代碼多了 20 萬(wàn)行,現(xiàn)在啟動(dòng)一次要 10 分鐘!代碼改動(dòng)一次,看到結(jié)果更新要等 30000 ms!😭
直到 2018 年的某一天,主流的瀏覽器 Chrome/Safafi/Firefox 開(kāi)始支持 ESModule,跟開(kāi)發(fā)者們說(shuō),你們只需要把入口代碼扔進(jìn)來(lái),我給你請(qǐng)求所有需要導(dǎo)入的模塊,你們不用再煞費(fèi)苦心寫(xiě)什么打包器把代碼放到一起了。
在這時(shí),Pika 團(tuán)隊(duì)登場(chǎng),向全世界宣告: 未來(lái)的曙光已經(jīng)出現(xiàn),想要擺脫當(dāng)下的困境,請(qǐng)跟著我們一起朝著光的方向奔跑!
這道曙光指的就是瀏覽器開(kāi)始支持 ESModule 標(biāo)準(zhǔn),他們務(wù)必堅(jiān)定地相信這件事情,并且由于 HTTP/2 的普及,以前將多個(gè)靜態(tài)資源打包到一起從而減少請(qǐng)求次數(shù)的性能優(yōu)化手段不再成為必須,所以打包這個(gè)過(guò)程也就不再必要。
本著這樣的信念和基礎(chǔ),一年之后他們宣布了 Snowpack 的誕生,新時(shí)代的第一份 Bundleless 方案終于問(wèn)世。
和 Webpack 的關(guān)系
一方面,與 Webpack 對(duì)比,Snowpack 的優(yōu)勢(shì)就在于它的構(gòu)建速度特別快。這種快主要體現(xiàn)在兩個(gè)方面:
開(kāi)發(fā)階段相當(dāng)于啟動(dòng)一個(gè) Dev Server,無(wú)需將業(yè)務(wù)代碼進(jìn)行打包,也就省略了一系列分析依賴(lài)、代碼打包的繁瑣過(guò)程,甚至可以直接秒起。
無(wú)論項(xiàng)目規(guī)模如何增加,構(gòu)建時(shí)間復(fù)雜度始終為O(1),不會(huì)隨項(xiàng)目規(guī)模不斷增長(zhǎng)。
可以看到,當(dāng)文件變更之后,對(duì)于 Webpack 來(lái)說(shuō),為了整體打包,它需要重新構(gòu)建依賴(lài)圖,但對(duì)于代表 Bundleless 的 Snowpack 則不是這樣,每次都是單文件編譯,構(gòu)建速度不再受限于項(xiàng)目規(guī)模,也帶來(lái)了文件改動(dòng)后極快的更新速度。
而另一方面,Snowpack 并不排斥 Webpack,在生產(chǎn)環(huán)境構(gòu)建階段,Snowpack 本身也是提供了插件機(jī)制來(lái)集成其它的打包器,并且官方提供了開(kāi)箱即用的插件 @snowpack/plugin-webpack 直接集成 Webpack。這也是相對(duì)于 Vite 更加靈活的地方,Vite 只能選擇 Rollup 進(jìn)行生產(chǎn)環(huán)境打包,但 Snowpack 可以直接不打包,也可以選擇集成任何一個(gè)打包器(Webpack、Rollup或Esbuild)進(jìn)行打包。
小結(jié)
這次我們仔細(xì)分析了 Snowpack 誕生的歷史背景和實(shí)現(xiàn)基礎(chǔ),相信你也對(duì) Bundleless 有了初步的認(rèn)識(shí)。當(dāng)然知道這些還遠(yuǎn)遠(yuǎn)不夠,關(guān)于 Snowpack 以及 Bundleless,有很多的細(xì)節(jié)需要展開(kāi),包括依賴(lài)預(yù)構(gòu)建、Streaming Imports、插件架構(gòu)、HMR 系統(tǒng)、服務(wù)端渲染支持等等,后續(xù)我們會(huì)逐漸從使用到內(nèi)部實(shí)現(xiàn),逐步深入 Snowpack 的方方面面,讓你一覽新時(shí)代構(gòu)建工具的風(fēng)采。