Code Monkey home page Code Monkey logo

nuxt-font-loader-strategy's Introduction

nuxt-font-loader-strategy

โš ๏ธ This project is no longer maintained, because the concept is not suitable for global management of many fonts in larger projects. For this reason we have developed a new concept that guarantees smart, efficient and performant component-based font management even in larger websites. Please visit: https://github.com/GrabarzUndPartner/nuxt-speedkit

Grabarz & Partner - Module

Main

npm version npm downloads Renovate - Status License

Helps to load the fonts and activate them by preloading.

nuxt-font-loader-strategy helps loading the fonts and provides a loading strategy based on preloads.

Define yourself which fonts will be unlocked first.
This gives the best experience in the initial viewport of the website.

Features:

  • Use preload to prevent font flashs.
  • Generates the @font-face definitions automatically and includes them in the layout.
  • Increases the Pagespeed Insight Score ๐ŸŽ‰
  • Take the fonts from Minimize critical request depth and load them via WebWorker.
  • Deactivate fonts at low connection. (Show Browser-Support)

โš ๏ธ Configuration of the fonts must be included only in the module settings.

๐Ÿ“– Release Notes

Setup

  1. Add nuxt-font-loader-strategy dependency to your project
yarn add nuxt-font-loader-strategy # or npm install nuxt-font-loader-strategy
  1. Add nuxt-font-loader-strategy to the modules section of nuxt.config.js
{
  modules: [

    ['nuxt-font-loader-strategy', { 
        ignoreLighthouse: true,
        ignoredEffectiveTypes: ['2g', 'slow-2g'],
        fonts: [
          // Font
          {
            fileExtensions: ['woff2', 'woff'],
            fontFamily: 'Font A',
            fontFaces: [
              // Font-Face
              {
                preload: true,
                localSrc: ['Font A', 'FontA-Regular'],
                src: '@/assets/fonts/font-a-regular',
                fontWeight: 400,
                fontStyle: 'normal'
              },
              // Font-Face
              {
                localSrc: ['Font A Light', 'FontA-Light'],
                src: '@/assets/fonts/font-a-300',
                fontWeight: 300,
                fontStyle: 'normal'
              },
              // Font-Face
              {
                localSrc: ['Font A Light Italic', 'FontA-LightItalic'],
                src: '@/assets/fonts/font-a-300Italic',
                fontWeight: 300,
                fontStyle: 'Italic'
              }
            ]
          },
          // Font
          {
            fileExtensions: ['woff2', 'woff'],
            fontFamily: 'Font B',
            fontFaces: [
              // Font-Face
              {
                preload: true,
                src: '@/assets/fonts/font-b-regular',
                fontWeight: 400,
                fontStyle: 'normal'
              },
              // Font-Face
              {
                src: '@/assets/fonts/font-b-700',
                fontWeight: 700,
                fontStyle: 'normal'
              }
            ]
          }
        ]
    }]

  ]
}

Options

Property Type Description Default
useWorker Boolean If set, the non-preloads (prefetches) are loaded via WebWorker. false
ignoreLighthouse Boolean If set, the non-preloads (prefetches) in Lighthouse are disabled (ignored). false
classPattern Boolean Font css class pattern. [family]_[weight]_[style]
importPathResolve Function Path resolve for font src: url(fontPath) Replace @/ to ~
requirePathResolve Function Path resolve for require(fontPath) no changes
ignoredEffectiveTypes Array List of excluded connection types. []
fonts Array List of included fonts. []
unlockDelay Number Delay in milliseconds for unlock prefetched fonts. 0
prefetchCount Number Defines how many fonts are prefetched at the same time.
Important: Lower than zero, everything is loaded at once.
2

Maximum expression classPattern

[family]_[variant]_[featureSettings]_[stretch]_[weight]_[style]

WebWorker useWorker

Look for compactability at https://github.com/webpack-contrib/worker-loader.

WebWorker is executed with the setting inline to reduce the script loads.

Font

Property Type Description Default
fileExtensions Array Font-Family Name ['woff2', 'woff']
fontFamily String Font-Family Name ['2g', 'slow-2g']
fontFaces Array Font-Faces []

Font-Face

Property Type Description Default
preload Boolean Specifies whether font is loaded as preload. false
local Array List of local font names (System, etc.). []
src Array File Path without extension. null
fontVariant String CSS-Prop. font-variant 'normal'
fontFeatureSettings String CSS-Prop. font-feature-settings 'normal'
fontStretch String CSS-Prop. font-stretch 'normal'
fontWeight Number CSS-Prop. font-weight 'normal'
fontStyle String CSS-Prop. font-style 'normal'
fontDisplay String CSS-Prop. font-display 'swap'

โš ๏ธ The first fileExtensions entry is used as preload.

Usage

On the HTML tag a class is set for each font file. This class then activates the set styles in the CSS.

The name of the font is specified in SnakeCase. (Example: Open Sans -> open_sans)

It is recommended to normalize the used tags.

Example: h1 has font-weight: bold as standard.

p {
  font-family: sans-serif;
}

html.font_open_sans p {
  font-family: 'Roboto', sans-serif;
}

For additional FontFaces, classes switch with the options weight and style.

p {
  font-family: sans-serif;
}

html.font_roboto_400_normal p.bold {
  font-family: 'Roboto', sans-serif;
  font-style: normal;
  font-weight: 400;
}

p.bold {
  font-family: sans-serif;
  font-style: normal;
  font-weight: 700;
}

html.font_roboto_700_normal p.bold {
  font-family: 'Roboto', sans-serif;
}

p.light {
  font-family: sans-serif;
  font-style: normal;
  font-weight: 300;
}

html.font_roboto_300_normal p.light {
  font-family: 'Roboto', sans-serif;
}

p.italic {
  font-family: sans-serif;
  font-style: italic;
  font-weight: 400;
}

html.font_roboto_400_italic p.italic {
  font-family: 'Roboto', sans-serif;
}

Browser Performance

alt text

Preview

Development

  1. Clone this repository
  2. Install dependencies using yarn install or npm install
  3. Start development server using npm run dev

Browser-Support

Preload Fonts

The options preload and prefetch are required for the link tag.

Not all browsers support this:

If not supported, all fonts are activated.

Deactivate fonts at low connection

Connection speed dependent font loading, requires the support of navigator.connection.effectiveType.

Can I use - effectivetype

License

MIT License

nuxt-font-loader-strategy's People

Contributors

renovate-bot avatar semantic-release-bot avatar stephangerbeth avatar thornwalli 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

Watchers

 avatar  avatar  avatar  avatar

Forkers

d3c0d3dpt

nuxt-font-loader-strategy's Issues

Unsupported type warning in chrome for truetype font

In Chrome there is warning when using ttf extensions with preload.

<link rel=preload has an unsupported type value

The type="font/truetype" seems invalid.

Can this somehow be overwritten with a valid type or what can be done about this warning?

TypeError: (intermediate value).flat is not a function - Deploying to Netlify

I'm trying to deploy to Netlify, running npm run generate works locally but not on their server.

This is the error from the log:
1:26:30 PM:  FATAL  (intermediate value).flat is not a function
1:26:30 PM:   at prepareFonts (node_modules/nuxt-font-loader-strategy/lib/utils/fontFace.js:56:8)
1:26:30 PM:   at process._tickCallback (internal/process/next_tick.js:68:7)
1:26:30 PM:   at Function.Module.runMain (internal/modules/cjs/loader.js:834:11)
1:26:30 PM:   at startup (internal/bootstrap/node.js:283:19)
1:26:30 PM:   at bootstrapNodeJSCore (internal/bootstrap/node.js:623:3)
1:26:30 PM:    โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
1:26:30 PM:    โ”‚                                                            โ”‚
1:26:30 PM:    โ”‚   โœ– Nuxt Fatal Error                                       โ”‚
1:26:30 PM:    โ”‚                                                            โ”‚
1:26:30 PM:    โ”‚   TypeError: (intermediate value).flat is not a function   โ”‚
1:26:30 PM:    โ”‚                                                            โ”‚
1:26:30 PM:    โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

And this is the .js file:

    import { extname } from 'path'
    import { paramCase, snakeCase } from 'change-case'
    
    // Font-Face
    
    const FONTFACE_PROPERTIES = {
      fontFamily: null,
      fontUnicodeRange: null,
      fontVariant: 'normal',
      fontFeatureSettings: 'normal',
      fontStretch: 'normal',
      fontWeight: 'normal',
      fontStyle: 'normal',
      fontDisplay: 'swap'
    }
    
    const DEFAULT_FONT_EXTENSIONS = ['woff2', 'woff']
    
    const DEFAULT_CLASS_PATTERN = '[family]_[variant]_[featureSettings]_[stretch]_[weight]_[style]'
    
    export function getFontClasses (pattern, set, properties) {
      pattern = pattern || DEFAULT_CLASS_PATTERN
      const className = Object.keys(properties).reduce((result, key) => {
        let name = key.replace(/^font/, '')
        name = name.replace(/^.{1}/, name[0].toLowerCase())
        let value = properties[String(key)]
        if (name === 'family') {
          value = set
        }
        result = result.replace(`[${name}]`, value)
        return result
      }, pattern)
      return [`font_${set}`, `font_${className}`]
    }
    
    export async function prepareFonts (options, resolve, kebabCaseProps = true) {
      const { fonts, classPattern } = options
      return (await Promise.all(fonts.map((font) => {
        const fileExtensions = getFileExtensions(font)
        return font.fontFaces.map((face) => {
          const sources = prepareSrc(face.src, fileExtensions, resolve)
          const properties = getProperties(
            Object.assign({ fontFamily: `${font.fontFamily}` }, face),
            kebabCaseProps ? paramCase : name => name
          )
          const set = snakeCase(font.fontFamily)
          return {
            classes: getFontClasses(classPattern, set, properties),
            properties,
            sources,
            set,
            preload: face.preload || false,
            local: [].concat(face.local || [])
          }
        })
      }))).flat()  /*This is where the error is reported to be on Netlify*/
    }
    
    export function createFontFace (font, baseUrl) {
      const props = font.properties
      const options = {
        display: props.fontDisplay,
        style: props.fontStyle,
        weight: props.fontWeight,
        unicodeRange: props.fontUnicodeRange,
        variant: props.fontVariant,
        featureSettings: props.fontFeatureSettings,
        stretch: props.fontStretch
      }
      const src = `url(${baseUrl + font.sources[0].path})`
      return new FontFace(props.fontFamily.replace(/'/g, ''), src, options)
    }
    
    function getFileExtensions (font) {
      if (Array.isArray(font.fileExtensions) && font.fileExtensions.length > 0) {
        return font.fileExtensions
      } else {
        return DEFAULT_FONT_EXTENSIONS
      }
    }
    function getFormat (path) {
      return extname(path).replace(/^\./, '')
    }
    
    function getProperties (face, transform = paramCase) {
      return Object.keys(FONTFACE_PROPERTIES).reduce((result, prop) => {
        const value = face[prop] || FONTFACE_PROPERTIES[prop]
        if (value) {
          result[transform(prop)] = value
        }
        return result
      }, {})
    }
    
    function prepareSrc (src, fileExtensions, pathResolve) {
      return fileExtensions.map((fileExtension) => {
        const filePath = src + '.' + fileExtension
        return {
          path: pathResolve(filePath),
          format: getFormat(filePath)
        }
      })
    }

Can you advise on how to fix this?

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Repository problems

These problems occurred while renovating this repository. View logs.

  • WARN: Using npm packages for Renovate presets is now deprecated. Please migrate to repository-based presets instead.

Warning

These dependencies are deprecated:

Datasource Name Replacement PR?
npm @nuxtjs/module-test-utils Unavailable
npm babel-eslint Available
npm codecov Unavailable
npm standard-version Available

Rate-Limited

These updates are currently rate-limited. Click on a checkbox below to force their creation now.

  • chore(deps): update devdependency eslint to v9
  • chore(deps): update devdependency eslint-plugin-json to v4
  • chore(deps): update devdependency husky to v9
  • chore(deps): update devdependency lint-staged to v15
  • chore(deps): update devdependency pinst to v3
  • chore(deps): update devdependency postcss-nesting to v12
  • chore(deps): update devdependency stylelint to v16
  • chore(deps): update devdependency stylelint-config-recess-order to v5
  • chore(deps): update devdependency stylelint-config-standard to v36
  • chore(deps): update github/codeql-action action to v3
  • chore(deps): update jest monorepo to v29 (major) (babel-jest, jest)
  • chore(deps): update peaceiris/actions-gh-pages action to v4
  • ๐Ÿ” Create all rate-limited PRs at once ๐Ÿ”

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/codeql-analysis.yml
  • actions/checkout v2
  • github/codeql-action v1
  • github/codeql-action v1
  • github/codeql-action v1
.github/workflows/main.yml
  • actions/setup-node v2
  • actions/checkout v2
  • actions/cache v2
  • actions/setup-node v2
  • actions/checkout v2
  • actions/setup-node v2
  • actions/checkout v2
  • actions/cache v2
  • peaceiris/actions-gh-pages v3
.github/workflows/test.yml
  • actions/setup-node v2
  • actions/checkout v2
  • actions/cache v2
npm
package.json
  • change-case 4.1.2
  • worker-loader 3.0.8
  • @babel/core 7.14.3
  • @babel/preset-env 7.14.2
  • @commitlint/cli 12.1.4
  • @commitlint/config-conventional 12.1.4
  • @nuxtjs/eslint-config 6.0.0
  • @nuxtjs/module-test-utils 1.6.3
  • babel-eslint 10.1.0
  • babel-jest 27.0.1
  • codecov 3.8.2
  • core-js 3.13.0
  • eslint 7.27.0
  • eslint-plugin-json 3.0.0
  • husky 6.0.0
  • jest 27.0.1
  • lint-staged 11.0.0
  • pinst 2.1.6
  • postcss-nesting 7.0.1
  • standard-version 9.3.0
  • stylelint 13.13.1
  • stylelint-config-recess-order 2.4.0
  • stylelint-config-standard 22.0.0
nvm
.nvmrc
  • node 14.17.0

  • Check this box to trigger a request for Renovate to run again on this repository

Use fonts from static folder to avoid hashing is not working

Hello!

Thank you very much for this plugin and all the work.

If we use '@/assets/fonts/font-a-regular' as stated in the documentation, it will be hashed in each build. This means that it will never be cached properly. Fonts rarely change, and if they change we can easily update their filename.

To avoid this, the fonts should be located in the /static/ folder. However, when I use for example this path src: '/static/assets/fonts/montserrat-v14-latin-700' the plugin does not work properly as it can't locate and preload the plugin.

Would be possible to check this?

Thank you once again and have a great year!

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: undefined. Note: this is a nested preset so please contact the preset author if you are unable to fix it yourself.

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.