用 FontForge 做 tree-shaking 減少網頁字型檔案大小

一個網頁使用了某個特殊字體,為了 SEO 和 RWD 排版斷行等原因,沒有直接通通做成圖片。但是網頁載入時因為會跑一個 10幾MB 的字型檔,雖然主機不是用我的,流量費用不是我付,但網頁開啟耗時畢竟比較久,也比較耗使用者的流量,所以嘗試把字型檔壓小。

頁面的文字都是固定的,不是會從後台上稿或動態產生的那種,所以可以用 FontForgeFontSpider,那種把字型檔裡面沒用到的字移除的技術,一般稱為 remove unused glyphs,但在前端好像要講 tree-shaking 比較潮?

以 FontForge 為例

1.下載安裝 FontForge,這邊安裝的是 Windows 版本。
2.從TechBridge 技術共筆部落格 – 透過減少 ttf 字體檔案大小來增進網頁效能知道有 script api 可以用,不用透過 ui 介面進行超低效率的操作,但是文中的範例跑不起來,於是又自己摸索。
3.把網頁裡會用到的中文字、英文、數字、符號挑出來,轉成長得像 u628au7db2u9801u88e1u6703u7528u5230u7684u5b57u6311u51fau4f86 的字串。
4.把上面那串 utf8 碼的字串代換成這種子,大致就是選取要留下的文字、反選、刪除。

SelectMore(“u628a”)
SelectMore(“u7db2”)
SelectMore(“u9801”)
SelectMore(“u88e1”)
SelectMore(“u6703”)
SelectMore(“u7528”)
SelectMore(“u5230”)
SelectMore(“u7684”)
SelectMore(“u5b57”)
SelectMore(“u6311”)
SelectMore(“u51fa”)
SelectMore(“u4f86”)
SelectInvert()
DetachAndRemoveGlyphs()

5.貼到 FontForge 的 File>Execute Script 裡面,這邊有幾個小眉角:
a.上面那篇教學產生的 SelectMore 範例看起來是沒有換行的,而貼到 Execute Script 裡面會出現 unterminated ff_statement 這種不知道要怎麼處理的錯訊訊息,跟寫 python 一樣加斷行就好了。
b.Execute Script 有兩個選項,一個是 Python,一個是 FF,上面那段範例,一定要選 FF 才能執行。

6.執行後會看到本來滿滿的字型會變成只剩剛剛列的那些字,可以按 Encoding>compact,把沒用到的字藏起來
7.選擇 File>generate fonts,存成網頁 webfont 所需要的字體格式 TrueType(ttf) 和 Web Open Font(woff),可以看到本來幾10MB的字型檔變小了(依保留文字的多寡而定)。

當然下次如果網頁有文字修改增減,同樣的步驟就要再做一次…….

補充: 後來看到一個工具 FontMagic,是在 macOS 跟 Windows 上面提供一個小軟體,把字體檔轉換成 svg,一樣可以選擇只保留哪些字元。

本技巧也適用於 iconfont

像 FontAwesome 比較新的版本可以動態產生 icon,但如果每月 pageview 會用超過 10000,又沒預算升級,只能用比較傳統技術型的 iconfont 。
傳統型 iconfont 就是即使只用了兩三顆 icon,但網頁要引用一大包所有圖示的 css,在網頁載入時還要下載一個好幾 MB 檔案的 font 檔案的那種,同樣也可以用這種技巧把 iconfont 的字型檔內沒用到的字元拿掉。

例如REMIX ICON,從 css 檔看到某圖示是 .ri-24-hours-fill:before { content: "ea01"; },那在上面的範例要輸入 SelectMore(“uea01”)
但這樣查有點辛苦,有的 iconfont 也有直接提供 svg 檔給人使用。
還要注意 iconfont 的授權方式能不能這樣改作。

Google Font 的 text 參數

如果是嵌入使用 Google Font 上面的中文 webfont 字體,預設會發現他們把字體切分成很多檔案或 subset,不一定會直接載入完整一大包。但是如果碰到不會用瀏覽器 devtools 的人,看到網頁下面 XXX MB resources 覺得網頁怎麼這麼大? 網頁如果有多少人來看,就消耗主機流量幾 GB 云云,這樣算其實是有問題的,如果使用 devtools 看資料時沒有指定 domain,網頁上的一些社群網站套件、GA、GTM、YouTube、Google Fonts 也會算在裡面,但根本就不會佔主機本身的流量呀。

如果是想要網頁載入 size 越小越好的狂人,從 Google Fonts API 發現還有讓網頁載入的 size 更小的方法。就是Google Fonts 提供一個 text 的參數,例如使用 link css 載入的,可以改成:

<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@700&display=swap&text=布魯斯威利是鬼" rel="stylesheet">

這樣載入網頁時,字體檔案裡面就會只剩 7 個字,檔案 size 就會小更多。但是只適用於知道網頁內是固定文字的情況。如果是考慮 PageSpeed 會扣分的問題,可以參考之前的 PageSpeed 文章,用實驗1的 Web Font Loader 載入思源黑體之類的作法。

注意事項1:看似一樣,但內碼不一樣的字

把新產生的字型檔套到網頁上一看,有些字不知道為何字體樣式跑掉了,看起來跟一般的中文字差不多,但字的內碼跟一般的中文字是不一樣的,例如:
⿆u2fc6
麥u9ea5
剛剛在 FontForge 只留下了u2fc6,而 u9ea5 被刪掉了,缺字的當然就變回系統預設字體。

文字是從 pdf 上 copy 下來的,不知道為何發生這種情形,不想 FontForge 重新補字,就直接人工修正網頁上的字。

有網友提供這種現象的解釋 漢字のようで漢字でないUnicodeの「康熙部首」と「CJK部首補助」

注意事項2:商業授權的字型不能這樣搞

本例中要被拿來壓縮的字體是源柔ゴシック,不是 Google Fonts 或任何一家 webfont 上面的,所以沒辦法用 webfont 網站上的網址,只能自己 hosting。而因為該字體是一個 Open Source 的開源免費字型,所以可以把字體檔上傳到自己的網頁伺服器,並任意進行改動。

而購買商業字型就不一樣囉! 而各大字體廠商對於這種購買桌面版/實體光碟字型之後…
通常一套只能安裝在一台電腦上。
這種「把沒用到的字從字型檔移除」「把字型檔放到其他電腦(伺服器)上讓人公開使用」的操作通常也不在合理使用範圍。
把字型檔上傳到自己網頁伺服器的嵌入式用法,甚至這個字體是用在什麼線上用途,都有許多授權和使用範圍的限制:

以下是一個案例

當然某些時候決策人員似乎完全不需要這種授權觀念也可以出來開設計公司,只要拿一些用盜版字體的網站問說「為什麼人家可以做?」「別人用的字體多好看」
結果設計人員整天幫字體公司查法律條款、證明某些字體平台是非法的?
整天查別人的產品,像是 下筆 有沒有買 Application Service Provider 或其他特殊授權?
整天查別人家用的字體或 webfont 要怎麼買、多少錢?
錢領最少的人要懂最多東西? 而且整天搞這些,連正事都不用做了。

留言:

近期熱門 Hot Posts