多場景靜態化編譯在兩輪SAAS用車實踐
背景
在用車saas化推廣相容小品牌用車的過程中,由於使用者互動、介面資料、業務流程在主品牌與小品牌之間存在差異性,導致程式碼分叉過多,影響可讀性與可編輯性;兩側用車能力存在部分混入,造成執行時程式碼過大;單一場景迭代容易干擾其他端側用車能力;後續還會擴充到端外用車,上述問題會繼續放大。
什麼是靜態化編譯
簡單來說,本文中「靜態化編譯」等同於程式執行中的「編譯時」,與「執行時」是相對的。也就是說主要在程式編譯階段,就得把相關程式碼打包進去產物中,來降低執行時的壓力。業務靜態化編譯,也就是在開發階段就把不同埠難以融合的業務邏輯以不同檔案的形式進行拆分,這裡的不同檔案是指不同的檔名字尾,檔名是相同的。來到編譯環節,透過webpack resolve plugin來對檔名及其字尾進行分叉與打包。
目標與價值
實現差異化場景隔離,共享核心用車能力;
多場景業務邏輯拆分,降低測試迴歸工作量;
降低研發、維護階段對於其他端額外影響和風險;
實現差異化打包構建,降低包體積,提高秒開率;
提高業務程式碼整潔性和獨立性;
為實現業務能力編排提供技術可能性。
使用場景
業務隔離
營銷能力、全域性通知欄、臨時鎖車、頭盔能力、響鈴尋車、更多業務…
樣式隔離
開鎖頁底部互動卡片、騎行中底部互動卡片、lottie動畫能力、popup彈窗能力
基礎能力隔離
藍芽能力 @hb/hb/bluetooth-taro、車碼識別能力 @hb/taro-core-monorepo/scan-parser、webView承載頁(主品牌使用平臺webView承載頁;小品牌獨立)
如何實現業務靜態化編譯
對於解決靜態化編譯,首先需要解決業務邏輯分叉問題;其次開發resolve外掛系統,對於分叉程式碼按照檔名字尾進行提取與編譯。
古早時期(未使用多場景靜態化編譯方案前)
上述圖片是業務程式碼中分別引入小品牌與主品牌全域性通知欄業務hook,只有在執行時才能根據當前環境是小品牌或主品牌來進行區分埠。這種方案的缺陷很明顯:執行時過大,直接影響包體積;程式碼分叉太多,影響可讀性。
上述圖片是構建後產物,不管當前環境是小品牌還是主品牌,其他場景邏輯都在在產物中,影響其體積。
當下及以後(使用多場景靜態化編譯方案後)
引入方式終結在資料夾之後,不用指定當前的具體檔名及其字尾。
這是構建小品牌場景後的產物,如果是主品牌的話,產物中字尾則為.../*.index.oho.ts。
目錄結構
上述圖片是老的目錄結構:只有透過檔名來進行區分不同業務型別:/mini.ts:小品牌;/oho.ts:主品牌
上述圖片是新的目錄結構:透過檔名字尾區分不同業務型別:*.mini.ts:小品牌包含了*.mini.alipay.ts,*.mini.weapp.ts;*.oho.ts:主品牌,*.oho.alipay.ts,*.oho.weapp.ts
基礎require的侷限性
只限於node環境;
只會解析.js .json .node檔案;
只會去解析檔案的完整路徑,不會解析資料夾;
解析檔案成功後返回值僅僅是一個路徑,沒有包含描述檔案等較為豐富的資料。
建立外掛
在建立外掛時一般會傳入source和target兩個引數:
source:外掛拿到Resolver.hooks['source']鉤子,並調tap或tapAsync新增處理函式事件。當解析器接收到了source事件時,會執行註冊的處理函式;
target:在處理完畢後,呼叫doResolve觸發一個target事件,交由下一個監聽target事件的外掛處理。
有了註冊事件tapAsync和觸發事件doResolve,各個外掛就可以像積木一樣連結起來。
Tapable介紹
簡介
Tapable 是一個類似於 Node.js 中的 EventEmitter 的庫,但它更專注於自定義事件的觸發和處理。透過 Tapable 我們可以註冊自定義事件,然後在適當的時機去執行自定義事件。這個和我們所熟知的生命週期函式類似,在特定的時機去觸發。
Tapable是一個由Webpack團隊維護的事件庫,它基於釋出訂閱模式實現事件處理。在Webpack中,Compiler和Compilation是Webpack的內建物件,它們都繼承於Tapable。透過使用Tapable,這些物件可以觸發事件,從而將不同的外掛串聯起來。這種機制使得Webpack可以在不同的編譯階段呼叫不同的外掛,從而影響編譯結果。
更具體地說,Tapable提供了一系列事件的釋出訂閱API,允許註冊事件,然後在適當的時機觸發這些註冊的事件進行執行。這些註冊的事件可以分為同步和非同步兩種執行方式。同步鉤子可以使用tap方法進行註冊,並透過call方法觸發執行。
總的來說,Tapable在Webpack中起到了一個核心的作用,它連線了Webpack的各個外掛,使它們能夠按照設定的邏輯和時機進行互動和執行,從而實現了Webpack的靈活性和擴充套件性。
分類
簡易demo
AsyncSeriesBailHook 是一個非同步序列、熔斷型別的 Hook。在序列的執行過程中,只要其中一個有返回值,後面的就不會執行了。這裡列舉該hook是因為後續resolve眾多plugin之中對於外掛系統中hook的註冊,全部都是使用該鉤子。
enhanced-resolve介紹
enhanced-resolve是webpack的一個核心包,用於增強webpack的模組解析能力,使其更容易找到所需的模組,從而提高webpack的效能和可維護性。
具體來說,enhanced-resolve可以為webpack解析器新增額外的搜尋路徑以及解析規則,讓webpack更好地解釋路徑和檔案,進而讓webpack更加專心地做模組打包相關的事情。
總的來說,enhanced-resolve對於webpack的作用是增強模組解析能力,提高效能和可維護性,使webpack更加專注於模組打包相關的工作。
流水線
不同的hooks之間透過Resolver中的doResolve串聯起來,一個hook中可以包含多個plugin。
外掛流轉
這裡描述了外掛在各個hooks上的註冊過程。可以將hooks理解成彈夾,plugin理解成子彈,外掛的註冊過程也就是給多個彈夾裝子彈的過程。
Resolver例項建立與解析
ResolverFactory.createResolver 根據 Resolver 類建立例項:myResolve (吃了配置,吐出物件myResolve)
myResolve 上 註冊並訂閱 大量的 hook (槍支彈藥貯備好,一刻激發)
呼叫 myResolver.resolve 方法開始進行 檔案解析 的主流程
內部透過 resolve.doResolve方法,開始呼叫第一個 hook: this.hooks.resolve
找到之前 訂閱 hook 的 plugin:ParsePlugin
ParsePlugin 進行初步解析,然後 透過doResolve 執行下一個 hook parsed-resolve,前期準備工作結束,鏈式呼叫開始,真正的解析檔案的流程也開始。
外掛裝配
整合靜態化編譯能力
安裝@hb/multi-scene-resolve-plugin_自定義編譯檔案npm包;
2. 專案配置檔案中引入上述npm包;
3. 替換taro內建multiPlatformPlugin外掛。
使用提示
統一介面的多場景檔案這一跨平臺相容寫法有如下三個使用要點:
不同端的對應檔案一定要統一介面和呼叫方式。
引用檔案的時候,只需要寫預設檔名,不用帶檔案字尾。
最好有一個平臺無關的預設檔案,這樣在使用 TS 的時候也不會出現報錯。
Q&A
1. 為啥必須用MultiSceneResolvePlugin外掛覆蓋Taro MultiPlatformPlugin自帶外掛,而不是並行處理?
由於MultiPlatformPlugin解析不了以下檔案路徑:/pages/riding/useHelmet.oho.weapp.ts,所以只能覆蓋Taro自身外掛;並且重複解析會提高編譯時間。
2. 外掛註冊的時機or鉤子一定是described-resolve和resolve嘛?不一定,只要是在檔名或字尾完成繫結前都可以,比如before-file,file等。
3. 為啥不能調整MultiSceneResolvePlugin外掛與MultiPlatformPlugin的順序,使其先執行前者?
MultiPlatformPlugin外掛Taro自帶外掛,整合在@tarojs/mini-runner和@tarojs/webpack-runner中,透過chain.merge合併自定義配置項,執行優先順序高於自定義。而且如果重置了,解析出帶有字尾的完整路徑後會影響MultiPlatformPlugin中對於處理檔案的篩選條件。
4. 為啥不編寫taro外掛而編寫webpack外掛?
taro外掛系統從3.6.3版本才系統性的支援,而且webpack外掛在系統中更為通用。
來自 “ 哈囉技術 ”, 原文作者:劉廣永;原文連結:https://server.it168.com/a2024/0304/6841/000006841318.shtml,如有侵權,請聯絡管理員刪除。
相關文章
- RocketMQ 在多 IDC 場景以及多隔離區場景下的實踐MQ
- Sermant在異地多活場景下的實踐
- 查詢提速 20 倍,Apache Doris 在 Moka BI SaaS 服務場景下的應用實踐Apache
- [譯] 用 Workers 讓靜態網站動態化網站
- Laravel頁面靜態化最佳實踐Laravel
- vue3編譯最佳化之“靜態提升”Vue編譯
- ClickHouse在自助行為分析場景的實踐應用
- Android NDK祕籍--編譯靜態庫、呼叫靜態庫Android編譯
- Taro編譯打包優化實踐編譯優化
- QCon-oCPX多目標多場景聯合建模在OPPO的實踐
- Visual Studio 2022 靜態庫編譯編譯
- 靜態WEB容器映象最小化實踐Web
- 解鎖「SOAR」在不同場景下的應用與實踐
- Linux下快速靜態編譯Qt以及Qt動態/靜態版本共存Linux編譯QT
- 有關Linux的可執行程式——動態編譯、靜態編譯、readelfLinux行程編譯
- 大伽「趣」說AI:在多個場景中的AI落地實踐AI
- go編譯靜態檔案到exeGo編譯
- 多場景多工學習在美團到店餐飲推薦的實踐
- 多容器動態化方案在遊戲SDK中的實踐遊戲
- 美團多場景建模的探索與實踐
- 靜態IP有哪些應用場景及該如何獲取?
- ARMS實踐|日誌在可觀測場景下的應用
- 淘寶個性化推薦中的多場景模型建模實踐模型
- 在AndroidStudio下使用cmake編譯出靜態連結庫的方法Android編譯
- IDA Pro for Mac(靜態反編譯軟體)Mac編譯
- IDA Pro for Mac 靜態反編譯軟體Mac編譯
- JIT-動態編譯與AOT-靜態編譯:java/ java/ JavaScript/Dart亂談編譯JavaScriptDart
- ☕【Java技術指南】「編譯器專題」深入分析探究“靜態編譯器”(JAVA\IDEA\ECJ編譯器)是否可以實現程式碼優化?Java編譯Idea優化
- TDengine的實踐場景
- 編譯提速最佳實踐編譯
- Serverless 在 SaaS 領域的最佳實踐Server
- TiDB 在咪咕雲原生場景下的實踐TiDB
- 多模態學習,帶來AI全新應用場景?AI
- Arm64架構下靜態編譯Nginx架構編譯Nginx
- 編譯靜態庫的方式使用spdlog和fmt編譯
- 交叉編譯場景分析(arm-linux)(四)--編譯readline和ncurses編譯Linux
- Flink CDC 在易車的應用實踐
- 私有化場景下大規模雲原生應用的交付實踐