dermyhughes / gatsby-ghost-blog

Gatsby front end blog using Ghost as headless CMS
MIT License
0 stars 0 forks source link

Long time for first paint on homepage due to font loading #199

Open dermyhughes opened 1 month ago

dermyhughes commented 1 month ago

The home page takes a second to load fully every time as the first thing a user sees is the large text, that load a google font, which takes a second to load.

codeautopilot[bot] commented 1 month ago

Potential solution

The plan to solve the bug involves preloading the Google font to ensure it is available as soon as possible, thereby reducing the time to the first paint on the homepage. This can be achieved by making changes in both the gatsby-ssr.js and Layout.tsx files to preload the font during server-side rendering and client-side rendering, respectively. Additionally, we need to ensure that the font-family in the _defaults.scss file correctly references the preloaded Google font.

What is causing this bug?

The bug is caused by the delay in loading the Google font, which is currently being fetched only after the client-side JavaScript runs. This delay results in a longer time to the first paint on the homepage. By preloading the font, we can prioritize its loading and reduce this delay.

Code

gatsby-ssr.js

Add the following code to preload the Google font during server-side rendering:

// gatsby-ssr.js

import React from "react";

export const onRenderBody = ({ setHeadComponents }) => {
  setHeadComponents([
    <link
      key="google-font-preload"
      rel="preload"
      href="https://fonts.googleapis.com/css2?family=Permanent+Marker&display=swap"
      as="style"
      onLoad="this.onload=null;this.rel='stylesheet'"
    />,
    <noscript key="google-font-noscript">
      <link
        rel="stylesheet"
        href="https://fonts.googleapis.com/css2?family=Permanent+Marker&display=swap"
      />
    </noscript>,
  ]);
};

src/styles/partials/_defaults.scss

Update the font-family to correctly reference the preloaded Google font:

body {
    font-family: 'Permanent Marker', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
        Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
}

src/components/common/Layout.tsx

Modify the <Helmet> component to preload the Google font during client-side rendering:

import React from 'react';
import { Helmet } from 'react-helmet';

const Layout = ({ children, site, bodyClass }) => (
  <>
    <Helmet>
      <html lang={site.lang} />
      <style type='text/css'>{`${site.codeinjection_styles}`}</style>
      <link
        rel="preload"
        href="https://fonts.googleapis.com/css2?family=Permanent+Marker&display=swap"
        as="style"
        onLoad="this.onload=null;this.rel='stylesheet'"
      />
      <noscript>
        <link
          href="https://fonts.googleapis.com/css2?family=Permanent+Marker&display=swap"
          rel="stylesheet"
        />
      </noscript>
      <body className={bodyClass} />
    </Helmet>
    {children}
  </>
);

export default Layout;

How to replicate the bug

  1. Load the homepage of the website.
  2. Observe the time it takes for the large text (using the Google font) to appear.
  3. Note that the text appears after a noticeable delay, indicating that the font is being loaded only after the client-side JavaScript runs.

By implementing the above changes, the Google font will be preloaded during both server-side and client-side rendering, reducing the time to the first paint on the homepage.

Click here to create a Pull Request with the proposed solution

Files used for this task:

Changes on gatsby-ssr.js # Analysis Report for `gatsby-ssr.js` ## Overview The file `gatsby-ssr.js` is currently empty. This file is intended to be used for server-side rendering (SSR) in a Gatsby project. The task is to add a `` tag to preload the Google font in the `` section during the server-side rendering process. ## Potential Cause of the Bug Since the file is empty, it does not currently contribute to preloading the Google font. This lack of preloading could be causing the delay in the first paint on the homepage, as the font is not being fetched until the client-side JavaScript runs. ## Solution To address the issue, we need to add a `` tag in the `` section to preload the Google font. This can be done by implementing the `onRenderBody` API provided by Gatsby. ## Implementation Plan 1. **Add the `onRenderBody` API**: This API allows us to modify the head and body of the HTML document during SSR. 2. **Insert the `` tag**: Add a `` tag to preload the Google font in the `` section. ### Example Code Here is an example of how to implement this: ```javascript // gatsby-ssr.js import React from "react"; export const onRenderBody = ({ setHeadComponents }) => { setHeadComponents([ , , ]); }; ``` Replace `YourFontName` with the actual name of the Google font you are using. ## Conclusion By adding the above code to `gatsby-ssr.js`, the Google font will be preloaded during the server-side rendering process, which should help reduce the time for the first paint on the homepage. This change should address the issue described in the ticket.
Changes on src/styles/partials/_defaults.scss ## Analysis Report ### File: `src/styles/partials/_defaults.scss` #### Current State The `_defaults.scss` file sets the default styles for the HTML and body elements, including the font-family. The current font-family stack is as follows: ```scss body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; } ``` This stack includes a variety of system fonts and web-safe fonts, with "Open Sans" and "Helvetica Neue" being the only web fonts in the stack. #### Potential Issue The issue described involves a delay in the first paint on the homepage due to the loading of a Google font. The current font stack does not explicitly include a Google font that might be causing the delay. However, if "Open Sans" is being loaded from Google Fonts, it could be the source of the delay. #### Recommended Changes To address the issue, we need to ensure that the Google font is preloaded and correctly set in the font-family. Here are the steps to achieve this: 1. **Identify the Google Font**: Determine which Google font is being used. For this example, let's assume "Open Sans" is the font causing the delay. 2. **Preload the Font**: Add a `` tag in the `` section of the HTML to preload the font. This will be done in the `gatsby-ssr.js` and `Layout.tsx` files as per the plan. 3. **Update Font-Family**: Ensure that the font-family in `_defaults.scss` correctly references the preloaded Google font. #### Updated Code Assuming "Open Sans" is the Google font in question, the updated `_defaults.scss` file should look like this: ```scss body { font-family: 'Open Sans', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Helvetica Neue", sans-serif; } ``` This change ensures that "Open Sans" is prioritized and correctly referenced in the font stack. ### Conclusion The `_defaults.scss` file is relevant to the bug as it sets the default font-family. By ensuring that the Google font is correctly referenced in the font-family stack, we can help mitigate the delay in the first paint on the homepage. The next steps involve preloading the font in the `gatsby-ssr.js` and `Layout.tsx` files.
Changes on src/components/common/Layout.tsx ## Analysis Report ### File: `src/components/common/Layout.tsx` #### Current Implementation The `Layout.tsx` file is responsible for rendering the main layout of the website, including the header, footer, and main content. It uses the `Helmet` component to manage the document head, including meta tags and styles. The file currently includes a `` tag to load the Google font "Permanent Marker" as follows: ```jsx ``` Additionally, the file contains logic to load the font asynchronously and set a state variable `isFontLoaded` to control the visibility of the text until the font is loaded. #### Identified Issue The issue reported is that the homepage takes a second to load fully due to the time taken to load the Google font. The current implementation loads the font using a standard `` tag, which may not be optimal for performance. #### Proposed Solution To address the issue, we should preload the Google font to ensure it is available as soon as possible. This can be done by adding a `` tag with the `rel="preload"` attribute in the `` section. Preloading the font will prioritize its loading, reducing the time to first paint. #### Changes to be Made 1. Add a `` tag with `rel="preload"` to preload the Google font in the `` section. #### Updated Code Here is the updated code snippet for the `` component: ```jsx ``` ### Summary The proposed change involves preloading the Google font "Permanent Marker" to improve the time to first paint on the homepage. This should help in reducing the delay caused by font loading and enhance the user experience. ### Next Steps - Implement the above changes in the `Layout.tsx` file. - Verify if the changes resolve the issue by testing the homepage load time. - Coordinate with the agent responsible for `gatsby-ssr.js` to ensure consistent font preloading during server-side rendering. This concludes the analysis and proposed solution for the identified issue in the `Layout.tsx` file.