如何预加载 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】:

我找到了解决方法。这并不令人愉快,但我认为总比没有好。 这里我只想预加载woffwoff2文件。

new PreloadWebpackPlugin(
      rel: 'preload',
      include: 'allAssets',
      fileBlacklist: [/\.(js|ttf|png|eot|jpe?g|css|svg)/]
    ),

【讨论】:

【参考方案4】:

我相信要预加载字体文件,您只需在 index.html 文件中手动指定 &lt;link /&gt;

<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 怎么办?

ES6入门十二:Module(模块化)

webpack4 使用babel处理ES6语法的一些简单配置

如何在供应商捆绑包上使用 babel 的 `useBuiltIns: 'usage'` 选项?

webpack4 Cannot find module '@babel/core'

如何使用 Vue CLI 4.3 默认禁用链接(异步模块)预取/预加载?