使用 CML 的渲染能力,需要集成對應平臺的 SDK。請在左側目錄中根據(jù)你需要接入的平臺來查看文檔。
CML iOS SDK 使用 Weex、React Native 與 WebView 作為基礎渲染引擎,提供了基礎的組件功能之外,還支持用戶擴展自己的功能組件。
CML 最低支持的 iOS deployment target 為:iOS 9.0 CML 使用Cocoapods進行管理,使用npm管理react_native。
組件名 | 依賴版本 | 備注 |
---|---|---|
Cocoapods | 1.3.1 | - |
npm | 最新版本即可 | - |
Weex SDK | 0.19.0.2 | - |
React Native | 0.57.6 | - |
React | 16.6.1 | - |
當 SDK 下載下來后,首先進入/chameleon-sdk-iOS/Chameleon/react_native,并運行npm install進行更新。(這也是 React Native 的更新辦法。)
接下來我們以 Demo 工程為例(要注意工程路徑位置,在工程實際配置中需要注意 :path 的內容)。
在 Podfile 中,寫入:
platform :ios, '9.0'
target 'Chameleon_Example' do
##CML pod 'Chameleon', :path => '../Chameleon/'
## 如果需要Weex,則寫入weex依賴。
pod 'WeexSDK', '~> 0.19.0.2'
## 如果需要react_native,則寫入react_native依賴。
pod 'React', :path => '../Chameleon/react_native/node_modules/react-native', :subspecs => [
'Core',
'CxxBridge', ## 如果RN版本 >= 0.45則加入此行
'DevSupport', ## 如果RN版本 >= 0.43,則需要加入此行才能開啟開發(fā)者菜單
'RCTText',
'RCTNetwork',
'RCTWebSocket', ## 這個模塊是用于調試功能的
]
pod 'yoga', :path => '../Chameleon/react_native/node_modules/react-native/ReactCommon/yoga'
pod 'DoubleConversion', :podspec => '../Chameleon/react_native/node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
pod 'glog', :podspec => '../Chameleon/react_native/node_modules/react-native/third-party-podspecs/GLog.podspec'
pod 'Folly', :podspec => '../Chameleon/react_native/node_modules/react-native/third-party-podspecs/Folly.podspec'
end
將 podfile 保存,并運行 pod install。
解決辦法:刪除 工程->Build Phrases->[CP] Copy Pods Resources->Output files下的 copy 路徑。
描述 | 作用 |
---|---|
CML | SDK 源碼與依賴文件夾 |
Example | react_native 依賴 |
####CMLsdk_src
目錄 | 功能描述 |
---|---|
CMLSDKEngine 類 | 初始化 SDK、注冊自定義的 Module 等功能 |
CMLCommon | CML 抽象層。抽象了基礎的渲染頁面、緩存、配置、預加載等功能。 |
CMLReactNative | 針對 ReactNative 額外配置的部分 |
CMLWeex | 針對 Weex 額外配置的部分 |
CMLWeb | 針對 WebView 額外配置的部分 |
當 Bundle 下載失敗、渲染出現(xiàn)嚴重錯誤時,會自動降級至 H5。 降級設計圖
當 H5 渲染失敗時,倘若設置了默認的本地 bundle,會使用本地 bundle 進行降級。
當渲染出現(xiàn)錯誤時,F(xiàn)E 可以通過 JSBridge 通知客戶端觸發(fā)降級。
使用+ (void)registerModule:(NSString *)moduleName className:(NSString *)className;注冊自己的擴展。
module 是 Native 提供給前端頁面調用的,完成一組操作的方法集合,用于擴展 Native 的能力。在 CML 頁面中,開發(fā)者引入相關 js 庫后即可調用 Module 中的方法。
import bridge from 'chameleon-bridge';
// 主動調用客戶端方法
export function sayHello() {
bridge.callNative(
'moduleDemo', // 模塊名
'sayHello', // 方法名
{}, // 參數(shù)
res => {} // 回調方法
);
}
Module 的使用分兩種情況,一種是使用 CML SDK 內置的 Module,一種是用戶自定義實現(xiàn)自己的 Module。
內置的 Module 在 js 前端代碼里直接使用即可,目前內置的 Module 有:
API 文檔里描述的能力,部分實現(xiàn)就是由上述 Module 支撐的。
示例可參看CMLStorageModule 示例
注冊自己的 Module 關聯(lián)文件:
詳細說明
預加載和緩存都是為了節(jié)省 JSBundle 下載的時間,加快 UI 的渲染。
預加載是將下載 JSBundle 的動作提前完成,在需要用到的時候直接從本地讀取并渲染。實際項目使用中,可以將需要預加載的 url 配置到預加載地址列表里,在 app 啟動時提前從服務端獲取,通過 CML SDK 提供的預加載能力提前下載下來。
對于沒有預加載的 JSBundle 在渲染前需要先下載,下載完成后 CML SDK 會緩存此 JSBundle,下次渲染同一個 JSBundle 時,如果此 JSBundle 沒有更新則不會下載新的,達到節(jié)省時間和流量提升渲染速度的目的。
CMLCache 是一個對 js 進行下載、緩存的一個模塊,根據(jù)協(xié)議來實現(xiàn) js 增量更新功能。主要有以下內容
|
|——CMLWeexCache 緩存模塊接口類
|——CMLCacheInfo JsBundle文件緩存實現(xiàn)邏輯
|——CMLCacheItem jsBundle文件內存對象,描述每一個jsBundle文件的緩存狀態(tài)
|——CMLConfig 配置類,業(yè)務方可通過這個類設置是否開啟緩存功能、預加載js路徑、緩存大小限制、默認兜底頁鏈接等
對 jsBundle 進行預加載、獲取、緩存的處理對外接口。
在該文件里,我們將拿到的 URL 解析出此頁面需要加載的 jsbundle 標識,然后根據(jù) jsBundle 標識來檢測是否在本地已預加載,如果此 jsBundle 已預加載成功,則直接讀本地緩存渲染;否則先從網(wǎng)絡下載 jsBundle,然后渲染并緩存本地。
后續(xù)我們將支持在一個 URL 中下發(fā)多段 jsbundle 標識,每段 jsbundle 標識代表這個頁面的一部分,然后在根據(jù)每段 jsbundle 標識,分別從本地緩存里獲取去尋找對應的 js 代碼,如果不存在則從網(wǎng)絡去下載這一段 jsBundle 并保存在本地,然后 SDK 中會將最終得到的多段 jsBundle,組合成一個完整頁面的 jsBundle 加載出來。
jsBundle 的內存管理器,是加載、獲取、緩存等處理的實際操作者。 對本地緩存 jsBundle 的 maxSize 加以限制,如果超過 maxSize,則優(yōu)先清除老的 jsBundle 緩存
對 jsBundle 的封裝,包括 jsBundle 文件在本地存儲的路徑、內存索引;CMLCacheInfo 就是通過 CMLCacheItem 來對 jsBundle 進行操作。
緩存相關配置
緩存相關配置定義位于 CMLWeexConfig (CMLConfig)
//設置服務類型為weex
[CMLEnvironmentManage chameleon].serviceType = CMLServiceTypeWeex;
//設置默認錯誤web鏈接
[CMLEnvironmentManage chameleon].weexService.config.defaultErrUrl = @“defaultErrUrl”
Chameleon 功能和緩存功能都是默認開啟的,如果有特殊需要,可以手動關閉;另外在這里還有緩存限制 maxSize、緩存目錄等配置
[CMLEnvironmentManage chameleon].weexService.config.isFeatureAvailable = NO;
[CMLEnvironmentManage chameleon].weexService.config.isEnableCacheFeature = NO;
預加載
//設置預加載 URL 列表
[CMLEnvironmentManage chameleon].weexService.config.prefetchContents = @[@"http%3A%2F%2F172.22.139.32%3A8000%2Fweex%2Fchameleon-bridge.js%3Ft%3D1546502643623"];
//開啟預加載
[[CMLEnvironmentManage chameleon].weexService setupPrefetch];
獲取加載 jsBundle 的 URL
CMLWeexCache *cache = (CMLWeexCache *)[CMLEnvironmentManage chameleon].weexService.cache;
//在緩存中獲取JSBundle的URL(本地有緩存則獲取到本地緩存的URL,本地無緩存則獲取到遠端的URL)
[cache getBundleCacheOfJSBundleUrl:self.bundleUrl completion:^(NSString *url, NSDictionary *parameter) {
//加載jsBundle
[self.render renderWithURL:[NSURL URLWithString:url] options:@{@"query" : [param copy]} data:nil];
}
CML Android SDK 是 CML 整體框架的一部分,主要任務是完成 CML JsBundle 在 Android 端的本地渲染。SDK 底層采用 Weex 作為渲染引擎,同時擴展一些一般工程通用的基礎能力,如緩存能力、降級能力等。
項目一級目錄結構如下:
|+ app SDK使用示例
|+ cmlsdk SDK接入層,抽象 CML 引擎能力、實現(xiàn)通用擴展能力
|+ cmlweex 包裝 Weex 渲染引擎
|+ cmlweb 包裝 Web 渲染引擎
|+ js-bundle-mgr 實現(xiàn) js bundle 預加載、緩存
|+ rich-text-component 富文本組件
|+ sdk-image 圖片選擇、圖片拍攝組件
|+ sdk-location 位置組件
cmlsdk 模塊單獨拿出來看下目錄結構:
|- cmlsdk
|+ adapter 定義了擴展能力的接口以及默認實現(xiàn),無默認實現(xiàn)的能力需要第三方項目根據(jù)自己的實際業(yè)務需求去實現(xiàn)
|+ bridge 定義了 js 和 Native 通信的接口,實現(xiàn)協(xié)議相關的處理能力,以及實現(xiàn)了協(xié)議層使用入口
|+ bundle js bundle 相關定義,目前只有一個類用來描述 js bundle 相關信息
|+ common 通用能力的基礎封裝類
|+ container 渲染容器的抽象能力定義
|+ extend CML 提供的一些能力
|+ Module 擴展能力管理,收集 sdk 默認提供的以及第三方用戶自己實現(xiàn)的 Module,根據(jù) bridge 層指令執(zhí)行具體某個 Module 的某個 method
|+ utils 工具類集合
|+ widget 自定義的widget,目前只有一個 title bar,用做 webview 渲染容器的action bar
|- CmlBaseLifecycle 生命周期的接口定義
|- CmlConstant 常量定義
|- CmlEngine CML SDK 使用入口
|- CmlEnvironment 運行環(huán)境和運行參數(shù)配置入口、擴展能力設置入口
|- CmlInstanceManage 頁面運行實例的管理類,每一個容器實例運行時,其對應的Instance會注冊到這里
|- ICmlEngine 引擎的抽象接口
|- ICmlInstance 容器實例抽象接口
|- ICmlActivityInstance 全屏容器實例抽象接口
|- ICmlViewInstance 視圖容器實例抽象接口
CML Android SDK 的使用步驟如下:
此類是 Chameleon/k??mi?l??n/ SDK 的入口類,提供基本的初始化入口和 Chameleon容器的調起能力。具體包含以下能力
CmlEnvironment 主要提供了開發(fā)期間需要的一些能力,如
以及一些常量的定義,如
富文本是 CML 里唯一一個默認注冊的組件,主要有以下內容
|
|-richinfo 主要是富文本需要定義的協(xié)議、點擊事件的回調等
|-utils 工具類,主要是加載assets下默認的字體
|-CmlRichTextComponent 繼承與與CmlComponent的富文本組件
|-CmlRichTextEngine 富文本入口類,
github 地址點這里
根目錄 assets 目錄下的 cml-demo-say.zip 是個簡單的示例工程,用來演示 Native 和 Weex 容器或 Web 容器的雙向通信
module 是 Native 提供給前端頁面調用的,完成一組操作的方法集合,用于擴展 Native 的能力。在 CML 頁面中,開發(fā)者引入相關 js 庫后即可調用 Module 中的方法。
import bridge from 'chameleon-bridge';
// 主動調用客戶端方法
export function sayHello() {
bridge.callNative(
'moduleDemo', // 模塊名
'sayHello', // 方法名
{}, // 參數(shù)
res => {} // 回調方法
);
}
Module 的使用分兩種情況,一種是使用 CML SDK 內置的 Module,一種是用戶自定義實現(xiàn)自己的 Module。
內置的 Module 在 js 前端代碼里直接使用即可,目前內置的 Module 有:
API 里描述的能力,部分實現(xiàn)就是由上述 Module 支撐的。
module 擴展 3 個重要的注解
詳細說明
先看個例子,對 Adapter 有個直觀印象和基本概念。Chameleon SDK 里打印日志使用的是默認的 android.util.Log, 如果想替換它可以按照如下步驟實行:
如果用戶想替換 SDK 默認提供的日志打印,可以實現(xiàn) CmlLoggerAdapter 接口,并按如下方式注冊進 SDK:
// 接口實現(xiàn)
public class MyLoggerDefault implements CmlLoggerAdapter {
@Override
public void d(String tag, String msg) {
// 這里實現(xiàn)自己的日志打印
}
...
}
// 接口注冊
public class MyApplication extends Application implements ICmlConfig {
@Override
public void onCreate() {
super.onCreate();
CmlEngine.getInstance().init(this, this);
}
@Override
public void configAdapter() {
CmlEnvironment.setLoggerAdapter(new MyLoggerDefault()); // 注冊自己的Adapter
...
}
...
}
以上就完成了日志打印能力的替換。
SDK Adapter 定義和默認實現(xiàn)如下:
// 日志接口定義
public interface CmlLoggerAdapter {
void d(String tag, String msg);
...
}
// 日志接口默認實現(xiàn)
public class CmlLoggerDefault implements CmlLoggerAdapter {
@Override
public void d(String tag, String msg) {
Log.d(tag, msg);
}
...
}
如果用戶注冊了自己的 Log Adapter 實現(xiàn)則優(yōu)先使用,否則使用 SDK 默認提供的實現(xiàn)。
日志打印通過 CmlLogUtil 類調用,注冊自己的 Logger Adapter 后,打印日志的相關方法就會回調到自定義的方法實現(xiàn)里,使用示例:
// 日志打印
public void launchPage(@NonNull Activity activity, String url, HashMap<String, Object> options) {
if (TextUtils.isEmpty(url)) {
CmlLogUtil.e(TAG, "CmlEngine launchPage, url is empty.");
return;
}
...
}
Adapter 的目的是定義一系列能力接口來隔離具體的實現(xiàn),方便 SDK 使用者在需要時靈活替換成自己的實現(xiàn)。Chameleon SDK 框架層在使用 Adapter 相關能力時都是面向接口的,使用者只需要實現(xiàn)相關能力的 Adapter 接口并通過 SDK 注冊接口進行注冊,即可輕松替換成自己的實現(xiàn)并進行能力擴展。
Chameleon SDK 并沒有完整的實現(xiàn)所有 Adapter 接口,也就是說一部分有默認實現(xiàn)的 Adapter 可以直接使用,未提供默認實現(xiàn)的需要使用者自己實現(xiàn),否則框架將無法使用對應的接口能力。
Chameleon SDK 定義了如下的 Adapter 接口
接口 | 功能 | 默認實現(xiàn) |
---|---|---|
ICmlDegradeAdapter | 降級 | 無 |
ICmlImgLoaderAdapter | 圖片加載 | 有 |
CmlLoggerAdapter | 日志 | 有 |
ICmlNavigatorAdapter | url 跳轉 | 有 |
ICmlStatisticsAdapter | 統(tǒng)計信息輸出 | 無 |
ICmlWebSocketAdapter | WebSocket | 有 |
CmlHttpAdapter | Http 請求 | 有 |
CmlJsonAdapter | json 解析 | 有 |
CmlDialogAdapter | 對話框 | 有 |
CmlToastAdapter | 提示浮層 | 有 |
CmlStorageAdapter | key->value 存儲 | 有 |
CmlThreadAdapter | 線程 | 有 |
降級、對話框、提示浮層 Adapter 在 SDK 實際使用時替換可能性較大,分別說明。
降級
ICmlDegradeAdapter 降級接口沒有提供默認實現(xiàn) CmlDegradeDefault 默認會關閉 Native 渲染容器,并打開 Web 容器加載降級 url。
public class CmlDegradeDefault implements ICmlDegradeAdapter {
@Override
public DegradeViewWrapper getDegradeView(int degradeCode) {
return new DegradeViewWrapper() {
CmlWebView webView;
@Override
public View getView(@NonNull Context context) {
webView = new CmlWebView(context);
webView.onCreate();
return webView;
}
@Override
public void onDestroy() {
if (null != webView) {
webView.onDestroy();
}
}
@Override
public void loadURL(@NonNull Context context, @NonNull String url, @Nullable HashMap<String, Object> options) {
if (null != webView) {
webView.render(url, null);
}
}
};
}
@Override
public void degradeActivity(@NonNull Activity activity, @NonNull String url, @Nullable HashMap<String, Object> options, int degradeCode) {
if (url.contains("?")) {
url = url.substring(0, url.indexOf("?"));
}
CmlEngine.getInstance().launchPage(activity, url, null);
}
}
degradeActivity 會在如下降級場景發(fā)生時回調
對話框
此接口定義以下兩種對話框能力
CmlModalTip 實現(xiàn)了此接口,通過 CmlModalModule 類暴露給 JS 側調用,前端用法參考 API交互反饋
提示浮層
此接口定義以下浮層提示能力
CmlModalTip 實現(xiàn)了此接口,通過 CmlModalModule 類暴露給 JS 側調用,前端用法參考 API交互反饋
圖片加載
CmlDefaultImgLoaderAdapter ,默認使用 Glide,需要用戶手動集成 Glide
日志打印
CmlLoggerDefault,默認使用系統(tǒng) log 輸出
跳轉
默認使用 Intent.ACTION_VIEW 處理
統(tǒng)計信息輸出
沒有默認實現(xiàn),不關心可以不用實現(xiàn)
WebSocket
CmlDefaultWebSocketAdapter,默認使用 OkHttp3,需要用戶手動集成 OkHttp3
Http 請求
執(zhí)行 http 請求,并監(jiān)聽 http 響應
json 解析
轉換成 json 字符串和反解成 json 對象
key->value 存儲
線程
定義工作線程和 ui 線程
預加載和緩存都是為了節(jié)省 JSBundle 下載的時間,加快 UI 的渲染。
預加載是將下載 JSBundle 的動作提前完成,在需要用到的時候直接從本地讀取并渲染。實際項目使用中,可以將需要預加載的 url 地址列表在 app 啟動時提前從服務端獲取,通過 CML SDK 提供的預加載能力提前下載下來。
對于沒有預加載的 JSBundle 在渲染前需要先下載,下載完成后 CML SDK 會緩存此 JSBundle,下次渲染同一個 JSBundle 時,如果此 JSBundle 沒有更新則不會下載新的,達到節(jié)省時間和流量提升渲染速度的目的。
JsBundleMgr 是一個對 js 進行下載、緩存的一個模塊,根據(jù)協(xié)議來實現(xiàn) js 增量更新功能。主要有以下內容
|
|——cache 基于DiskLrucache來實現(xiàn)緩存功能
|——code js代碼的獲取及管理
|——net 采用httpUrlConnect實現(xiàn)下載功能
|——utils 工具包
|——CmlJsBundleConstant 常量的管理
|——CmlJsBundleEngine 實現(xiàn)了CmlJsBundleManager接口,入口類
|——CmlJsBundleEnvironment 當前環(huán)境的設置,如debug環(huán)境等
|——CmlJsBundleManager 實現(xiàn)此接口可自己定義JsBundle的管理
|——CmlJsBundleMgrConfig 配置類,設置預加載js路徑、緩存大小等,默認預加載及運行時緩存大小是4M,可自行設置
對 js 代碼進行預加載、獲取、緩存的管理。在該包里,我們將拿到的 url 根據(jù)協(xié)議來拆分成多個 url1、url2 等,然后在根據(jù) url1、url2 等來獲取對應的 js 代碼,首先從本地緩存里獲取去尋找對應的 js 代碼,如果不存在則從網(wǎng)絡去下載并保存在本地
一些文件管理、拆分 url、網(wǎng)絡判斷的工具類
緩存文件名、預加載優(yōu)先級的管理,預加載優(yōu)先級有以下三種類型
實現(xiàn)了 CmlJsBundleManager 接口,主要有以下三個方法
實現(xiàn)此接口可以自己定義 JsBundleMgr 的實現(xiàn)
添加依賴
compile 'com.didiglobal.chameleon:js-bundle-mgr:latest.version'
預加載
CmlJsBundleEnvironment.DEBUG = true;
List<CmlModel> cmlModels = new ArrayList<>();
CmlModel model = new CmlModel();
model.bundle = CmlUtils.parseWeexUrl(url1);
model.priority = 2;
cmlModels.add(model);
model = new CmlModel();
model.priority = 2;
model.bundle = CmlUtils.parseWeexUrl(url2);
cmlModels.add(model);
CmlJsBundleMgrConfig config = new CmlJsBundleMgrConfig.Builder().setPreloadList(cmlModels).build();
CmlJsBundleEngine.getInstance().initConfig(this, config);
CmlJsBundleEngine.getInstance().startPreload();
獲取 Js 代碼
CmlJsBundleEngine.getInstance().initConfig(this, new CmlJsBundleMgrConfig.Builder().build());
String url = CmlUtils.parseWeexUrl(url);
CmlJsBundleEngine.getInstance().getWXTemplate(url, new CmlGetCodeStringCallback() {
@Override
public void onSuccess(String codes) {
Log.i(TAG, "onSuccess: " + codes);
}
@Override
public void onFailed(String errMsg) {
Log.i(TAG, "onFailed: " + errMsg);
}
});
獲得 SDK 信息
無
返回 promise
返回值 | 類型 | 說明 |
---|---|---|
version | String | 版本號 |
同步方法,判斷 webview 或 Native 頁面是否在 sdk 環(huán)境中,目前只用于內部封裝方法使用。
無
返回值 | 類型 | 說明 |
---|---|---|
value | Boolean | true:在 sdk 環(huán)境中;false:不在 sdk 環(huán)境中 |
import bridge from 'chameleon-bridge';
const inSDK = bridge.inSDK(); // true/false
降級到 cmlUrl 對應的 h5 地址。
js 調用 Native sdk
import bridge from 'chameleon-bridge';
// 主動調用客戶端方法
export function sayHello() {
bridge.callNative(
'moduleDemo', // 模塊名
'sayHello', // 方法名
{}, // 參數(shù)
res => {} // 回調方法
);
}
監(jiān)聽客戶端調用 js
import bridge from 'chameleon-bridge';
// 監(jiān)聽客戶端調用js
export function listenTell() {
bridge.listenNative(
'moduleDemo', // 模塊名
'NaTellJS', // 方法名
res => {
// 回調方法中處理返回的數(shù)據(jù)
}
);
}
瀏覽器在加載靜態(tài)資源的時候一般的話會使用兩種 HTTP 緩存管理機制:
類似的,在使用chameleon sdk加載 JS 包的時候也會提供兩種緩存管理機制:
基于LRU的緩存策略,簡單來說就是實現(xiàn)了一個緩存池,每次請求先從緩存池中搜索一下,如果有就直接使用緩存池中的 JS 包,如果沒有,就從網(wǎng)絡上請求 JS 包并將其緩存在緩存池中,每一份 JS 包緩存按照最后使用時間排序,當緩存池滿了以后,將最早使用過的緩存從緩存池中清理出去,保證客戶端上的資源占用可控。
與普通瀏覽器實現(xiàn)的協(xié)商式緩存類似,用戶只需在靜態(tài)資源服務端配置好靜態(tài)資源的協(xié)商式緩存頭部,即可實現(xiàn)與普通瀏覽器一致的方式使用協(xié)商式緩存。
當 JS 包升級迭代需要在客戶端內使用最新的包時,在使用兩種緩存方式下,相應的存在兩周更新方式,下面會詳細介紹
由于強制緩存,客戶端不會主動的去向服務器請求最新的更新包,會導致客戶端一直使用老的版本。
為了能夠打到規(guī)避這種情況,我們提供了一種可供參考的解決方案:
設置chameleon.config.js中的hash: true,具體可參考工程化配置之文件指紋, CML 項目構建出的 JS 包文件名會類似如下
test_project_c6bdf9074a821f01e70f.js
得到以下可以訪問的資源地址
https://www.static.com/test_project_c6bdf9074a821f01e70f.js
將入口頁面中的 cmlUrl cml_addr 替換成 encodeURIComponent 后的最新資源地址即可,比如
原 cmlUrl:
https://www.static.com/test_project.html?cml_addr=https%3A%2F%2Fwww.static.com%2Ftest_project_21f01e70fc6bdf9074a8.js
新的 cmlUrl
https://www.static.com/test_project.html?cml_addr=https%3A%2F%2Fwww.static.com%2Ftest_project_c6bdf9074a821f01e70f.js
最佳實踐
由于強制緩存下每次修改都需要修改入口頁面的 cmlUrl 中的 cml_addr 參數(shù),可能會導致修改頻繁影響效率,所以建議通過后端讀取 map.json 的方式下發(fā)跳轉 cmlUrl 進行統(tǒng)一管理。
具體請求過程如下圖所示:
這樣每次 bundle 修改后可以自動完成更新
可以直接使用 http 的緩存更新策略,不需額外的配置。
在某些場景下,為了能夠讓頁面更快的呈現(xiàn)在用戶面前,需要讓客戶端提前下載一些 js 包,這時就需要用到預加載。
更多建議: