0

I would like to preload Material Icons font thanks to:

<link rel="preload" href="https://fonts.gstatic.com/s/materialicons/v125/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2" as="font" type="font/woff2" crossorigin="anonymous">

In fact, it works!

However, in the filename, we have a hash/UUID: v125/flUhRq6tzZclQEJ-Vdg-IuiaDsNc; consequently, if Google publishes a new release, for example v126/sjboabchdiamblq-Abf-abvichef, then my preload won't work!

For more details, I use their CDN like this:

<link
  href="https://fonts.googleapis.com/icon?family=Material+Icons"
  rel="stylesheet"
/>

Which returns this CSS:

@font-face {
  font-family: 'Material Icons';
  font-style: normal;
  font-weight: 400;
  src: url(https://fonts.gstatic.com/s/materialicons/v125/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2) format('woff2');
}

.material-icons {
  font-family: 'Material Icons';
  [...]
}

Notice: I'm working with Angular, and I want the loading of the font start immediately, and not when the application is loaded, i.e. when a Material Icon is displayed.Moreover, even if the CSS file loads immediately, the font won't start loading until a Material Icon is displayed.

Jérémie RPK
  • 297
  • 4
  • 13

1 Answers1

0

I found a solution, thanks to https://www.npmjs.com/package/@angular-builders/custom-webpack, and using a library for mMaterial Icons (https://www.npmjs.com/package/material-icons)

This builder allows to transform the index.html after the build process.

  1. Add classic preloading in index.html (works in dev)
<link rel="preload" href="/material-icons.woff2" as="font" type="font/woff2" crossorigin="anonymous">
<link rel="preload" href="/material-icons-outlined.woff2" as="font" type="font/woff2" crossorigin="anonymous">
  1. Add "indexTransform": "index-html-transform.js" in angular.json like this:
"configurations": {
  "production": {
    [...],
    "indexTransform": "index-html-transform.js"
  }
}
  1. Create index-html-transform.js:
const fs = require("fs");

/**
 * @param {string} indexHtmlSource
 * @return {string}
 */
const setMaterialIconsFontsPreloading = (indexHtmlSource) => {
  const allOutputFilenames = fs.readdirSync("./dist/essai-preload-mat-icons");

  const requiredMatIconsFontsMatches = indexHtmlSource.matchAll(/(material-icons.*)\.woff2/g);

  /**
   * @exemple `['material-icons', 'material-icons-outlined']`
   */
  const requiredIconTypes = [...requiredMatIconsFontsMatches].map((match) => match[1]);

  return requiredIconTypes.reduce((previousIndexHtml, requiredIconType) => {
    /**
     * @exemple `'material-icons-outlined.woff2'`
     */
    const inputFilename = `${requiredIconType}.woff2`;

    /**
     * @exemple `'material-icons-outlined.125af8545b6.woff2'`
     */

    const outputFilename = allOutputFilenames.find((outputFilenameItem) => outputFilenameItem.match(`^${requiredIconType}\\.\\w+\\.woff2$`));

    return previousIndexHtml.replace(inputFilename, outputFilename);
  }, indexHtmlSource);
}

/**
 *
 * @param {{ configuration?: string; project: string; target: string;}} targetOptions
 * @param {string} indexHtmlSource
 * @returns {string} The final index.html to serve.
 */
module.exports = (targetOptions, indexHtmlSource) => {
    return setMaterialIconsFontsPreloading(indexHtmlSource);
};
Jérémie RPK
  • 297
  • 4
  • 13