重要:建议直接看目录 四、更新部分 因为原来推荐的方法我已经弃用,效果并不是很好,后面又查询好一个更好的解决方案
一、问题点(业务场景)
当项目加载字体库的时候通过@font-face
方法引入字体文件,并在main.js
中全局引入,这样会导致页面加载缓慢,阻塞页面加载。
二、解决方案
以.ttf
文件为例,可以通过以下的几种方式进行解决字体文件加载缓慢的问题:
-
压缩字体文件:确保您的TTF字体文件已经进行了压缩。可以使用在线工具或字体编辑器将字体文件进行压缩,以减少文件大小。较大的字体文件会增加下载时间,从而导致页面加载缓慢。
-
异步加载字体文件:考虑将字体文件的加载延迟到页面其他内容加载完成之后。这可以通过异步加载字体文件的方式来实现,例如使用JavaScript的
async
或defer
属性来加载字体文件。 -
字体子集化:如果您只使用了字体文件中的一小部分字符,可以考虑使用字体子集化工具,如
Font Squirrel
的Webfont Generator,以生成包含所需字符的自定义字体文件。这将减小字体文件的大小,从而加快加载速度。 -
CDN或字体托管服务:将字体文件托管在CDN上或使用字体托管服务,如Google Fonts。这将使字体文件能够通过多个地理位置的服务器进行分发,从而提高加载速度。
-
使用系统字体作为备选方案:如果您使用的字体在大多数用户的操作系统中都是常见的字体,可以考虑使用系统字体作为备选方案,而不是自定义字体文件。这样可以避免字体文件的下载和加载。
三、示例
在Vue项目中异步加载字体文件并全局引用可以通过以下步骤完成:
-
首先,在Vue项目的根目录中创建一个
fonts
文件夹,并将字体文件(比如your-font.ttf
)放入其中。
-
在Vue项目的根目录中的
public
文件夹下创建一个名为fonts.css
的CSS文件,并在其中定义字体的@font-face规则。示例代码如下:
@font-face {
font-family: 'AlibabaPuHuiTi-2-55-Regular';
src: url('/fonts/AlibabaPuHuiTi-2-55-Regular.ttf') format("truetype");
}
@font-face {
font-family: 'AlibabaPuHuiTi-2-65-Medium';
src: url('/fonts/AlibabaPuHuiTi-2-65-Medium.ttf') format("truetype");
}
@font-face {
font-family: 'AlibabaPuHuiTi-2-85-Bold';
src: url('/fonts/AlibabaPuHuiTi-2-85-Bold.ttf') format("truetype");
}
@font-face {
font-family: 'SourceHanSansCN-Regular';
src: url('/fonts/SourceHanSansCN-Regular.ttf') format("truetype");
}
/* 可以添加其他字体属性,如font-weight和font-style */
}
- 打开项目的
public/index.html
文件,并在<head>
标签内添加以下代码来引入上一步创建的fonts.css
文件:
<link rel="stylesheet" href="/fonts.css">
- 接下来,您可以在Vue项目的入口文件(一般是
main.js
或main.ts
)中使用动态导入异步加载字体文件。示例代码如下:
// main.js 或 main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import './permission' // 控制
// 异步加载字体文件
function loadFonts() {
const fontStyles = document.createElement('link');
fontStyles.href = '/fonts.css';
fontStyles.rel = 'stylesheet';
document.head.appendChild(fontStyles);
}
const app = createApp(App)
app.use(store)
app.use(router)
app.mixin({
beforeMount() {
loadFonts()
},
})
app.mount('#app')
这样,字体文件将在页面加载后进行异步加载,确保页面的关键内容能够尽快加载完成。您可以将字体文件的路径和文件名根据您的实际情况进行调整。
请注意,使用异步加载字体文件可能会导致字体的闪烁或文本重新布局。为了避免这些问题,您可以在字体文件加载完成后,再触发页面的重新渲染或刷新。注意,这里我用的是vue3的语法,如果是vue2的语法自行调整。并且我不太清楚在main.js
中如何使用beforeMount
,所以我这里用的是mixin
全局混入的方式,如果有了解的直接可以使用beforeMount
方法的朋友,希望在评论中指导一下,互相学习,感谢!!!
四、更新方法
原来的上述方法我已经弃用,虽然字体加载确实是异步加载的,但是似乎还是会阻塞页面的渲染。现在来推荐一个新的css样式可以解决字体异步加载的问题:font-display:swap;
效果就是等页面加载的时候会最先加载默认的字体,等自定义的字体加载完成之后才会替换默认的字体,使用方式如下:
1.创建一个fonts.css文件,用于引入自定义的字体包
@font-face {
font-family: 'AlibabaPuHuiTi-2-55-Regular';
font-display: swap;
src: url('/fonts/AlibabaPuHuiTi-2-55-Regular.ttf') format("truetype");
}
/* 可以添加其他字体属性,如font-weight和font-style */
2.可以在main.js文件中全局引入css文件,也可以在要使用的页面引入css文件,我这里全局引入
// main.js 或 main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import './permission' // 控制
import './style/fonts.css' // 全局引入css文件
const app = createApp(App)
app.use(store)
app.use(router)
app.mount('#app')
3.要调用的页面
p { font-family: "AlibabaPuHuiTi-2-55-Regular", "Helvetica", "Arial"; }
注意:要使用引入的字体的时候需要在后面输入好浏览器的安全字体,这样页面最先加载的时候是用浏览器自带的字体,然后等引入的字体下载完成之后就会代替原来的安全字体。