在Vue項目中導入外部字體的幾個注意點

因爲項目裏有需求,要做一個代碼展示。既然要做代碼展示,高亮可以用highlight.js(當然這裏沒有這個需求,只是單純做一個展示),同時字體也是必不可少的,用瀏覽器的默認字體總覺得差點啥,所以就有此一說。找了半天,我用了Source Code Pro這個開源的字體,用的是Google提供的字體服務。

本來應該是沒啥需要注意的,大家都知道,只要從網上把字體下下來,然後放在項目裏讓webpack一起打包就行了,但是字體這種東西,打包在一起有點大,會增加打包的體積。可能有人說,我可以異步加載,可以shake(把字體裏用不上的部分shake掉,對性能有特殊追求的同學可以試試,有一些解決方案),可以split,但是即使是靜態資源,只要跟項目放在一起,就會佔用服務器的帶寬,間接降低併發量,所以最好還是拿出來;更何況這又不是那些必須要有的依賴,沒有字體也能照樣展示,就是不太好看罷了。

但是拿出來之後又有一個問題。如果說放在head裏,啥都不加,肯定會阻塞渲染,顯然是不好的;加個defer,或者在我這個場景下,放在Vue的mounted鉤子裏,又會導致界面閃爍。之前聽說有個preload還不錯,就試着用一下。

然後因爲我用了vue-meta這個庫,這個庫似乎不能配置link的as、crossorigin這幾個屬性,着實有點難受,只能在mounted裏創建一個link標籤來配置:

mounted() {
  const fontElement = document.createElement('link');
  fontElement.rel = 'preload';
  fontElement.href =
    'https://fonts.googleapis.com/css?family=Source+Code+Pro&display=swap';
  fontElement.as = 'style';
  fontElement.crossOrigin = 'anonymous';
  document.head.appendChild(fontElement);
}

這裏面其實有好幾個需要注意的地方:

第一個已經說了,vue-meta這個庫好像不能配置link的as、crossorigin這幾個屬性,只能自己手寫;

第二個是這裏用的是Google的字體服務,Google的字體是以CSS的形式提供的,所以as要寫成style而不是font,否則不能正確解析;

第三個是crossOrigin一定要有,沒有的話也無法加載,這是字體的一個比較特殊的地方,即使是同源,也要設置這個,更何況這還不是同源的。因爲CSS規範規定,瀏覽器必須匿名地去獲取字體:

4.8.2. Font fetching requirements

For font loads, user agents must use the potentially CORS-enabled fetch method defined by the [HTML] specification for URL’s defined within @font-face rules. When fetching, user agents must use “Anonymous” mode, set the referrer source to the stylesheet’s URL and set the origin to the URL of the containing document.

但是爲什麼會有這樣的規定,據說是因爲XHR的默認請求就是匿名的;但是這個理由並不是很有說服力,我也沒有找到其他的解釋,希望知道的人不吝賜教。

說了半天,其實是和業務場景強相關的一些問題,並不具有普遍價值。不過,這也可以作爲性能優化的一個切入點去進行思考。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章