Giter Site home page Giter Site logo

codeadrian / gatsby-omni-font-loader Goto Github PK

View Code? Open in Web Editor NEW
104.0 104.0 7.0 41 KB

Font loader optimized for maximum performance. Removes render-blocking font resources and loads them asynchronusly. Handle FOUT & FOUC with font loading status watcher. Supports both local-hosted fonts and web fonts.

License: MIT License

TypeScript 70.67% JavaScript 29.33%
css font gatsby react reactjs web-fonts

gatsby-omni-font-loader's People

Contributors

codeadrian avatar hugofabricio avatar lekoarts avatar mehimanshupatil avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

gatsby-omni-font-loader's Issues

Text flickers before switch to icon with Material Icons font

We've added this to our Gatsby project as a better way to load Material Icons from Google Fonts. Here is what we have for our config options:

resolve: 'gatsby-omni-font-loader',
options: {
    mode: 'async',
    enableListener: true,
    preconnect: ['https://fonts.gstatic.com'],
    preload: ['https://fonts.googleapis.com/css?family=Material+Icons+Sharp'],
    web: [{
	name: 'Material Icons Sharp',
	file: 'https://fonts.googleapis.com/css?family=Material+Icons+Sharp'
    }]
}

Unfortunately, it seems the listener triggers the wf-material-icons-sharp-all class before it's actually loaded and it shows the icon text before flickering to the icon. Any ideas on how to fix this?

Errors when leaving out settigs

Firstly thanks for the plugin, I was surprised that a plugin like this didn't already exist.

I seem to be getting errors when I leave out some of the settings in the plugin. Namely, with the following config:

      options: {
        /* Self-hosted fonts config. Add font files and font CSS files to "static" folder */`
        custom: [
          {
            /* Exact name of the font as defied in @font-face CSS rule */
            name: ['Open Sans'],
            /* Path to the font CSS file inside the "static" folder with @font-face definition */
            file: ['/fonts/fonts.css'],
          },
        ],
      },
    },

I get
Unhandled Rejection (TypeError): Invalid attempt to spread non-iterable instance.

I assume this is because I'm not providing web and preconnect arrays to the plugin.

So I add some just to get the build going:

        /* Preconnect URL-s. This example is for Google Fonts */
        preconnect: ['https://fonts.gstatic.com'],
        /* Web fonts. File link should point to font CSS file. */
        web: [],

but then Helmet gives the following error:

TypeError: tag[primaryAttributeKey].toLowerCase is not a function
in
node_modules/react-helmet/lib/HelmetUtils.js:121

I assume because something else again is not initialised.

Still looking into this though, but thought I would create an issue in the meantime :)

tag[primaryAttributeKey].toLowerCase is not a function

First of all, let me start by saying, we saw your original reddit post for this particular Gatsby plugin and read your blog post. We're blown away with the functionality and plan to use it in nearly every one of our sites. That being said...

We've encountered this issue twice, once on this site and once here. We'd love to try and get to the bottom of it, and I suspect it's related to this issue.

See screenshot:
Screenshot 2020-12-01 at 12 09 07

Integration with npm-typeface fonts

My Gatsby project is using npm-typefaces to self-host fonts, so the font files live in the node_modules folder.

For self-hosted fonts, the plugin requires a statically-typed path to the css file (i.e. the "file" param) where the @font-face lives.

In this case, using npm-typefaces, the filename of the css where the @font-face lives is determined at build time (e.g. /public/styles.46589de85f365befd1a4.css) and the fonts live in the public/static/ folder.

Is there a way to use this plugin with npm-typeface?

gatsby-browser.js causes issue in mono-repo

I'm working on adding this plugin to a theme which gatsby does by using yarn mono-repos. This causes the build to fail with

success createPages - 9.226s
success Checking for changed pages - 0.001s
success createPagesStatefully - 0.090s
success update schema - 0.294s
success write out redirect data - 0.002s
success Build manifest and related icons - 0.124s
success onPostBootstrap - 0.130s
info bootstrap finished - 17.981s
success onPreExtractQueries - 0.001s
success extract queries from components - 1.010s
success write out requires - 0.131s
success run static queries - 0.084s - 11/11 131.66/s
success run page queries - 0.044s - 2/2 45.00/s

 ERROR #98123  WEBPACK

Generating development JavaScript bundle failed

Unexpected token (31:4)

File: ../node_modules/gatsby-omni-font-loader/gatsby-browser.js:31:4

failed Building development bundle - 22.474s

Seems like there is a known fix for this following this example gatsbyjs/gatsby#19042 (comment)

Crossorigin value automatically assigned and the value is invalid.

When I analyzed my Gatsby website using omni font loader v2, I got an error crossorigin has an invalid value 'true' by HTML validator. It has to be 'anonymous' or empty.

There is not setting options for me to do with omni font loader for crossorigin but it renders 'true'.

<link rel="preconnect" href="https://fonts.googleapis.com" crossorigin="true"/>
Can anyone tell me how to fix it and/or add an optional setting for crossorigin, please?

My configuration

    {
      resolve: `gatsby-omni-font-loader`,
      options: {
        enableListener: true,
        preconnect: [
          `https://fonts.googleapis.com`,
          `https://fonts.gstatic.com`,
        ],
        web: [
          {
            name: `Jost`,
            file: `https://fonts.googleapis.com/css2?family=Jost:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap`,
          },
        ],
      },
    },

Thank you!

Add classes to HTML instead of the BODY

Hi, would it be possible to add the loaded classes on HTML instead of the Body?
This would allow setting styles at the root of the project instead of its first child.

I bring up this use case mainly because of rem units, which are relative to the font-size at the root.
So if you have the intention of using rem units anywhere, the font-size needs to be on HTML tag.

This could potentially be a new option scope: 'html/body', preventing breaking changes.

How to handle variants in async mode

Hello Adrian!

Congratulations and thank you for the awesome plugin!

It really handles font loading with ease. I have a specific example that I am not sure how to handle with gatsby-omni-font-loader and I would appreciate the help.

The problem is the following.

Custom fonts are specified in the custom config key.

Something like this:

custom: [
          {
            name: "MyCustomFontName",
            file: "/fonts.css",
          },
        ],

fonts.css looks something like this:

@font-face {
  font-family: "MyCustomFontName";
  font-weight: 300;
  src: url("path_to_font_300");
  font-display: swap;
}

@font-face {
  font-family: "MyCustomFontName";
  font-weight: 900;
  font-style: italic;
  src: url("path_to_font_900");
  font-display: swap;
}

This seems like a normal configuration, from what I saw in the documentation. However, although these fonts are very similar, their weights make a big difference in terms of the character width. gatsby-omni-font-loader waits for only one variant to be loaded, and in my case, the first one that needs to be shown on the page is not one that is loaded until then, which looks like an additional layout shift after the other one is loaded. I am using enableListener config which adds the loaded class to the body element.

Is there a way to wait for all the weights to load?

Preloading doesn't work when deploying with netlify

Currently I have a blog deployed using netlify but in the resulting head element I get

<link rel="preload" as="style" href="https://****.cloudfront.net/css/***/fonts/all.css">
...
<link rel="stylesheet" media="all" href="/fonts/all.css" data-react-helmet="true">
<noscript data-react-helmet="true"><link rel="stylesheet" href="/fonts/all.css" /></noscript>

Where only the first link has the cdn attached. So when running lighthouse I still get an error telling me to Preload key requests specifying that fonts/all.css request.

I'm not sure exactly what netlify is doing, but I tried locally adding a assetPrefix (assetPrefix: 'http://localhost:9000/') and running gatsby build --prefix-paths to simulate a cdn path, but that ended up with neither of the font paths getting prefixed (although all other assets not handled by the plugin were getting it).

My plugin options are

{
      /* Include plugin */
      resolve: "gatsby-omni-font-loader",

      /* Plugin options */
      options: {

        /* Font loading mode */
        mode: "async",

        /* Enable font loading listener to handle FOUT */
        enableListener: true,

        /* Font listener interval (in ms). Default is 300ms. Recommended: >=300ms */
        interval: 300,

        /* Font listener timeout value (in ms). Default is 30s (30000ms). Listener will no longer check for loaded fonts after timeout, fonts will still be loaded and displayed, but without handling FOUT. */
        timeout: 30000,

        /* Self-hosted fonts config. Add font files and font CSS files to "static" folder */
        custom: [
          {
            /* Exact name of the font as defied in @font-face CSS rule */
            name: ['Karbon', 'Open Sans'],
            /* Path to the font CSS file inside the "static" folder with @font-face definition */
            file: "/fonts/all.css",
          },
        ],
      },
    },

Not sure if file: "/fonts/all.css", needs to change or if something else on my end should be updated.

Any help is appreciated. Thanks!

Feature Request: Remove usage of `react-helmet`

Hi!

With Gatsby 4.19 a Head API was released: https://www.gatsbyjs.com/docs/reference/release-notes/v4.19/#gatsby-head-api

I'm slowly removing react-helmet from all my projects and replace it with the Head API. To be able to completely remove that react-helmet dependency this plugin would need to not rely on react-helmet.

While you can't use Gatsby Head API for your plugin, you can use the normal setHeadComponents API. Or did you run into any problems when using that and opted for react-helmet? :)

Happy to help with guidance on how to remove that peerDep.

Thanks!

Module parse failed - potential Webpack config conflict

Hi,

I just tried replacing gatsby-plugin-web-font-loader with your loader, as your blog neatly summated the problems with the former! My latest project is running on Gatsby v3 and I get a non-fatal error in develop-mode:

ERROR Failed to compile with 6 errors 17:39:23

error in ./node_modules/gatsby-omni-font-loader/components/AsyncFonts.tsx

Module parse failed: Unexpected token (7:23)
File was processed with these loaders:

  • ./node_modules/@pmmmwh/react-refresh-webpack-plugin/loader/index.js
    You may need an additional loader to handle the result of these loaders.
    | import { Helmet } from "react-helmet"
    |

export const AsyncFonts: React.FC<{ hrefs: string[] }> = ({ hrefs }) => {
| const links = []
|

error in ./node_modules/gatsby-omni-font-loader/components/FontListener.tsx

Module parse failed: The keyword 'interface' is reserved (7:0)
File was processed with these loaders:

  • ./node_modules/@pmmmwh/react-refresh-webpack-plugin/loader/index.js
    You may need an additional loader to handle the result of these loaders.
    | import { hookOptions, useFontListener } from "../hooks"
    |

interface Props {
| options: hookOptions
| }

error in ./node_modules/gatsby-omni-font-loader/utils/arrayCheck.ts

Module parse failed: Unexpected token (4:31)
File was processed with these loaders:

  • ./node_modules/@pmmmwh/react-refresh-webpack-plugin/loader/index.js
    You may need an additional loader to handle the result of these loaders.
    | $RefreshSetup$(module.id);
    |

export const arrayCheck = (arr?: unknown) =>
| arr && Array.isArray(arr) && Boolean(arr.length)
|

error in ./node_modules/gatsby-omni-font-loader/utils/getFontFiles.ts

Module parse failed: Unexpected token (4:37)
File was processed with these loaders:

  • ./node_modules/@pmmmwh/react-refresh-webpack-plugin/loader/index.js
    You may need an additional loader to handle the result of these loaders.
    | $RefreshSetup$(module.id);
    |

export const getFontFiles = (allFonts: { file: string }[]) =>
| allFonts.map(({ file }) => file)
|

error in ./node_modules/gatsby-omni-font-loader/utils/getFontNames.ts

Module parse failed: Unexpected token (4:37)
File was processed with these loaders:

  • ./node_modules/@pmmmwh/react-refresh-webpack-plugin/loader/index.js
    You may need an additional loader to handle the result of these loaders.
    | $RefreshSetup$(module.id);
    |

export const getFontNames = (allFonts: { name: string }[]) => {
| const fontNames = []
| allFonts.forEach(({ name }) =>

error in ./node_modules/gatsby-omni-font-loader/utils/kebabCase.ts

Module parse failed: Unexpected token (4:29)
File was processed with these loaders:

  • ./node_modules/@pmmmwh/react-refresh-webpack-plugin/loader/index.js
    You may need an additional loader to handle the result of these loaders.
    | $RefreshSetup$(module.id);
    |

export const kebabCase = (str: string) =>
| str
| .match(/[A-Z]{2,}(?=[A-Z][a-z0-9]|\b)|[A-Z]?[a-z0-9]|[A-Z]|[0-9]+/g)

The error on build is fatal and seems to include a conflict with netlify-cms:

ERROR #11321 PLUGIN

"gatsby-plugin-netlify-cms" threw an error while running the onCreateWebpackConfig lifecycle:

Module parse failed: Unexpected token (4:23)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See
https://webpack.js.org/concepts#loaders
| import { Helmet } from "react-helmet"
|

export const AsyncFonts: React.FC<{ hrefs: string[] }> = ({ hrefs }) => {
| const links = []
|

ModuleParseError: Module parse failed: Unexpected token (4:23)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See h
ttps://webpack.js.org/concepts#loaders
| import { Helmet } from "react-helmet"
|

export const AsyncFonts: React.FC<{ hrefs: string[] }> = ({ hrefs }) => {
| const links = []
|

My package.json dependencies are:

"dependencies": {
"@ccalamos/gatsby-source-googlemaps-static": "^3.1.1",
"babel-plugin-styled-components": "^1.12.0",
"gatsby": "^3.4.1",
"gatsby-background-image": "^1.5.3",
"gatsby-plugin-env-variables": "^2.1.0",
"gatsby-plugin-gatsby-cloud": "^2.4.1",
"gatsby-plugin-image": "^1.4.0",
"gatsby-plugin-manifest": "^3.4.0",
"gatsby-plugin-modal-routing-3": "^3.0.0",
"gatsby-plugin-netlify-cms": "^5.4.1",
"gatsby-plugin-offline": "^4.4.0",
"gatsby-plugin-react-helmet": "^4.4.0",
"gatsby-plugin-react-svg": "^3.0.1",
"gatsby-plugin-sharp": "^3.5.0",
"gatsby-plugin-smoothscroll": "^1.2.0",
"gatsby-plugin-styled-components": "^4.4.0",
"gatsby-plugin-web-font-loader": "^1.0.4",
"gatsby-remark-copy-linked-files": "^4.2.1",
"gatsby-remark-images": "^5.2.1",
"gatsby-remark-relative-images": "^2.0.2",
"gatsby-source-filesystem": "^3.4.0",
"gatsby-transformer-remark": "^4.1.0",
"gatsby-transformer-sharp": "^3.4.0",
"gbimage-bridge": "^0.1.4",
"google-map-react": "^2.1.9",
"intersection-observer": "^0.12.0",
"netlify-cms-app": "^2.15.2",
"prop-types": "^15.7.2",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-google-recaptcha": "^2.1.0",
"react-helmet": "^6.1.0",
"react-masonry-component": "^6.2.1",
"react-slick": "^0.28.1",
"react-slick-ios-fix": "^0.24.8",
"react-transition-group": "^4.4.1",
"remark": "^13.0.0",
"remark-html": "^13.0.1",
"request-animation-frame-polyfill": "^1.1.2",
"slick-carousel": "^1.8.1",
"styled-components": "^5.3.0",
"use-fit-text": "^2.4.0"
}

I'm node -v 16 ( I should really be on 14) don't know if this could cause the problem? Would be grateful for your insight?

Thanks

Module not found: Error: Can't resolve './defaults' in '.../node_modules/gatsby-omni-font-loader/consts'

Trying to start developing from this starter, but when I run gatsby develop I get the following error. Seems to be an issue with trying to export functions from a *.ts file in a *.js file.

Any ideas?

error There was an error compiling the html.js component for the development server.

See our docs page on debugging HTML builds for help https://gatsby.dev/debug-html


  Error: ./node_modules/gatsby-omni-font-loader/consts/index.js
  Module not found: Error: Can't resolve './defaults' in '.../node_modules/gatsby-omni-font-loader/consts'
  resolve './defaults' in '.../node_modules/gatsby-omni-font-loader/consts'
    using description file: .../node_modules/gatsby-omni-font-loader/package.json (relative path: ./consts)
      using description file: .../node_modules/gatsby-omni-font-loader/package.json (relative path: ./consts/d
  efaults)
        no extension
          .../node_modules/gatsby-omni-font-loader/consts/defaults doesn't exist
        .mjs
          .../node_modules/gatsby-omni-font-loader/consts/defaults.mjs doesn't exist
        .js
          .../node_modules/gatsby-omni-font-loader/consts/defaults.js doesn't exist
        .jsx
          .../node_modules/gatsby-omni-font-loader/consts/defaults.jsx doesn't exist
        .wasm
          .../node_modules/gatsby-omni-font-loader/consts/defaults.wasm doesn't exist
        .json
          .../node_modules/gatsby-omni-font-loader/consts/defaults.json doesn't exist
        as directory
          .../node_modules/gatsby-omni-font-loader/consts/defaults doesn't exist
  [.../node_modules/gatsby-omni-font-loader/consts/defaults]
  [.../node_modules/gatsby-omni-font-loader/consts/defaults.mjs]
  [.../node_modules/gatsby-omni-font-loader/consts/defaults.js]
  [.../node_modules/gatsby-omni-font-loader/consts/defaults.jsx]
  [.../node_modules/gatsby-omni-font-loader/consts/defaults.wasm]
  [.../node_modules/gatsby-omni-font-loader/consts/defaults.json]
   @ ./node_modules/gatsby-omni-font-loader/consts/index.js 1:0-26 1:0-26
   @ ./node_modules/gatsby-omni-font-loader/gatsby-ssr.js
   @ ./.cache/api-runner-ssr.js
   @ ./.cache/develop-static-entry.js

Error: Failed to decode downloaded font: <URL>

Hi Adrian,

I am getting this error in console, when I try to use the plugin. The fonts don't show but the bundle is developed, and site works.

Here is my folder structure:

├───src     
│   ├───components
│   │       all.sass
└───static
    ├───fonts
    │       local_fonts.css
    │       montserrat-latin-ext-400-italic.woff
    │       montserrat-latin-ext-400-italic.woff2
    │       montserrat-latin-ext-400-normal.woff
    │       montserrat-latin-ext-400-normal.woff2

local_fonts.css:

@font-face {
  font-family: "Montserrat";
  font-style: normal;
  font-display: swap;
  font-weight: 400;
  src: url("/montserrat-latin-ext-400-normal.woff2") format("woff2"),
    url("/montserrat-all-400-normal.woff") format("woff");
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB,
    U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: "Montserrat";
  font-style: italic;
  font-display: swap;
  font-weight: 400;
  src: url("/montserrat-latin-ext-400-italic.woff2") format("woff2"),
    url("/montserrat-all-400-italic.woff") format("woff");
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB,
    U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

imported to all.sass like this:

@import "../../static/fonts/local_fonts.css"

gatsby-config.js:

    {
      /* Include plugin */
      resolve: "gatsby-omni-font-loader",

      /* Plugin options */
      options: {
        /* Enable font loading listener to handle FOUC */
        enableListener: true,

        /* Self-hosted fonts config. Add font files and font CSS files to "static" folder */
        custom: [
          {
            /* Exact name of the font as defied in @font-face CSS rule */
            name: ["Montserrat"],
            /* Path to the font CSS file inside the "static" folder with @font-face definition */
            file: "/fonts/local_fonts.css",
          },
        ],
      },
    }

This is probably my mistake because I am new to all this. Any tips would be appreciated.

Thanks.

Setting MIME type?

Running into an issue where the browser is giving this error.

The stylesheet http://localhost:8000/ParalucentCondensedHeavy/paralucentCondensedHeavy.css was not loaded because its MIME type, “text/html”, is not “text/css”.

Does the plugin handle MIME type setting?

More complex example

I think it would be nice with a more specific and complete example of how to configure and use this plugin.

  • Two Google fonts, one of them with multiple weights and styles.
  • How to use the fonts in the CSS.

Only load fonts that are used in a page

I have a website where some pages use one font and other pages use another. How could I go about using all this plugin's optimizations (e.g. for FOUT) without loading all the fonts my site uses for every page?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.