npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

vite-plugin-webfont-dl

v3.11.1

Published

Vite plugin for downloading and injecting webfonts

Readme

🔠 Webfont Download Vite Plugin ⚡

NPM NPM downloads all-time NPM downloads last month

Automatically collects webfont links, imports, and definitions from your Vite project, downloads CSS and font files (privacy-first), adds the fonts to your bundle (or serves them through the dev server), and injects font definitions using a non-render-blocking method. External CSS and font files are stored in a persistent file cache, making them available for offline development.

📦 Install

npm i vite-plugin-webfont-dl -D

📖 Table of Contents

  1. 📦 Install
  2. Usage:
  3. 🚀 That's all!
  4. 🧩 Supported webfont providers
  5. 🛠️ Options
  6. Third-party webfonts
  7. 🔮 How it works
  8. 📊 Benchmark
  9. 📚 Resources
  10. 📄 License

😎 Usage: Zero config [method A]

Extracts, downloads, and injects fonts from the original Google Fonts code snippet.

  1. Select your font families from your webfont provider (e.g. Google Fonts) and copy the code from the "Use on the web" block into your <head>:
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@300;400&family=Roboto:wght@100&display=swap" rel="stylesheet">
  2. Add webfontDownload to your Vite plugins without any configuration. The plugin will automatically handle everything:
    // vite.config.js
    
    import webfontDownload from 'vite-plugin-webfont-dl';
    
    export default {
      plugins: [
        webfontDownload(),
      ],
    };
  3. The original webfont tags will be replaced in dist/index.html:
    <style>@font-face{font-family:...;src:url(/assets/foo-xxxxxxxx.woff2) format('woff2'),url(/assets/bar-yyyyyyyy.woff) format('woff')}...</style>

🦄 Usage: Simple config [method B]

Extracts, downloads, and injects fonts from the configured webfont CSS URL(s).

  1. Select your font families from your webfont provider (e.g. Google Fonts) and copy the CSS URL(s) from the "Use on the web" code block:
    <link href="[CSS URL]" rel="stylesheet">
  2. Add webfontDownload to your Vite plugins with the selected Google Fonts CSS URL(s):
    // vite.config.js
    
    import webfontDownload from 'vite-plugin-webfont-dl';
    
    export default {
      plugins: [
        webfontDownload([
          'https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap',
          'https://fonts.googleapis.com/css2?family=Fira+Code&display=swap'
        ]),
      ],
    };

🚀 That's all!

The webfonts are injected and ready to use. The plugin works seamlessly whether you are running a local development server or building for production.

h1 {
  font-family: 'Press Start 2P', cursive;
}

h2 {
  font-family: 'Fira Code', monospace;
}

🔌 Laravel

To use with the Laravel Vite Plugin, add this line to your Blade file:

@vite('webfonts.css')

📸 Screenshot

🧩 Supported webfont providers

🛠️ Options

  • injectAsStyleTag (boolean, default: true): Inject webfonts as a <style> tag (embedded CSS) or as an external .css file.

  • minifyCss (boolean, default: value of build.minify): Minify CSS code during the build process.

  • embedFonts (boolean, default: false): Embed base64-encoded fonts into CSS. In some cases, this can increase the file size if the CSS contains multiple references to the same font file. Example

  • async (boolean, default: true): Prevents the use of inline event handlers in webfonts.css that can cause Content Security Policy issues. Only applicable when injectAsStyleTag:false.

  • cache (boolean, default: true): Persistently stores downloaded CSS and font files in a local file cache. If set to false, the existing cache will be deleted.

  • proxy (false|AxiosProxyConfig, default: false): Proxy configuration for network requests.

  • assetsSubfolder (string, default: ''): Moves downloaded font files to a separate subfolder within the assets directory.

  • throwError (boolean, default: false): If set to true, the plugin will throw an error and stop the build if any font download or processing fails. If false, errors are logged as warnings and the build continues.

  • subsetsAllowed (string[], default: []): Restricts downloaded fonts to the specified Unicode subsets (e.g., ['latin', 'cyrillic']). Only font files matching these subsets will be included. Leave empty to allow all subsets.

Usage example:

ViteWebfontDownload(
  [],
  {
    injectAsStyleTag: true,
    minifyCss: true,
    embedFonts: false,
    async: true,
    cache: true,
    proxy: false,
    assetsSubfolder: '',
  }
)

Or:

ViteWebfontDownload(
  [
    'https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap',
  ],
  {
    injectAsStyleTag: true,
    minifyCss: true,
    embedFonts: false,
    async: true,
    cache: true,
    proxy: false,
    assetsSubfolder: '',
  }
)

❓ Third-party webfonts

⚠️ Using the standard method to add third-party webfonts (Google Fonts, Bunny Fonts or Fontshare) to a webpage can significantly slow down page load. Lighthouse and PageSpeed Insights call them "render-blocking resources", which means the page can't fully render until the webfonts CSS has been fetched from the remote server.

📈 By avoiding render-blocking resources caused by third-party webfonts, you can boost page performance, leading to a better user experience and improved SEO results.

⚙️ The plugin downloads the specified fonts from the third-party webfont service (like Google Fonts) and dynamically injects them (as an internal or external stylesheet) into your Vite project, transforming third-party webfonts into self-hosted ones. 🤩

🔐 In addition to the significant performance increase, your visitors will also benefit from privacy protection, since there is no third-party server involved.

🔮 How it works

📉 Google Fonts

Google Fonts generates the following code, which you have to inject into your website's <head>, example:

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fira+Code&display=swap" rel="stylesheet">

📱 What happens on the client-side with Google Fonts:

  1. The first line gives a hint to the browser to begin the connection handshake (DNS, TCP, TLS) with fonts.googleapis.com. This happens in the background to improve performance. [preconnect]
  2. The second line is another preconnect hint to fonts.gstatic.com. [preconnect]
  3. The third line instructs the browser to load and use a CSS stylesheet file from fonts.googleapis.com (with font-display:swap). [stylesheet]
  4. The browser downloads the CSS file and starts to parse it. The parsed CSS is a set of @font-face definitions containing font URLs from the fonts.gstatic.com server.
  5. The browser starts to download all relevant fonts from fonts.gstatic.com.
  6. After the fonts are successfully downloaded, the browser swaps the fallback fonts for the downloaded ones.

🆚

📈 Webfont-DL Vite Plugin

In contrast, the Webfont-DL plugin does most of the work at build time, leaving minimal work for the browser.

Webfont-DL plugin

  • Collects the webfont CSS URLs (from plugin config, index.html, and generated CSS)
  • Downloads the webfont CSS file(s)
  • Extracts the font URLs
  • Downloads the fonts
  • Adds the fonts to the bundle
  • Generates embedded CSS (<style> tag) or an external webfont CSS file
  • Adds them to the bundle and injects the following code into your website's <head> using a non-render-blocking method, example:
<style>
  @font-face {
    font-family: 'Fira Code';
    font-style: normal;
    font-weight: 300;
    font-display: swap;
    src: url(/assets/uU9eCBsR6Z2vfE9aq3bL0fxyUs4tcw4W_GNsJV37Nv7g.9c348768.woff2) format('woff2');
    unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
  }
  ...
</style>

Or (using the dev server or injectAsStyleTag: false option):

<link rel="preload" as="style" href="/assets/webfonts.b904bd45.css">
<link rel="stylesheet" media="print" onload="this.onload=null;this.removeAttribute('media');" href="/assets/webfonts.b904bd45.css">

📱 What happens on the client-side with the Webfont-DL plugin:

  1. Loads fonts from the embedded CSS (<style> tag).

Or

  1. The first line instructs the browser to prefetch a CSS file for later use as a stylesheet. [preload]
  2. The second line instructs the browser to load and use that CSS file as a print stylesheet (non-render-blocking). After loading, it is promoted to an all media type stylesheet (by removing the media attribute). [stylesheet]

📊 Benchmark

Starter Vite project with

| ▶️ Standard Google Fonts | 🆚 | ▶️ Webfont DL Vite plugin | |:---:|:---:|:---:| | 🔗 webfont.feat.agency | | 🔗 webfont-dl.feat.agency |

Compare

📚 Resources

📄 License

MIT License © 2022 feat.