Web字型圖示-自動化方案

特丶困發表於2019-01-12

原文連結jiangxiaokun.com/web/2019/01…

緣起

Web從誕生之日起是為了展示圖片文字的,最典型的代表就是imgspan。這是構建豐富的Web頁面的基石,也是理解瀏覽器表現(Browser performance)的基礎。本文將從從圖片中的小圖示切入,介紹一下Web小圖示的技術方案的演進。

Web中小圖示方案的演進

筆者本來打算從Image Sprites,到 Svg Spritesiconfontsvg Icon 整體介紹一遍的,在查閱資料之後發現已經有大佬寫過了:Web中的圖示-大漠,介紹得算是很詳細(絕大部分應用場景都已經能覆蓋了),這一部分本文就不再贅述了。

筆者的補充

  1. MDN關於 Image sprites備註:當使用 HTTP/2 時,使用多個小流量請求實際上可能更為頻寬友好。
  2. DataURI(圖片Base64)(筆者的建議是慎用,它可能成為一個效能瓶頸),因為CSS在解析過程遇到Base64,每次都需要解碼,這會阻塞關鍵CSS的渲染,具體可以看這一篇文章:深挖 data URI 效能瓶頸

趁機糾正了自己之前的錯誤:Gzip是針對html/css/js的,.wotf/.png/.ico 等圖片資源是不進行Gzip壓縮,如果不確定可以檢視Network中的Response Headers

言歸正傳

接下來終於輪到了本文中的主角:Icon Font 登場了~~~。相比點陣圖 png Sprites 而言,使用字型圖示可以不受限於螢幕解析度,而且字型圖示另一個優勢是:只要適合字型相關的CSS屬性都適合字型圖示。筆者經過調研之後在專案中確定了 Icon font 的方案。

逝去的青春

最開始是將svg上傳到 https://icomoon.io/,生成對應的字型和樣式檔案,然後引入到專案中。

問題1:每次update圖示都需要重複上面的步驟,然後再把檔案下載下來,然後複製到專案原始碼中替換舊的檔案

問題2:樣式檔案不好管理,因為icomoon下載下來的樣式檔案因為相容性的需要,是需要進行修改的,以致於每次得摘出icon-list, 原有已進行相容的程式碼保留。

問題3:當時 icomoon免費版 沒有提供去色構建字型圖示的功能,導致還需要對生成的樣式進行一定的定製(調色,調位置)

問題4:更換了設計師之後,設計出來的某些圖示檔案引入之後,icomoon 生成的字型全部沒法用了。終於忍無可忍……

探索方案

因為源專案中使用gulpwebpack打包,心中最理想的方案當然是webpackplugin或者loader,或者gulpplugin。嘗試過gulp-iconfont結合gulp-iconfont-css已經等等其他方案,要不是因為一些細節方面沒有配置成功,要不就是成功構建出來的字型圖片有明顯的偏移或者鋸齒。多番查閱資料和實踐之後終於發現了一個不那麼起眼的庫webfonts-loader

筆者曾經嘗試過的:gulp-iconfontgulp-iconfont-csswebfontloader ……and so on.

webfonts-loader

第一眼見到他的時候,我未曾想過這將會是陪伴我許久的那一個,無論是從TA可憐的78❤️,還是作者本人jeerbl的知名度,但作為一個勇(zou)於(tou)嘗(wu)鮮(lu)的前端,還是認真地讀了一下TAREADME,看到了熟悉的webpackloader配置和js的語法,決定好好地實踐一下。(扯遠了)

原理(工作流程)

webfonts-loader(藉助webpack)如何一步一步地將svg的圖示處理成我們最終想要的樣子?

How does the webfonts-loader which work with webpack build svg icons step by step ?

先來看最關鍵的3份配置:

scionfont.js
module.exports = {
	files: [
		'./svg/*.svg',
	],
	fontName: 'bicon',
	classPrefix: 'bicon-',
	fixedWidth: true,
	types: ['eot', 'woff', 'ttf', 'svg'],
	cssTemplate: './template.hbs'
};
複製程式碼
iconfont.js loader
{
    test: /siconfont.js/,
    use: [
        'vue-style-loader',
        'css-loader',
        {
            loader: 'webfonts-loader',
            options: isProd ? {
                fileName: assetsPath('img/[fontname]-[hash:7].[ext]')
            } : {}
        }
    ]
}
複製程式碼
fonts loader
{
    test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
    loader: 'url-loader',
    options: {
        limit: 10000,
        name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
    }
}
複製程式碼
  1. 首先,webpack解析到 import './assets/fonts/siconfont.js'
  2. 接著,webpack會將對應的siconfont.js載入到webpack的工作流中
  3. siconfont.js通過正則匹配到了對應的siconfont.js的webpack相應的 loader(上面第2份配置)
  4. 首先使用webfonts-loader來處理這個xx.jswebfonts-loader解析這個siconfont.js(上面的第一份配置) 之後, 會將當前目錄svg下的所有svg圖示檔案都載入進來,並且將相應的CSS模板也載入了進來,並且通過一些項的配置

e.g:配置 types: ['eot', 'woff', 'ttf', 'svg'],表示會打包出四種字型圖示檔案

  1. 接下來的步驟就簡單了:webfonts-loader處理完成之後輸出兩種檔案流:(1).eot/.woff 等字型檔案流 (2) 對應的關聯css流
  2. 檔案流下一步進入css-loader,該importimport,字型圖示路徑該resolveresolve,還有其他可能需要的工作。
  3. 最終生成的CSS可能通過style-loader直接內嵌到html 的style標籤中,也可以通過Extract外掛提取出來整合到最終頁面的CSS 中,然後通過link使用

再一次感受到 webpack 自動收集依賴和管理依賴,真的是很強大,為我們省了太多心

大功告成

藉助著webpack的熱更新機制,我們可以很方面地去更新svg資料夾下的字型檔案,並即時使用。使用步驟:

  1. 拖入檔案 left-arrow.svg
  2. 在元件中對應DOM上新增類名(class): bicon-left-arrow
  3. 重新整理瀏覽器,字型圖示已經加上~

寫在最後

文中的方案已經在手機搜狐網手搜體育頻道等多個專案中實踐和使用,能覆蓋絕大多數業務場景。文中完整的示例可以檢視 vue-ssr-start ,歡迎 star※

Vue-ssr-start 是我學習從零開始搭建一個SSR腳手架的理解和記錄,還有一些對前端工程化的思考和探索,會持續迭代並加上完整的註釋,歡迎watch。水平有限,出錯難免,歡迎各位同學多多指正,共同進步~

參考

webfonts-loader

Web中的圖示-大漠

深挖 data URI 效能瓶頸

icomoon

相關文章