如何预加载 webpack4+babel 捆绑的 CSS @font-face 字体?
Posted
技术标签:
【中文标题】如何预加载 webpack4+babel 捆绑的 CSS @font-face 字体?【英文标题】:How to preload a CSS @font-face font that is bundled by webpack4+babel? 【发布时间】:2019-08-19 05:08:31 【问题描述】:我为 React Web 应用程序设置了 webpack4+babel 捆绑器。在 LESS 文件中,我引用了本地字体。该字体在构建时被复制到dist
文件夹,并且其文件名是散列的。我希望能够预加载此字体。
这是我的 LESS 文件:
@font-face
font-family: 'Test';
src: url('../fonts/test.ttf') format('truetype');
font-weight: 400;
我尝试了以下方法,但到目前为止都没有成功:
-
将自定义导入添加到我的应用的主 JS 文件中。
import(/* webpackPreload: true */ "../fonts/test.ttf");
这是我的.babelrc
文件:
"presets": [
"@babel/preset-env",
"@babel/preset-react"
],
"plugins": [
"@babel/plugin-syntax-dynamic-import"
]
运行 webpack
不会在任何地方产生预加载方向,就我在输出的 html 中看到的而言 - 我搜索了 dist
文件夹的内容,但一无所获。
-
preload-webpack-plugin
我将此添加到我的webpack.config.js
文件中:
plugins: [
new HtmlWebpackPlugin(),
new PreloadWebpackPlugin(
rel: 'preload',
as(entry)
if (/\.css$/.test(entry)) return 'style';
if (/\.woff$/.test(entry)) return 'font';
if (/\.png$/.test(entry)) return 'image';
return 'script';
)
]
这会为 JS 脚本文件包创建预加载,但不会为 CSS 和字体创建预加载。
关于如何让它发挥作用的任何想法?
【问题讨论】:
【参考方案1】:能够通过安装版本 3beta 并使用 while list 选项使其在 webpack4 上运行:
yarn add -D preload-webpack-plugin@3.0.0-beta.3
new PreloadWebpackPlugin(
rel: 'preload',
as: 'font',
include: 'allAssets',
fileWhitelist: [/\.(woff2?|eot|ttf|otf)(\?.*)?$/i],
),
【讨论】:
【参考方案2】:发布此内容是因为我认为它可能对处于类似位置的人有所帮助 - 我意识到它并不能解决所描述的问题。
有同样的问题 - 不需要对我的字体文件进行哈希处理,但 URL 的另一部分不是静态的。有点hackish,但解决了我的问题。也许它可以帮助某人。理论上,您可以创建自己的 hash-id 并将其设置为 htmlWebpack-plugin 变量。
在我的 index.html 中
<html>
<head>
<link rel="preload" href="<%= htmlWebpackPlugin.options.woffSrc %>" as="font" type="font/woff" crossorigin>
<link rel="preload" href="<%= htmlWebpackPlugin.options.woff2Src %>" as="font" type="font/woff2" crossorigin>
//rest of html
webpack.prod.conf.js - 更新了 HtmlWebpackPlugin
plugins: [
new HtmlWebpackPlugin(
...config,
woffSrc: `https://url.to.my.page.com/$ASSETS_FOLDER/static/assets/fonts/GilroyRegular.woff`,
woff2Src: `https://url.to.my.page.com/$ASSETS_FOLDER/static/assets/fonts/GilroyExtraBold.woff2`
)
]
我推断字体文件不需要有哈希 - 因为它主要用于控制缓存并且我不会更改字体文件,所以我在我的 webpack 文件加载器中关闭了它。如果我在这里错了,请纠正我。
拥有加载器:
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options:
limit: 2000,
name: utils.assetsPath('assets/fonts/[name].[ext]')
由于构建错误而无法让preload-webpack-plugin 工作,并且在 2 天后厌倦了故障排除。
【讨论】:
【参考方案3】:我找到了解决方法。这并不令人愉快,但我认为总比没有好。
这里我只想预加载woff
和woff2
文件。
new PreloadWebpackPlugin(
rel: 'preload',
include: 'allAssets',
fileBlacklist: [/\.(js|ttf|png|eot|jpe?g|css|svg)/]
),
【讨论】:
【参考方案4】:我相信要预加载字体文件,您只需在 index.html
文件中手动指定 <link />
:
<link rel="preload" href="../fonts/test.ttf" as="font" type="font/ttf">
有关详细信息,请参阅this。
【讨论】:
感谢您的回复,但我的问题是字体文件名是由 webpack 散列的,所以我不知道将它们复制到dist
文件夹后它们会是什么。也许有一种在 HTML 文件中使用占位符的方法?
您的字体文件会经常更改吗?为什么需要将它们包含到您的 webpack 编译过程中?我认为您可以创建另一个 assets
文件夹来服务器静态文件,这些文件不需要由 webpack 与 dist
文件夹并行编译,并从该文件夹中提供静态文件
这是一个公平的观点。字体不会改变,即使它们改变了,在 webpack 构建之后复制它们也不会太费力。我认为链接到 HTML 中的字体文件(用于预加载)以及在 CSS 中使用 @font-face 链接(它们实际上将在其中使用)都很好 - 即一旦它们被浏览器预加载,那么它会'不想再这样做了?
我认为除了使用link
之外,没有其他方法可以预加载字体。因此,即使您使用了一些 Webpack 预加载解决方案,它也只会插入带有预加载属性的 link
来加载您的资产。所以是的,我相信如果浏览器已经预加载了资产,它就不应该发出另一个请求,但是我认为你想放置一些 cache-control
标头,以便浏览器缓存资产。
干杯。您推荐的方法现已生效并运行良好。以上是关于如何预加载 webpack4+babel 捆绑的 CSS @font-face 字体?的主要内容,如果未能解决你的问题,请参考以下文章
<REACT-NATIVE> 从预捆绑文件加载,我想从端口:8081 加载,id 怎么办?
webpack4 使用babel处理ES6语法的一些简单配置
如何在供应商捆绑包上使用 babel 的 `useBuiltIns: 'usage'` 选项?