問題
H5 頁面的動態文案需要使用藝術字體,而通常情況下,字體包都是很大的,全部加載肯定是不行的。
那該怎麼辦呢?
分析
對於普通的 H5 頁面需要使用藝術字體,我能想到的解決方案大致是以下幾種。
1、靜態文案:
- 直接用圖片
- 用類似 font-spider 的工具將字體庫過濾,然後引入。(如果字體庫比較大)
2、動態文案:
- 硬着頭皮加載整個字體庫(如果字體包很大,體驗肯定很棒)
- 和設計同學溝通,對於不固定文案的地方,看看能不能棄用藝術字體(看設計的態度,可以適當謊稱技術無法實現,通常這是最佳解決方案)。
- 通過後端服務,將頁面需要用到的藝術字體文案發給後端,讓後端服務生成圖片或者svg等,然後返回顯示。
- 其他優秀的解決方案,還望分享。
這裏就不討論每種方案的優缺點了。
這裏說下我們遇到的場景以及解決方案——客戶端攔截請求返回本地字體包資源。
因爲我們是 Hybird 開發,而且整個 app 的標題都統一採用了藝術字體,最精彩的是標題是後臺可配的。
客戶端打包了一個完整的字體包(也不是很完整,過濾了常用的5000字,大概 1M,夠用了),這樣就可以支持藝術字體了。
但是H5就很尷尬了,請求服務端字體包,太大了。所以思路就是,能不能 H5 頁面也使用客戶端本地打包的那個字體包?
通過上面分析,現在需要解決的問題變成了 H5 頁面訪問客戶端本地文件。
最先想到的是通過文件協議 file:///
直接去訪問,但是試了幾次,沒有成功。後來想到應該是跨域了。
後來想到大部分客戶端協議(scheme的方式)都是通過攔截請求的方式實現的,還有之前瞭解過客戶端緩存 H5 靜態資源的需求,也是通過攔截 H5 請求,然後對比本地緩存清單,決定是返回本地文件還是向服務端發出請求。
解決方案
經過分析,我們來梳理下實現。
1、h5 頁面正常發出請求(通過 http/https 協議),爲了客戶端能識別出這個請求是訪問本地文件,這裏需要對請求路徑或域名進行一些特殊處理。
這裏說下我們的處理方式。
通過和客戶端商量,我們將域名改成 localfile
作爲請求本地文件的標示。不過這樣需要客戶端同學響應時修改頭信息中的 Access-Control-Allow-Origin ,允許跨域。
後面的 fonts 和 nbfont.tff 分別代表文件類型和名稱。
@font-face {
font-family: 'nbfont';
src: url('//localfile/fonts/nbfont.ttf');
}
2、客戶端攔截請求並返回本地文件。這裏只瞭解了 Android 的實現方式。
重寫 shouldInterceptRequest:
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
WebResourceResponse response = super.shouldInterceptRequest(view, url);
CLog.i("load intercept request:" + url);
if (url != null && url.contains("localfile")) {
String assertPath = url.substring(url.indexOf("localfile/") + "localfile/".length(), url.length());
try {
// 如果有跨域,還需要添加修改頭部信息的代碼,具體可以看下 WebResourceResponse
response = new WebResourceResponse("application/x-font-ttf",
"UTF8", getAssets().open(assertPath)
);
} catch (IOException e) {
e.printStackTrace();
}
}
return response;
}
總結
以上就是基本實現方式了,還是很簡單。可能有人看到客戶端攔截請求返回本地字體包資源的時候就知道怎麼實現了哈。這其實就是 H5 和客戶端通信協議的實現思路,只不過一個是回調返回參數,一個是返回響應文件。
簡單說下這個方案的優缺點。
缺點:
1、如果字體包客戶端不使用,將字體包打包在客戶端會增加 APK 的大小。
2、需要客戶端修改代碼,所以需要發版本,版本兼容需要考慮。
3、比較適合固定某個藝術字體的需求,如果設計一個活動頁換一個藝術字體,那就拜拜吧。
優點:
1、本地訪問,速度快。
2、不僅解決了字體的問題,而且提供了一種訪問客戶端本地文件的方式。
最後我想說,這些問題,只是某個時期客觀上的一些原因或者不足造成的,就像當年開發需要寫各種瀏覽器的兼容,後來通過瀏覽器廠商對各種規範的落實和移動互聯網的到來,有些以前讓人頭疼的問題,現在已經不存在了。
同樣我們可以暢想,未來硬件性能提升,5G 基站的逐漸普及,帶寬升級,流量費用降低。那麼我們今天討論的問題可能就不會是問題了,那個時候就毫不猶豫的加載整個字體庫吧。
不過在這一天沒有到來前,最有效的解決方法還是從需求入手,勸勸設計同學。