React CRA项目如何预加载本地fonts文件夹内的自定义字体资源
React CRA 本地自定义字体预加载解决方案
针对CRA打包后本地字体带哈希、无法直接写固定路径预加载的问题,可根据你的项目需求选择以下三种方案:
方案1:零配置迁移到public目录(推荐快速实现)
不需要修改任何构建配置,直接利用CRA public目录的静态资源特性:
- 把所有字体文件移动到项目
public目录下新建的fonts文件夹内,public下的文件打包时不会被添加哈希后缀,路径固定 - 修改SCSS中
@font-face的资源路径为绝对路径,示例:src: url('/fonts/FiraGO-Regular.woff2') format('woff2'), url('/fonts/FiraGO-Regular.woff') format('woff'); - 直接在
public/index.html的head标签内添加预加载代码即可:<link rel="preload" href="/fonts/FiraGO-Regular.woff2" as="font" type="font/woff2" crossorigin> <link rel="preload" href="/fonts/FiraGO-Medium.woff2" as="font" type="font/woff2" crossorigin> <link rel="preload" href="/fonts/FiraGO-Bold.woff2" as="font" type="font/woff2" crossorigin>
方案2:保留哈希缓存,通过自定义构建配置自动注入预加载标签
如果不想放弃webpack对字体的哈希缓存能力,可以通过craco(无需eject)修改webpack配置实现:
- 安装依赖:
npm i @craco/craco @vue/preload-webpack-plugin --save-dev(该版本插件适配webpack5,对应CRA v5+版本) - 项目根目录新建
craco.config.js,添加如下配置:const PreloadWebpackPlugin = require('@vue/preload-webpack-plugin'); module.exports = { webpack: { plugins: [ new PreloadWebpackPlugin({ rel: 'preload', // 只预加载woff2格式字体,避免不必要的资源消耗 as: asset => asset.endsWith('.woff2') ? 'font' : false, include: 'allAssets', // 匹配你的字体文件名,避免预加载其他无关字体 fileWhitelist: [/FiraGO.*\.woff2$/], // 字体预加载必须加crossorigin属性 crossorigin: true }) ] } }; - 修改
package.json里的启动、打包脚本为craco执行:"scripts": { "start": "craco start", "build": "craco build", "test": "craco test" }
后续打包时webpack会自动把带哈希的字体路径注入到index.html的preload标签中,不需要手动维护路径。
方案3:无配置修改,JS动态预加载
不想改构建配置也不想移动字体文件的话,可以在入口文件中引入字体获取带哈希的路径,动态创建预加载标签:
- 在入口文件
src/index.js中添加如下代码:// 引入字体文件,webpack会自动返回带哈希的打包后路径 import firagoRegular from './fonts/FiraGO-Regular.woff2'; import firagoMedium from './fonts/FiraGO-Medium.woff2'; import firagoBold from './fonts/FiraGO-Bold.woff2'; const preloadFont = (fontUrl) => { const link = document.createElement('link'); link.rel = 'preload'; link.href = fontUrl; link.as = 'font'; link.type = 'font/woff2'; link.crossOrigin = 'anonymous'; document.head.appendChild(link); }; // 执行预加载 preloadFont(firagoRegular); preloadFont(firagoMedium); preloadFont(firagoBold);
注意事项
- 仅预加载woff2格式即可,woff等兼容格式不需要预加载,避免浪费带宽
- 所有字体预加载标签必须添加
crossorigin属性,哪怕是同域字体,否则预加载的资源不会被复用,会触发二次加载 - 你已配置的
font-display: swap可以和预加载配合,最大化避免页面文字闪烁问题
内容的提问来源于stack exchange,提问作者Varun Sukheja
相关产品推荐
相关产品推荐

