扎穩(wěn)陣腳乖仇,再進(jìn)一步伐脖。
注意:原文發(fā)表于2017-12-31傍药,隨著框架不斷演進(jìn)昧谊,部分內(nèi)容可能已不適用尝偎。
給迫不及待的小伙伴們的快速入門:Sapper 文檔 和快速模板 starter template重归。
如果要列出完美的 Node.js Web 應(yīng)用框架的特征国夜,你可能會想到這些:
它應(yīng)該支持服務(wù)端渲染(SSR)减噪,能夠快速初始化并加載內(nèi)容,且對 SEO 友好;
應(yīng)用支持同構(gòu)為更通用的服務(wù)端和客戶端的代碼筹裕,這是當(dāng)下合情合理的趨勢預(yù)期醋闭;
客戶端應(yīng)用支持與服務(wù)端渲染的 HTML 混寫,綁定事件偵聽到現(xiàn)有的元素上朝卒,而非重新渲染它們目尖;
導(dǎo)航到其他頁面快如閃電;
離線及其他漸進(jìn)式 Web 應(yīng)用特性扎运,務(wù)必支持開箱即用瑟曲;
首個展示的頁面應(yīng)該按需僅加載必要的 JavaScript 和 CSS,這意味著框架支持路由級別的自動代碼分割豪治,及動態(tài)
import(...)
以實現(xiàn)更細(xì)粒度的手動控制洞拨;性能毫不妥協(xié);
絕佳的開發(fā)體驗负拟,使用熱模塊重載及其他輔佐搭配工具烦衣;
生成的代碼應(yīng)該易于理解和維護(hù);
框架應(yīng)該是淺顯易懂的掩浙,并且各個方面均可自定義花吟,沒有被 webpack 的配置鎖死在某個框架中,以及少之又少會“暗藏玄機(jī)”厨姚;
一個小時內(nèi)就可以將整個框架悉數(shù)習(xí)得衅澈,不論是久經(jīng)沙場的老手,還是初入門徑的新人谬墙。
Next.js 就十分接近這個理想值今布。
如果你與 Next 還素未謀面,我強(qiáng)烈推薦你去看 learnnextjs.com 上面的教程學(xué)學(xué)拭抬。
Next 提出了一個絕妙的想法:你應(yīng)用中所有的頁面都是 your-project/pages
目錄下的文件部默,每個文件都是一個 React 組件。
這是 Next 所有突破性設(shè)計的根基造虎。
找到某個頁面的代碼輕而易舉傅蹂,只需要在文件系統(tǒng)中查看即可,而不用去猜測組件的名稱是做什么的算凿。
同時份蝴,對于用什么樣的項目文件結(jié)構(gòu)這類雞毛蒜皮爭論不休的事情便一去不再了。
而 SSR(服務(wù)器端渲染)及代碼分割的結(jié)合更是從容不迫(不過 React 團(tuán)隊放棄了 Router澎媒,對那些嘗試 SSR 和代碼分割的人說搞乏,“祝你好運!”)戒努。
然而但是 —— 雖然 Next 這么美好,恕我出言不遜,Next 仍然美中不足:
-
Next 使用“rout masking”的技術(shù)來創(chuàng)建更為美觀的 URL(譬如
/blog/hello-world
替換掉/post?slug=hello-world
)储玫。這破壞了應(yīng)用程序結(jié)構(gòu)與目錄結(jié)構(gòu)一一對應(yīng)的保證侍筛,并迫使你維護(hù)這兩種形式之間轉(zhuǎn)換的配置。
-
你所有的路由都假定是“頁面”撒穷。
但通常你需要一些服務(wù)端路由匣椰,比如 301 重定向,或者專門為頁面提供數(shù)據(jù)的 API endpoint端礼,而 Next 沒有兼顧到這一點(
注:Next 新版本已經(jīng)具備 API 路由能力
)禽笑。你可以將處理這類情況的邏輯寫到
server.js
中,不過這樣會讓人感覺與頁面聲明的方式不太一致蛤奥。 要使用客戶端路由佳镜,鏈接不能是標(biāo)準(zhǔn)的
<a>
標(biāo)簽。 相反你必須使用框架指定的<Link>
組件凡桥,譬如在這篇用 markdown 寫的博客文章中的使用<Link>
是不可能的了蟀伸。
然而,真正的問題是缅刽,所有這些好處都是要付出代價的啊掏。
最簡單的 Next 應(yīng)用(僅展示一個“hello world”靜態(tài)文本的頁面),其 JavaScript 使用 gzip 壓縮后是 66kb衰猛,解壓后迟蜜,它占用 204kb,對于移動端來說這是一個非常龐大的代碼量了啡省,但這已是“最低消費”小泉。此時,性能是決定你的用戶是否會留下來的關(guān)鍵因素冕杠。
這事我們可以做得更好微姊!
編譯器即框架的逆襲
Svelte 提出了一個激進(jìn)的想法:如果你的UI框架壓根就不是框架,而是一個編譯器呢分预?如果它把你的組件編譯成獨立的 JavaScript 模塊會怎么樣呢兢交?
我們生成高度優(yōu)化的普通的 JavaScript,而不是使用 React 或者 Vue 這些類庫笼痹,其實它們對你的應(yīng)用一無所知配喳,因為框架必須提供一個通用的解決方案。
如果只生成應(yīng)用所需的代碼凳干,便可以完全避免了基于虛擬 DOM 方案的內(nèi)存和性能開銷晴裹。
JavaScript 領(lǐng)域正在朝著這種趨勢發(fā)展。
Stencil 是一個來自 Ionic 團(tuán)隊的深受 Svelte 啟發(fā)的輕量級框架救赐,它支持編譯為 Web Components涧团。
Glimmer 雖說并沒有編譯為獨立的 JavaScript(不深入地講了,要詳盡敘述其優(yōu)缺點的內(nèi)容都可以獨立成篇),但是團(tuán)隊正在圍繞將模板編譯為字節(jié)碼做了一些有趣的研究泌绣。
(React 現(xiàn)在也開始加入了這個陣營钮追,盡管他們目前研究的重點是優(yōu)化 JSX 的代碼,這與近年來 Angular阿迈、Reactive 和 Vue 所做的預(yù)優(yōu)化其實是異曲同工元媚。)
試想一下,如果我們破舊立新苗沧,嘗試使用這種新的方式作為新的起點刊棕,其結(jié)果又將如何?
Sapper 簡介
Sapper 或許可以回答這個問題(這個名字源于“工兵”待逞,它也是“Svelte 應(yīng)用程序制作器”的代名詞)甥角。
Sapper 是一個類似 Next.js 的框架,旨在滿足前文提及的 11 個理想標(biāo)準(zhǔn)飒焦,同時極大減少發(fā)送到瀏覽器的代碼量蜈膨。
它可以與 Express 的中間件兼容,這意味著它很容易理解和定制牺荠。
同樣的 “hello world” 使用 React 和 Next 需要 204kb翁巍,而使用 Sapper,僅有 7kb休雌。
隨著我們不斷探索其空間優(yōu)化的可能性灶壶,這個數(shù)字未來會進(jìn)一步下降,比如杈曲,除了處理客戶端路由的微型 Sapper 運行時以外驰凛,其余情況壓根不會為沒有交互的頁面發(fā)送任何 JavaScript。
有沒有一個更真實的示例看看呢担扑?
其實 RealWorld 就提供了這么一個開發(fā)中型項目的示例恰响。
展示這個 RealWorld 示例的交互式首頁,Sapper 的實現(xiàn) 僅需39.6kb(壓縮后 11.8kb)涌献。
整個應(yīng)用的尺寸是132.7kb(壓縮后為 39.9kb)胚宦,遠(yuǎn)遠(yuǎn)小于用來參照的 React/Redux 327kb(85.7kb)的實現(xiàn),即便 132.7kb 仍然是挺大的燕垃,不過關(guān)鍵是枢劝,得益于代碼分割,它會使人感觀上覺得跑起來非巢泛荆快速您旁。
代碼分割當(dāng)下早已蔚然成風(fēng)了,不過如果你的應(yīng)用使用了 React 或者 Vue 等傳統(tǒng)的框架轴捎,代碼分割就有一個“最低消費” —— 框架本身鹤盒,它可能占據(jù)整個應(yīng)用程序總尺寸的很大一部分蚕脏。
代碼分割也不是免費的 —— 譬如 React 等框架使用了代碼分割,它體積會更大昨悼。
不過如果使用的是 Svelte蝗锥,情況就大相徑庭跃洛。
當(dāng)然率触,尺寸大小問題也不過是開發(fā)的關(guān)注點之一罷了。
Svelte 寫的應(yīng)用同時具有極高的性能和內(nèi)存利用率汇竭,并且它包含了強(qiáng)大的功能葱蝗,而如果你選擇其他某個框架,搭配“小型”或者“簡易”的 UI 庫的話细燎,那么可能會犧牲掉這些東西两曼。
權(quán)衡
對于許多開發(fā)者來說,Sapper 最大缺點是什么呢玻驻?
“我還是喜歡 React悼凑,而且用慣用熟了¤邓玻” —— 其實會這么覺得户辫,也是無可厚非。
如果你屬于上面這個陣營的話嗤锉,那我建議你至少嘗試一下其他框架渔欢,很可能你會喜出望外!
Sapper 的 RealWorld 實現(xiàn)瘟忱,總共才 1,201 行代碼奥额,而其他框架需要 2,377 行,因為你可以使用非常簡潔访诱、易于表達(dá)的模板語法(只需要5分鐘就可以上手)垫挨。
你還能享受到范圍受限的局部CSS,內(nèi)置了對未使用的樣式自動刪除和最小化能力触菜,你也可以使用 Less 這樣的預(yù)處理器九榔。
這樣你就不用再依賴 Babel 了。
而 SSR 也是非常地快速玫氢,因為它只是字符串拼接而已帚屉。
我們最近還加入了 svelte/store,這是一個小型的全局狀態(tài)管理庫漾峡,它可以零引入就能在組件層次結(jié)構(gòu)之間同步狀態(tài)攻旦。
就算是最糟糕的情況下,你也會覺得自己的選擇是英明的生逸!
盡管如此牢屋,我們還是有值得權(quán)衡取舍之處且预。
你比方說,某些人對“模板語言”深惡痛絕烙无,難道你就是其中之一锋谐?
JSX 的支持者會說 “它其實就是 JavaScript” 這樣的話來刺激刺激你,React 最大的優(yōu)點就是它這種寫法有無限的靈活性截酷。
對于這種靈活性涮拗,React 有其自己的一套權(quán)衡邏輯,總之一言難盡迂苛,我們不在此展開過多討論三热。
接著聊聊生態(tài)。
特別是 React 周邊生態(tài) —— 開發(fā)工具三幻、編輯器集成就漾、輔助類庫、教程指南念搬、StackOverflow問答數(shù)量抑堡、框架自身的天坑以及工作機(jī)會等等……這些 React 簡直天下無敵。
誠然朗徊,如果你將“生態(tài)系統(tǒng)”視為選型的重要依據(jù)的話首妖,說明你已局限在個人技術(shù)的天花板了,勢必成為你技能上升的桎梏荣倾。
但它仍舊是當(dāng)下普惠開發(fā)者最重要的舉措悯搔。
路線圖
我們還不會發(fā)布 v1.0.0 版本,因為還有很多變數(shù)在里面舌仍。不過相信指日可待了妒貌,想必屆時會有許多令人興奮的可能性。(注:事實上 v1.0 可能永遠(yuǎn)都不會發(fā)布铸豁,作者對技術(shù)有了一番新的思考)
我認(rèn)為Web性能的下一個風(fēng)口將會是 “全應(yīng)用程序優(yōu)化”灌曙。
目前 Svelte 的編譯器是作用在組件級別,編譯器通過理解組件之間的邊界节芥,能夠生成更有效的代碼在刺。
React 團(tuán)隊的 Prepack 研究 也基于類似的想法面褐,Glimmer 團(tuán)隊也在這一塊做一些有趣的研究次乓。
Svelte 和 Sapper 可以很好地利用這些想法。
說起 Glimmer负间,我們可能會在 2018 嘗試借鑒他們“將組件編譯為字節(jié)碼”的想法相艇。
試想一下颖杏,像 Sapper 這樣的框架,可以根據(jù)應(yīng)用的特性來決定使用哪種編譯模式坛芽,它甚至可以為 JavaScript 的初始路由提供最快的啟動時間留储,然后為后續(xù)路由提供延遲的字節(jié)碼解釋器翼抠,從而實現(xiàn)啟動大小和應(yīng)用程序總大小的最佳組合。
不過大多數(shù)情況下获讳,我們希望 Sapper 的發(fā)展方向由用戶決定阴颖。
如果你樂于助我們一臂之力,并希望協(xié)助我們打造 Web 應(yīng)用的未來丐膝,歡迎加入 Github 和 Discord量愧。
< The End >