Qwik簡介:一個超快的JavaScript框架
譯文譯者 | 李睿
審校| 孫淑娟
Qwik對響應(yīng)式用戶界面(UI)的工作方式進(jìn)行了大膽的反思。其核心前提是框架從頭開始構(gòu)建,以使用最少的JavaScript交付HTML,只要足夠的JavaScript就可以根據(jù)需要逐步引入交互性。
Qwik使用一種細(xì)粒度的模型來隔離應(yīng)用程序的分段,這些分段根據(jù)需要進(jìn)行水合。通過從基本原則出發(fā),Qwik可以實現(xiàn)其他無法實現(xiàn)的性能,并代表了前端JavaScript的另一種發(fā)展路徑。
Qwik的狀態(tài)
Qwik仍處于早期版本中,但它已經(jīng)推出了一段時間。在StackBlitz中有一個功能完整的示例,一個REPL游樂場和一個命令行工具。Qwik也已經(jīng)發(fā)展到支持對開發(fā)人員更友好的、類似響應(yīng)的語法。其底層仍然是一個高級的、獨一無二的響應(yīng)式引擎,它定義了狀態(tài)、模板和偵聽器的響應(yīng)邊界。
(1)可恢復(fù)性
Qwik使用了巧妙的服務(wù)器端和客戶端渲染的組合,以避免當(dāng)代框架在兩次(一次在服務(wù)器上,一次在客戶端上)執(zhí)行水合工作時重復(fù)。
正如Qwik的創(chuàng)建者M(jìn)isko Hevery所寫:Qwik的基本思想是它是可恢復(fù)的。它可以在服務(wù)器停止的地方繼續(xù)。在客戶端上只需要執(zhí)行最少的代碼。
或者換一種方式:讓服務(wù)器設(shè)置一個功能盡可能完整的HTML頁面,并允許客戶端執(zhí)行盡可能少的工作,以便繼續(xù)或恢復(fù)用戶的進(jìn)程。
帶有服務(wù)器端渲染(SSR)的響應(yīng)式框架中的典型流程是,首先在服務(wù)器上生成應(yīng)用程序的版本,然后將其發(fā)送到客戶端,客戶端渲染架式應(yīng)用程序。在這一點上,客戶端應(yīng)用程序接管了任務(wù),基本上必須再次引導(dǎo)同一應(yīng)用程序,以便將一個正常運行的客戶端連接在一起。
這個過程被稱為水合作用。有幾種巧妙的方法可以提高水合作用的效率,但Qwik放棄了這些方法,采用了一種名為“可恢復(fù)性”的新方法。
可恢復(fù)性意味著客戶機可以從服務(wù)器中斷的地方開始,而不必在客戶機上重新構(gòu)建應(yīng)用程序。
(2)交互時間
Qwik努力提升的指標(biāo)是交互時間(TTI)。這是指用戶向網(wǎng)頁發(fā)出請求和網(wǎng)頁響應(yīng)用戶交互之間的時間間隔。
加載時間(TTL)跟蹤客戶端完成接收所有所需數(shù)據(jù)所需的時間(因此是一個主要由文件大小和網(wǎng)絡(luò)速度決定的指標(biāo)),交互時間(TTI)考慮了現(xiàn)代JS框架的一個突出事實:一旦下載了數(shù)據(jù),客戶端就必須解壓縮,并執(zhí)行所需的JavaScript代碼,以使頁面具有交互性。
響應(yīng)式引擎需要做很多工作。引擎必須分解/解析所有標(biāo)記(如JSX),這些標(biāo)記通過變量和表達(dá)式來根據(jù)狀態(tài)的變化修改所顯示的內(nèi)容,以及根據(jù)代碼的行為。
另一端是一個簡單的HTML頁面。一旦瀏覽器掌握了它,頁面就可以開始移動了。這就是谷歌的PageSpeed Insights給Reddit.com這樣的頁面打32分(滿分100分),而原始HTML打100分的原因。
(3)閉包和偵聽器
Hevery將快速TTI的技術(shù)障礙描述為“死于封閉”。簡而言之,每個閉包必須維護(hù)封閉的信息世界這一事實意味著運行時應(yīng)用程序是一個急切加載代碼的“千層餅”。
Qwik采用的解決方案是使用與序列化監(jiān)聽器交互的全局事件監(jiān)聽器。換句話說,通用事件偵聽器用于編排按需實現(xiàn)的偵聽器,而不是下載并封裝在閉包中(不管它們是否實際執(zhí)行)。
Qwik的目標(biāo)是提供與HTML一致的響應(yīng)性,使其可序列化。根據(jù)標(biāo)記中封裝的信息,只需要一個很小的可執(zhí)行文件就可以在運行時顯示響應(yīng)性。
(4)代碼拆分并進(jìn)行微調(diào)
從另一個角度來看,Qwik正在執(zhí)行微調(diào)的代碼拆分。當(dāng)用戶需要時,它會根據(jù)需要加載交互代碼。如果有必要,捆綁器可以將這些塊打包成更大的塊。
Qwik從頭構(gòu)建,有三個獨立的函數(shù),用于創(chuàng)建狀態(tài)、模板和偵聽器。這允許框架只加載手頭任務(wù)所需的內(nèi)容。
狀態(tài)、模板和偵聽器這三個邊界一度由開發(fā)人員直接編碼。多虧了一個新的優(yōu)化器工具,它可以將類響應(yīng)式語法轉(zhuǎn)換為這些幕后邊界,可以得到一個相當(dāng)熟悉的DX。優(yōu)化器的工作是將實際代碼轉(zhuǎn)換為一組微小的存根,以便在必要時以小塊恢復(fù)應(yīng)用程序。
在優(yōu)化器中,模板和偵聽器用美元符號表示,而狀態(tài)由useStore鉤子處理。稍后將看到這個語法。
Qwik代碼的最終輸出看起來與其他框架不同,但是將Qwik與優(yōu)化器一起使用可以使其與其他框架相媲美。Qwik還推出了QwikCity,這是一套更高級的功能(例如路由),可以讓構(gòu)建完整的應(yīng)用程序更容易。
使用Qwik進(jìn)行操作
現(xiàn)在已經(jīng)理解了Qwik背后的概念,以下了解一下如何使用它進(jìn)行編碼。清單1顯示了用Qwik編寫的一個簡單組件。(這個例子來自Qwik FAQ。)
(1)清單1.簡單的Qwik組件
清單1顯示了Qwik中的一個組件被定義為一個匿名函數(shù),從Qwik庫傳遞到組件$函數(shù)中。每當(dāng)在Qwik中看到美元符號$時,這是在讓優(yōu)化器知道它需要做一些工作。Qwik將在應(yīng)用程序的美元符號部分設(shè)置其細(xì)粒度延遲加載邊界。
清單1中的onClick$是Qwik特殊語法的另一個例子。Qwik將使用一些技巧,在實際需要時只加載支持該功能所需的JavaScript。
清單1中的代碼將被優(yōu)化器分解為幾個片段,如清單2所示。
(2)清單2.編譯后的Qwik組件
在清單2中可以看到,Qwik沒有包含實際的組件功能,而是使用庫中的componentQrl()函數(shù)包含了一個引用。這個函數(shù)接受一個qrl()函數(shù),該函數(shù)使用匿名函數(shù)導(dǎo)入生成的組件文件。組件之間的這種關(guān)聯(lián)都是由優(yōu)化器在后臺管理的。開發(fā)人員不需要直接考慮這個問題。
QRL代表Qwik URL,這是Qwik引用將被延遲加載的方式。基本上,只要框架需要延遲加載某些內(nèi)容,它就會插入一個QRL,由特定于QRL的消費者包裝(比如組件、狀態(tài)或模板函數(shù))。
例如,組件QRL可以在子組件中找到的代碼的正確時刻加載,而父組件可以快速顯示其布局。與onClick處理程序類似:當(dāng)單擊發(fā)生時,可以對它進(jìn)行計算。
(3)Qwik CLI
該命令行工具可從npm獲得,具有所期望的基本功能,包括創(chuàng)建、開發(fā)模式和生產(chǎn)構(gòu)建。Qwik CLI使用Vite作為構(gòu)建工具??梢允褂胣pm create啟動新應(yīng)用程序qwik@latest,這將啟動一個交互式提示。
如果創(chuàng)建一個簡單的應(yīng)用程序并運行產(chǎn)品構(gòu)建,會得到一個dist目錄,在那里可以看到前面描述的所有獨立的可惰性加載的應(yīng)用程序塊。
Qwik調(diào)整
了解Qwik語法的一個有趣的地方是Qwik Cheat Sheet,它提供了Qwik和React代碼的并排比較。人們可能會發(fā)現(xiàn),這并不是一個很難的過渡。有些領(lǐng)域非常相似,有些則主要需要思維的轉(zhuǎn)變。更大的收獲是,Qwik中的響應(yīng)式系統(tǒng)與類響應(yīng)式框架完全不同,盡管優(yōu)化器實現(xiàn)了相似的語法。
Qwik對代碼拆分和延遲加載的創(chuàng)新方法為前端JavaScript提供了一種新的發(fā)展方式,而了解事情的發(fā)展將會很有趣。
原文標(biāo)題:??Intro to Qwik: A superfast JavaScript framework??,作者:Matthew Tyson