Prepack詳細介紹及微信小程序優化的(de)新思路 - 新聞資訊 - 雲南小程序開發|雲南軟件開發|雲南網站建設-昆明融晨信息技術有限公司

159-8711-8523

雲南網建設/小程序開發/軟件開發

知識

不(bù)管是(shì)網站,軟件還是(shì)小程序,都要(yào / yāo)直接或間接能爲(wéi / wèi)您産生價值,我們在(zài)追求其視覺表現的(de)同時(shí),更側重于(yú)功能的(de)便捷,營銷的(de)便利,運營的(de)高效,讓網站成爲(wéi / wèi)營銷工具,讓軟件能切實提升企業内部管理水平和(hé / huò)效率。優秀的(de)程序爲(wéi / wèi)後期升級提供便捷的(de)支持!

您當前位置>首頁 » 新聞資訊 » 小程序相關 >

Prepack詳細介紹及微信小程序優化的(de)新思路

發表時(shí)間:2021-4-30

發布人(rén):融晨科技

浏覽次數:59

前言

Prepack前幾個(gè)月剛出(chū)來(lái)的(de)時(shí)候已經得到(dào)了(le/liǎo)前端界的(de)大(dà)範圍關注,而(ér)在(zài)不(bù)久之(zhī)後又逐漸退出(chū)了(le/liǎo)人(rén)們的(de)視線。此時(shí)這(zhè)篇文章出(chū)來(lái)可能顯得有些滞後,個(gè)人(rén)還是(shì)比較看好它未來(lái)對于(yú)前端代碼預編譯優化所帶來(lái)的(de)收益。所以(yǐ)再詳細地(dì / de)介紹一下Prepack和(hé / huò)它給我帶來(lái)的(de)思考。

在(zài)前端技術叠代更新速度較快、前端人(rén)力寶貴的(de)情況下,面對新技術的(de)不(bù)斷湧現我們需要(yào / yāo)保持冷靜和(hé / huò)嚴謹的(de)态度去接受這(zhè)些新技術,所以(yǐ)一般在(zài)一個(gè)新技術湧現時(shí),我都會先弄清楚這(zhè)幾個(gè)問題再考慮是(shì)否要(yào / yāo)推動和(hé / huò)更叠現有的(de)技術棧:

  • 是(shì)什麽?

  • 解決了(le/liǎo)什麽問題?

  • 帶來(lái)了(le/liǎo)什麽新的(de)問題?

  • 新的(de)問題和(hé / huò)解決的(de)問題在(zài)目前場景下權重是(shì)怎麽樣的(de)?

  • 投入産出(chū)比如何?

帶着這(zhè)幾個(gè)問題進入正題。

一、什麽是(shì)Prepack

官網的(de)第一句是(shì):A tool for making JavaScript code run faster. —— 一個(gè)讓JavaScript代碼運行更快的(de)工具。

實際上(shàng)Prepack 就(jiù)是(shì)一個(gè)部分求值器(Partial Evaluator),代碼打包編譯時(shí)提前将計算結果放到(dào)編譯後的(de)代碼中,從而(ér)去除冗餘的(de)代碼(相對運行時(shí)來(lái)說(shuō),對應的(de)代碼邏輯本身并不(bù)是(shì)冗餘的(de)),而(ér)不(bù)是(shì)在(zài)代碼真正運行時(shí)才去求值。消除那些本可以(yǐ)在(zài)編譯階段完成的(de)運行時(shí)計算,一定程度上(shàng)減少了(le/liǎo)javascript資源包大(dà)小以(yǐ)及浏覽器運行js所耗費的(de)時(shí)間。詳情移步prepack.io/

另外要(yào / yāo)說(shuō)明的(de)是(shì),Prepack雖然能一定程度上(shàng)減少代碼量的(de)大(dà)小,但是(shì)Prepack開發團隊開發它的(de)初衷并不(bù)是(shì)爲(wéi / wèi)了(le/liǎo)減少代碼包大(dà)小,主要(yào / yāo)還是(shì)減少運行時(shí)的(de)時(shí)間消耗,代碼包的(de)大(dà)小減少算是(shì)一個(gè)附加收益。

二、工作原理

根據官網列的(de)幾個(gè)點依次進行詳細解釋。

  • Abstract Syntax Tree (AST) 抽象語法樹 (粒度) Prepack在(zài)抽象語法樹的(de)級别運行,使用Babel解析并生成JavaScript源代碼。 那什麽是(shì)“在(zài)抽象語法樹的(de)級别運行”? 将一種結構化語言編譯成另一個(gè)結構化語言的(de)代碼過程如下:

1、Parse,将代碼解析成抽象語法樹(AST);

2、對抽象語法樹(AST)進行遍曆(traverse)和(hé / huò)替換(replace) 生成新的(de) 抽象語法樹(AST);

3、Generator—— 根據新的(de) AST 生成編譯後的(de)代碼; “在(zài)抽象語法樹的(de)級别運行” 說(shuō)明了(le/liǎo)Prepack的(de)編譯流程,也(yě)說(shuō)明了(le/liǎo)編譯粒度。 比抽象語法樹粒度更細的(de)還有一個(gè)分析樹。 例如以(yǐ)下一個(gè)3+4 例子(zǐ)的(de)對比: 分析樹:

抽象語法樹:

概括來(lái)說(shuō),分析樹包含了(le/liǎo)記号序列和(hé / huò)推導的(de)各個(gè)步驟,拆分粒度更細;抽象語法樹則隻包含了(le/liǎo)關鍵的(de)信息,不(bù)知道(dào)具體的(de)文法和(hé / huò)運算符細節。 在(zài)抽象語法樹的(de)級别編譯,也(yě)就(jiù)是(shì)說(shuō)不(bù)用依賴于(yú)具體的(de)文法,不(bù)依賴于(yú)語言的(de)細節。也(yě)進一步說(shuō)明,原code經過語法分析後總是(shì)構造出(chū)相同的(de)抽象語法樹,再通過Prepack進行轉換處理成新的(de)抽象語法樹,Prepack不(bù)會對原有的(de)代碼文法和(hé / huò)處理邏輯帶來(lái)影響,對編譯器的(de)接口的(de)統一性也(yě)不(bù)會造成影響。 對編譯更多細節感興趣的(de)可讀 兩周自制腳本語言 (圖靈程序設計叢書)

  • Concrete Execution 具體執行 Prepack的(de)核心是(shì)一個(gè)JavaScript解釋器,它與ECMAScript 5幾乎完全兼容,而(ér)且緊密地(dì / de)保持與 ECMAScript 2016語言規範 的(de)一緻性,你可以(yǐ)将Prepack中的(de)解釋器視爲(wéi / wèi)完全參照JavaScript實現的(de)。

解釋器能夠跟蹤并撤銷包括所有對象Mutation在(zài)内的(de)結果,從而(ér)能夠進行推測優化(Speculative Optimization)。

  • Symbolic Execution 符号執行 除了(le/liǎo)對具體值進行計算外,Prepack的(de)解釋器還可以(yǐ)操作受環境相互作用影響的(de)抽象值。例如Date.now可以(yǐ)返回一個(gè)抽象值,你可以(yǐ)通過helper輔助函數(如__abstract())手動注入抽象值。Prepack會跟蹤所有在(zài)抽象值上(shàng)執行的(de)操作,在(zài)遇到(dào)分支時(shí),Prepack會執行并探索所有可能性。所以(yǐ),Prepack實現了(le/liǎo)一套JavaScript的(de)符号執行引擎。 以(yǐ)上(shàng)是(shì)官網的(de)翻譯,就(jiù)是(shì)符号可以(yǐ)代表一個(gè)根據環境不(bù)同而(ér)可變的(de)一個(gè)方法執行結果,例如以(yǐ)下例子(zǐ)中的(de)_0就(jiù)是(shì)這(zhè)樣的(de)一個(gè)抽象值,它無法提前計算,因爲(wéi / wèi)在(zài)不(bù)同的(de)浏覽器或運行時(shí)機下結果是(shì)不(bù)同的(de)。左邊編譯前代碼,x 存在(zài)if 判斷的(de)分支情況,Prepack會彙總所有的(de)分支情況進行優化編譯,如例子(zǐ)中将所有分支彙總(2個(gè)分支)替換成三目運算符表達。

  • Abstract Interpretation 抽象釋義 符号執行在(zài)遇到(dào)抽象值的(de)分支時(shí)會分叉(fork),Prepack會在(zài)控制流合并點加入分歧執行(Diverged Execution)來(lái)實現抽象釋義的(de)形式。連接變量和(hé / huò)堆屬性可能會得到(dào)條件抽象值,Prepack會跟蹤有關抽象值和(hé / huò)型域(Type Domain)的(de)信息。 還是(shì)之(zhī)前的(de)例子(zǐ),就(jiù)是(shì)抽象值“_0 ” 存在(zài)2個(gè)分支,Prepack底層會彙總分支情況,生成新的(de)抽象語法樹,在(zài)優化解析時(shí)(Generator)通過連接變量和(hé / huò)堆屬性,得到(dào)各分支下的(de)抽象值“_0 ”可能的(de)對應情況,并跟蹤相關情況的(de)信息計算出(chū)結果形成新的(de)代碼。

  • Heap Serialization堆序列化

這(zhè)裏的(de)堆序列化其實指的(de)是(shì)當全局代碼返回,初始化階段結束時(shí),也(yě)就(jiù)是(shì)在(zài)generator 過程中Prepack 會捕獲最終的(de)堆,按順序遍曆堆創建、鏈接堆中的(de)可及對象。堆中的(de)一些值可能是(shì)對抽象值進行計算的(de)結果,Prepack 将會根據這(zhè)些值生成執行計算的(de)代碼,最終組成新的(de)代碼。

總結一下Prepack的(de)工作過程:

  1. 開發的(de)代碼經過解析(Parse)形成抽象語法樹

  2. Transform時(shí)期預先計算出(chū)的(de)可求的(de)值,對存在(zài)受環境影響的(de)抽象值進行抽象釋義,轉換成新的(de)抽象樹

  3. Generate時(shí)期按順序遍曆堆進行符号執行和(hé / huò)跟蹤有關抽象值和(hé / huò)型域信息處理抽象值等,最終組成新的(de)代碼。

三、示例

官網(prepack.io/)有舉代表性的(de)例子(zǐ),這(zhè)裏不(bù)再詳述。還可以(yǐ)通過線上(shàng)的(de)Prepackprepack.io/repl.html将自己的(de)代碼輸入動态查看解析結果。

四、Prepack 引入會帶來(lái)的(de)問題

Prepack 帶來(lái)的(de)優勢是(shì)把 js 的(de) AST 編譯到(dào)更加低級的(de)語義,提前計算出(chū)值, 減少 js 代碼在(zài)浏覽器端初始化運行消耗的(de)時(shí)間,附帶收益是(shì)減少了(le/liǎo)代碼包的(de)大(dà)小,還可以(yǐ)與Closure Compiler 配合進一步縮小代碼包.,但同時(shí)也(yě)帶來(lái)了(le/liǎo)新的(de)問題:

  • 沒有官方統一、成熟的(de)方案支持打包集成到(dào)開發環境——需要(yào / yāo)開發者另辟蹊徑完成集成

  • 不(bù)能識别 document 和(hé / huò) window,會識别爲(wéi / wèi) undefined——浏覽器環境代碼利用Prepack存在(zài)較大(dà)局限性

  • 沒有完全支持浏覽器環境和(hé / huò)node.js環境——node代碼不(bù)能全面接入Prepack

  • 生成的(de)代碼沒有針對引擎做好優化——運行效率會存在(zài)變低的(de)情況

  • 存在(zài)一些尚未解決的(de)issues——會有更多的(de)“坑”需要(yào / yāo)踩

五、Prepack 未來(lái)規劃

目前Prepack仍處于(yú)早期開發階段,尚未準備好在(zài)生産環境中使用,官方建議僅嘗試使用,并且歡迎提供反饋以(yǐ)幫助修複錯誤。

Prepack團隊對未來(lái)的(de)規劃如下:

短期

  • 穩定現有功能集,用于(yú)預優化(Prepack)React Native代碼包

  • 集成React Native工具鏈

  • 根據React Native所用模塊系統的(de)假設來(lái)構建優化

中期

  • 進一步優化序列化(Serialization),包括:消除不(bù)暴露特性(identity)的(de)對象;消除未使用的(de)導出(chū)屬性,等等

  • 預優化每個(gè)函數、基本代碼塊、語句、表達式

  • 與ES6保持完全一緻

  • 支持廣泛的(de)模塊系統

  • 假設ES6支持某些功能,延遲完成或直接忽略Polyfill應用

  • 進一步實現Web和(hé / huò)Node.js環境中的(de)兼容性目标

  • 深入集成JavaScript虛拟機,改進堆反序列化過程,包括 :暴露“對象懶初始化”的(de)概念 - 以(yǐ)一種JavaScript無感知的(de)方式,在(zài)首次使用對象時(shí)對其進行初始化;通過專門的(de)字節碼提高普通對象創建的(de)編碼效率;将代碼分爲(wéi / wèi)兩個(gè)階段:1) 非環境依賴階段,虛拟機可以(yǐ)安全地(dì / de)捕獲并恢複生成的(de)堆;2)環境依賴階段,通過從環境中獲得的(de)值執行所有剩餘的(de)計算過程來(lái)拼湊具體的(de)堆,等等

  • 總結循環和(hé / huò)遞歸

長期 - 利用Prepack作爲(wéi / wèi)一個(gè)平台

  • JavaScript Playground - 通過調整JavaScript引擎體驗JavaScript特性,這(zhè)些引擎由JavaScript所編寫,托管在(zài)浏覽器中;你可以(yǐ)把它想象成一個(gè)“Babel虛拟機”,實現了(le/liǎo)不(bù)能被編譯的(de)JavaScript新特性

  • 捉Bug - 發現異常崩潰、執行問題……

  • 效果分析,例如檢測模塊工廠函數可能的(de)副作用或強制純淨注釋

  • 類型分析

  • 信息流分析

  • 調用圖推理,允許内聯和(hé / huò)代碼索引

  • 自動測試生成,利用符号執行的(de)特性與約束求解器(Constraint Solver)結合來(lái)計算執行不(bù)同執行路徑的(de)輸入

  • 智能模糊(Smart Fuzzing)

  • JavaScript沙盒 - 以(yǐ)不(bù)可觀察的(de)方式有效地(dì / de)測試JavaScript代碼

六、Prepack給微信小程序優化帶來(lái)的(de)新思路

從以(yǐ)上(shàng)Prepack帶來(lái)的(de)優勢和(hé / huò)問題來(lái)看,在(zài)普遍的(de)前端項目中使用的(de)話投入較大(dà)于(yú)産出(chū),目前必然是(shì)不(bù)适宜投入到(dào)項目中使用。

雖然目前Prepack尚未完善,但是(shì)開拓了(le/liǎo)一個(gè)新的(de)js代碼優化方向。減少 js 代碼在(zài)浏覽器端初始化運行消耗的(de)時(shí)間,這(zhè)對于(yú)提升用戶體驗來(lái)說(shuō)也(yě)是(shì)很關鍵的(de)點。例如 app本身的(de)啓動一般也(yě)比較占用時(shí)間,所以(yǐ)一般app 都會有一個(gè)啓動時(shí)的(de)廣告頁或靜态介紹頁,借此消除啓動時(shí)間較長給用戶帶來(lái)的(de)不(bù)良體驗。 App可以(yǐ)用廣告頁和(hé / huò)靜态介紹頁吸引用戶的(de)注意力。

最近在(zài)做小程序相關的(de)業務,微信小程序本質是(shì)app,在(zài)業務邏輯較重的(de)小程序也(yě)同樣存在(zài)啓動時(shí)間消耗帶來(lái)不(bù)良用戶體驗的(de)問題,但是(shì)卻不(bù)能以(yǐ)普通app的(de)解決方案來(lái)解決。因爲(wéi / wèi)微信本身比較注重用戶體驗,是(shì)一個(gè)擅長做減法且克制的(de)産品,加入廣告和(hé / huò)啓動頁不(bù)僅會影響用戶體驗還破壞産品的(de)“克制”性。 所以(yǐ)小程序的(de)啓動優化就(jiù)需要(yào / yāo)新的(de)解決思路,而(ér)Prepack就(jiù)剛好帶來(lái)了(le/liǎo)曙光。

微信小程序不(bù)存在(zài) document 和(hé / huò) window 對象,也(yě)非在(zài)node.js環境,不(bù)受它帶來(lái)的(de)問題所局限。可以(yǐ)通過腳本或其他(tā)集成方式将Prepack加入到(dào)打包流程中完成優化,也(yě)可降級處理部分主要(yào / yāo)文件發揮他(tā)的(de)作用。總之(zhī)和(hé / huò)微信小程序之(zhī)間存在(zài)着可能性和(hé / huò)可行性,後續會再出(chū)針對小程序和(hé / huò)Prepack的(de)實踐文章,感興趣的(de)同學可待續。

以(yǐ)上(shàng)純屬個(gè)人(rén)觀點,可能存在(zài)不(bù)足或錯誤之(zhī)處,歡迎指正。

作者介紹:雪婧,美團點評點餐團隊成員。

相關案例查看更多