Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatic Inlining of Fonts breaks in Angular 11 #19350

Closed
glued opened this issue Nov 12, 2020 · 8 comments · Fixed by #19352
Closed

Automatic Inlining of Fonts breaks in Angular 11 #19350

glued opened this issue Nov 12, 2020 · 8 comments · Fixed by #19352

Comments

@glued
Copy link

glued commented Nov 12, 2020

🐞 bug report

Is this a regression?

Yes, the previous version in which this bug was not present was: 10

Description

This update to Angular 11 prevents our fonts from loading when linked from (fonts.google.com)

  1. How can I turn off this feature?
  2. Why is this enabled by default?
  3. This seems like an unnecessary optimization for those who are using service worker cache.

in my index.html I have the following

<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500|Roboto+Mono:400,500|Material+Icons&display=swap" rel="stylesheet"/>

That link goes to the following url

Which appears to be converted into the following when built for production:

<style type="text/css">
@font-face {
    font-family: "Roboto Mono";
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url(https://fonts.gstatic.com/s/robotomono/v12/L0x5DF4xlVMF-BfR8bXMIjhLq3-cXbKD.woff2)
      format("woff2");
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
      U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215,
      U+FEFF, U+FFFD;
  }
  .material-icons {
    font-family: "Material Icons";
    font-weight: normal;
    font-style: normal;
    font-size: 24px;
    line-height: 1;
    letter-spacing: normal;
    text-transform: none;
    display: inline-block;
    white-space: nowrap;
    word-wrap: normal;
    direction: ltr;
    -webkit-font-feature-settings: "liga";
    -webkit-font-smoothing: antialiased;
  }
</style>

Missing are the @font-face for Roboto and Material Icons.
Unclear how these are being evaluated but used you should also consider CSS custom variable assignments such as:

:root{
  --icon-font-family:'Material Icons';
}
.icon{
  font-family:var(--icon-font-family);
}

🔬 Minimal Reproduction

see above

🌍 Your Environment

Angular Version:



Angular CLI: 11.0.0
Node: 14.5.0
OS: darwin x64

Angular: 11.0.0
... animations, cli, common, compiler, compiler-cli, core
... elements, forms, language-service, platform-browser
... platform-browser-dynamic, router, service-worker
Ivy Workspace: Yes

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1100.0
@angular-devkit/build-angular   0.1100.0
@angular-devkit/core            11.0.0
@angular-devkit/schematics      11.0.0
@angular/cdk                    10.2.7
@angular/fire                   6.0.5
@angular/material               10.2.7
@schematics/angular             11.0.0
@schematics/update              0.1100.0
ng-packagr                      11.0.1
rxjs                            6.6.3
typescript                      4.0.5

@glued
Copy link
Author

glued commented Nov 12, 2020

Ah i found the document about how to turn this off...
https://angular.io/guide/workspace-config#optimization-and-source-map-configuration

but i would not recommend having this on by default, doesn't appear to work properly

@AndrewKushnir
Copy link

cc @alan-agius4

@alan-agius4
Copy link
Collaborator

alan-agius4 commented Nov 12, 2020

It appears that the root problem is caused by a multiline comment in the response which is not handled properly in our minifier. I have a PR inflight to fix this #19352.

Also, kindly find below the answer to your questions.

How can I turn off this feature?

As you mentioned, the docs for this are available https://angular.io/guide/workspace-config#optimization-and-source-map-configuration

Why is this enabled by default?

This is a critical performance optimisation to reduce the First Contentful Paint. See: https://blog.angular.io/version-11-of-angular-now-available-74721b7952f7 and #18730 for the motivation behind this feature.

This seems like an unnecessary optimization for those who are using service worker cache.

This optimization is still beneficial if you use service workers because first time visitors will not have the service worker installed.

Resources from external domains are not cached by the service-worker unless, you have configured the service worker to cache such resources, In which case you'll see the benefit of this after the 2nd visit of the application., because during the 1st visit the SW get installed, during 2nd the requests get cached and 3rd visit serve the request from cache. None-the-less, having the CSS of fonts inlined inlined in the HTML is still be slightly more performant.

@glued
Copy link
Author

glued commented Nov 12, 2020

Hold up,
This should be at the developers discretion based on how they've configured their fonts, you can still reduce First Contentful Paint using font-display to achieve the same result...
https://developers.google.com/web/updates/2016/02/font-display

For example, i'm using swap

swap gives the font face a zero second block period and an infinite swap period. This means the browser draws text immediately with a fallback if the font face isn’t loaded, but swaps the font face in as soon as it loads. Similar to block, this value should only be used when rendering text in a particular font is important for the page, but rendering in any font will still get a correct message across. Logo text is a good candidate for swap since displaying a company’s name using a reasonable fallback will get the message across but you’d eventually use the official typeface.

@glued
Copy link
Author

glued commented Nov 12, 2020

Would also like to mention that fonts from fonts.google.com add swap by default using the &display=swap parameter
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@100&display=swap" rel="stylesheet">

@alan-agius4
Copy link
Collaborator

This approach doesn’t take away the benefits of display swap. If anything it’s complimentary and users should still use display swap. Adding display swap if one of the many steps that needs to be done to achieve better FCP. Other complimentary approaches which we are currently working on, is inlining of critical CSS.

The FCP is improved even further when inlining the external CSS rule definitions because each external CSS has a performance bottle neck, because it needs to be downloaded and parsed all this while rendering is blocked.

When the external CSS is an on another domain, the bottle neck is even more because of addition DNS resolutions and connection creation which can take a couple of hundreds of milliseconds.

clydin pushed a commit that referenced this issue Nov 12, 2020
clydin pushed a commit that referenced this issue Nov 12, 2020
…uring font inlining

Closes #19350

(cherry picked from commit 1237dda)
@glued
Copy link
Author

glued commented Nov 13, 2020

Seems risky to cache these at build time.
What happens if the fonts inside that url are changed or removed...

@font-face {
src: url(https://fonts.gstatic.com/s/robotomono/v12/L0x5DF4xlVMF-BfR8bXMIjhLq3-cXbKD.woff2) format("woff2");

They could change due to licensing issues or bug fixes etc

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Dec 14, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.