How to precache a font that is used by css font-face rule that includes a query parameter in its URL value? - css

I'm using Workbox(V5) and in my workbox-config.js I precached the fonts (.woff and .woff2 formats) that are needed for the 3rd-party CSS styles that I'm using, by specifying this for the globPatterns property:
// workbox-config.js
module.exports = {
globDirectory: './',
globPatterns: [
'**/*.{html,ico,woff,woff2}',
],
globIgnores: [
'node_modules/**/*',
'{.,_}*/**/*',
'**/*.{md,txt}',
'Gemfile*',
'package*',
],
additionalManifestEntries: [
{
url: './manifest.webmanifest',
revision: null, // I have also precached my manifest file like this. Is it the best practice?
},
],
swDest: './sw.js',
sourcemap: false,
};
Now in the .css file of the 3rd-party, I can see that the needed fonts are being used with the #font-face rule that includes a query parameter in its URL value:
#font-face {
font-family: "bootstrap-icons";
src: url("./fonts/bootstrap-icons.woff?4601c71fb26c9277391ec80789bfde9c") format("woff"),
url("./fonts/bootstrap-icons.woff2?4601c71fb26c9277391ec80789bfde9c") format("woff2");
}
Well, if I remove the generated hash that has been added to the URL, when I run my PWA offline, the precached fonts show up just fine... But when the styles are calling the fonts with the hash, the precached fonts won't show up!
I have also tried to precache the fonts in my HTML file's head tag and the do runtimeCaching for the .woff and .woff2 formats instead of precaching them by the globPatterns property, but still no luck!
<link rel="preload" as="font" href="./assets/styles/vendor/fonts/bootstrap-icons.woff" type="font/woff2" crossorigin="anonymous">
<link rel="preload" as="font" href="./assets/styles/vendor/fonts/bootstrap-icons.woff2" type="font/woff2" crossorigin="anonymous">
So I was wondering how can we fix this problem?
Thanks a heap,
Ali

You can use the ignoreURLParametersMatching configuration option when generating your service worker to tell workbox-precaching that certain URL parameters can be ignored when checking the cache for a match.
The parameter takes an array of RegExps, and the default is [/^utm_/, /^fbclid$/], which matches some common analytics tracking parameters.
In your particular case, it sounds like the values you want to ignore are all 32 hex characters, so the following configuration should help:
// workbox-config.js
module.exports = {
ignoreURLParametersMatching: [/^[0-9a-f]{32}$/],
// ...other options go here...
};

Related

Vite: Add CSS file to end of <head> section

We are using Vite and would like to manually load an external CSS file. Internally to the project we are using CSS modules. We need the external CSS file to load after the CSS generated by CSS modules.
In vite.config.js I have tried to add a plugin that adds the stylesheet link to the head section as follows.
function externalCSSPlugin() {
return {
name: 'external-css',
transformIndexHtml: {
enforce: 'post',
transform(html, ctx) {
return [{
tag: "link",
attrs: {"rel": "stylesheet", "type":"text/css", "href": "/*<link to css>*/"},
injectTo: "head"
}]
}
}
}
}
However, this always results in the stylesheets generated by CSS modules to be appended to the head after the external CSS:
<head>
...
<link rel="stylesheet" type="text/css" href="/public/external-css.css">
/* styles generated by CSS modules */
</head>
We don't want this, as the external CSS sets some CSS variables.
How can we force the external stylesheet to be added to the end of the head section?
The problem only occurs while using the dev server (and not in a build). Since the CSS module styles are always appended to <head> in the dev server, you can ensure your <link> is after those styles by injecting into the beginning of <body>. This should be done for the dev server only (in which case the plugin's ctx.server exists), as Vite already appends the <link> correctly to <head> in production builds:
function externalCSSPlugin() {
return {
name: 'external-css',
transformIndexHtml: {
enforce: 'post',
transform(html, ctx) {
return [{
tag: "link",
attrs: {"rel": "stylesheet", "type":"text/css", "href": "/*<link to css>*/"},
injectTo: ctx.server ? "body-prepend" : "head", 👈
}]
}
}
}
}
demo

Bing Maps - How do I change font family on map labels?

Per these guidelines:
https://learn.microsoft.com/en-us/bingmaps/styling/map-style-sheet-entry-properties#mapelement-properties
I am trying to set the map style. All properties are working except "fontFamily"
I'm using this google font temporarily, but I have also tried 'serif', 'Times', and 'Times New Roman' and none of them show any difference.
<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=Rye&display=swap" rel="stylesheet">
var sampleStyle = {
"elements": {
"mapElement": {
"labelVisible": true,
"fontFamily": 'Rye',
//"fontFamily": 'serif',
//"fontFamily": 'Times',
//"fontFamily": 'Times New Roman',
"labelColor": "#007bff",
},
},
"settings": {
"landColor": "#F6F4E3"
},
"version": "1.0"
};
The fontFamily style option I believe is only supported by the Bing Maps UWP map control (Windows). Most of the Bing Maps styling was designed for the UWP control and only a subset of those styles were exposed in the Web SDK and static map image service. Unfortunately it doesn't look like they have clearly called out which styles are supported where in their documentation.
If you use the Map Stylesheet editor application available here https://www.microsoft.com/en-us/p/map-style-sheet-editor/9nbhtcjt72ft, it will show which options are available for the web control, static map, and UWP map control, as well as generating sample code for each.

Fonts not found: React-slick + nextjs

I am trying to use react-slick inside a NextJs project. The carousel works fine but I have some problems importing the fonts used in the css files.
I have tried the following:
npm install slick-carousel
and imported the css in the component where the react-slick module is used:
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
When i run the application I get the following error in the network log:
404 Not found on both slick.woff and slick.ttf
I found some other responses where they have added the following to the next.config.js:
const withSass = require('#zeit/next-sass')
const withFonts = require('next-fonts');
const withCss = require('#zeit/next-css')
module.exports = withFonts(withSass(withCss({
env: {
environment: 'development'
},
enableSvg: true,
webpack: function (config) {
config.module.rules.push({
test: /\.(eot|woff|woff2|ttf|svg|png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
limit: 100000,
name: '[name].[ext]'
}
}
})
return config
},
cssLoaderOptions: {
url: false
},
})))
I've tried both with and without the withFonts module.
If i add the direct urls in the <Head>it will work:
<Head>
<>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick.min.css" />
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.6.0/slick-theme.min.css" />
</>
</Head>
But will rather get the fonts to work instead.
Anyone with some suggestion to get the fonts to load in Nextjs?
Not a solution, but I solved it another way.
As I am going to style most of the stuff that requires fonts, i decided to just copy the css from slick-carousel and delete all font references. Override arrow left, arrow right as well as the dots.
Not a solution on the problem stated above but fix my issue.
Pasting both files in public directory with next font installed should resolve 404 error

Custom TTF fonts loading slowly in React app

I'm trying to include a custom font in my React app (made with create-react-app). It seems to be somewhat working but only after 2-3 second after loading the page. Until then, the text appears to use the browser's default font (like Times New Roman), and then swaps to the custom font after a few seconds. Can someone please explain to me why this is happening and what I need to do to fix this?
I'm importing the font into my top-level App.js file like so:
import './fonts/tarrgetital.ttf';
import './App.scss';
And have it declared in my App.scss file like so:
#font-face {
font-family: 'tarrgetital';
src: local('tarrgetital'), url(./fonts/tarrgetital.ttf) format('truetype');
}
h2 {
font-family: tarrgetital;
}
The delay in loading the web fonts is an expected behaviour issue and it's happening because the browser load the fonts when it detects a DOM element with a CSS selector that matches the font-face rule and that happens when then HTML file and all the CSS files have been downloaded on the client. It's a lazy loading mechanism. There are some solutions to improve this behavior:
Use optimized web font file:
For better performance, you can swap your TTF font file in the
font-face with the woff and woff2 file formats. these formats are
compressed in gzip thus reducing the file size and initial
downloading time on the client. If those formats are not available
you can use one of many online tools to convert the font file (google
TTF to woff2).
Webpack Preload:
In webpack 4.6.0+ you can preload modules. this uses
the preload hint in HTML link tags (<link rel="preload">). it will tell the browser to preload the resource before downloading the rest of the resources. To use this option replace import './fonts/tarrgetital.ttf'; with import(/* webpackPreload: true */ './fonts/tarrgetital.ttf');
More on webpack preload here: https://webpack.js.org/guides/code-splitting/#prefetchingpreloading-modules and more info on HTML preload hint here: https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content
One alternative is to use webfontloader. It was co-developed by Google and Typekit.
npm i webfontloader
In your App.js file add this one. Note: You still have to maintain your font face declarations at your css file.
import WebFont from 'webfontloader';
WebFont.load({
custom: {
families: ['tarrgetital'],
},
});
I use also font-face on index.css file
#font-face {
font-family: "Avenir";
src: local("Avenir"),
url("assets/fonts/AvenirNextLTPro-Regular.ttf") format("truetype");
font-weight: normal;
font-style: normal;
}
<link rel="stylesheet" href="../src/index.css" />
Then I imported index.css file into index.html, this worked for me.
Use document.fonts.load with useEffect
import React, { useEffect, useState } from 'react';
const MyComponent = () => {
const [loading, setLoading] = useState(true);
useEffect( ()=> {
document.fonts.load("12px Font-Name").then( () => { setLoading(false) } );
}, [])
return (
<React.Fragment>
{ loading
? <div> Loading... </div>
: <main> Rest of Elements </main>
}
</React.Fragment>
);
};
export default MyComponent;

Using null-loader to remove unneeded fonts in Webpack

I'm using FontAwesome and other font packages which include eot, ttf, svg fonts. I don't want to package them so I've got something like that in Webpack:
/*
* Load fonts from URL
*/
{
test: /\.(png|woff|woff2)(\?.*$|$)/,
loader: 'file-loader'
},
/*
* Remove outdated fonts
*/
{
test: /\.(eot|ttf|svg)(\?.*$|$)/,
loader: 'null-loader'
},
And then in main.css I got something like this:
url(fee66e712a8a08eef5805a46892932ad.woff) format("woff"),
url([object Object]) format("truetype"),
url([object Object]#fontawesomeregular) format("svg");
Which is not valid I believe and I don't see any FontAwesome icons. Is there a way to acheive it with Webpack?
At last I found a solution. Which is best described here
To ignore some fonts and still have proper CSS one need to combine ignore-loader which returns empty string + raw-loader which returns contents but not object.
{
// Ignore fonts
test: /\.(eot|ttf|svg)(\?.*$|$)/,
use: ['raw-loader', 'ignore-loader']
},
If you only want to support woff you can use the url-loader
{
// Match woff2 in addition to patterns like .woff?v=1.1.1.
test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
loader: 'url-loader',
options: {
// Limit at 50k. Above that it emits separate files
limit: 50000,
// url-loader sets mimetype if it's passed.
// Without this it derives it from the file extension
mimetype: 'application/font-woff',
// Output below fonts directory
name: './fonts/[name].[ext]',
},
},

Resources