How to preload a CSS @font-face font that is bundled by webpack4+babel?

19,539

Solution 1

was able to make it work on webpack4 by installing version 3beta and using while list option:

yarn add -D [email protected]

new PreloadWebpackPlugin({
        rel: 'preload',
        as: 'font',
        include: 'allAssets',
        fileWhitelist: [/\.(woff2?|eot|ttf|otf)(\?.*)?$/i],

    }),

Solution 2

Posting this since I think it might help someone in a similar position - I realize it doesn't solve the described issue.

Had the same problem - didn't need to hash my font-files but had another part of the url that was not static. A bit hackish, but solved my problem. Maybe it can help someone. In theory you can create your own hash-id and set that as the htmlWebpack-plugin variable.

In my 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 - updated 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`
  })
]

I reasoned that the font-files didn't need to have the hash - since that is mainly used to control cache and I won't change the font files, so I turned that of in my webpack file-loader. Please correct me if I'm wrong here.

Having the loader:

{
  test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
  loader: 'url-loader',
  options: {
    limit: 2000,
    name: utils.assetsPath('assets/fonts/[name].[ext]')
  }
}

Was unable to get the preload-webpack-plugin to work due to build errors and got tired troubleshooting after 2 days.

Solution 3

I found a workaround for this. It isn't pleasant but I think is't better than nothing. here I only wanted to preload woff and woff2 files.

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

Related videos on Youtube

Frank
Author by

Frank

I'm a digital archaeologist

Updated on June 04, 2022

Comments

  • Frank
    Frank almost 2 years

    I have a webpack4+babel bundler setup for a react web app. In a LESS file, I reference a local font. This font gets copied over to the dist folder on build and its filename is hashed. I want to be able to preload this font.

    Here is my LESS file:

    @font-face {
        font-family: 'Test';
        src: url('../fonts/test.ttf') format('truetype');
        font-weight: 400;
    }
    

    I have tried the following approaches but so far with no success:

    1. Add custom import to my app's main JS file.
    import(/* webpackPreload: true */ "../fonts/test.ttf");
    

    Here is my .babelrc file:

    {
        "presets": [
            "@babel/preset-env",
            "@babel/preset-react"
        ],
        "plugins": [
            "@babel/plugin-syntax-dynamic-import"
        ]
    }
    

    Running webpack does not produce preload directions anywhere as far as I can see in the outputted html - I have searched through the dist folder contents and found nothing.

    1. preload-webpack-plugin

    I add this to my webpack.config.js file:

    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';
        }
      })
    ]
    

    This creates preloads for the JS script file bundles but not for the CSS and fonts.

    Any ideas on how to get this to work?

  • Frank
    Frank about 5 years
    Thanks for the response but my problem is that the font filenames are hashed by webpack and so I don't know what they will be after they are copied across to the dist folder. Perhaps there is a way of using a placeholder in the HTML file?
  • GProst
    GProst about 5 years
    Are your font files going to change often? Why do you need to include them to your webpack compilation process? I think you can create another assets folder to server static files which don't need to be compiled by webpack in parallel with a dist folder and serve static files from this folder as well
  • Frank
    Frank about 5 years
    That's a fair point. The fonts won't change and even if they do, copying them across after the webpack build isn't too much effort. I presume that linking to the font files in the HTML (for preload) and also linking using @font-face in CSS (where they'll actually be used) is fine - i.e. once they are preloaded by the browser, then it won't bother doing so again?
  • GProst
    GProst about 5 years
    I don't think there is any other way of preloading fonts other than using link. So even if you used some Webpack preload solution it would just insert the link with preload attribute that would load your asset. So yes I believe a browser shouldn't make another request if it already preloaded the asset however I think you'd want to put some cache-control headers so that browser cached the asset.
  • Frank
    Frank about 5 years
    Cheers. Your recommended approach is now in and working well.
  • GProst
    GProst about 5 years
    Glad to hear that!
  • Brandon Minton
    Brandon Minton about 4 years
    not what the user was looking for but that helped me out +1
  • cbrwizard
    cbrwizard over 3 years
    This can be the best solution when you want only specific fonts to be preloaded.