Search code examples
reactjsgatsby

GatsbyJS - Build files too large (styled components and SVGs)


I have a large Gatsby site that has ~10k news articles that get built from a headless CMS. The compiled site is a bit larger than I'd like it to be (2.5gb). When I investigated how to get the total build size down, I saw some repeating elements in the build files that I think can be optimized.

Issue 1 - SVGs: Vector files are being added inline. Is there a way to have these reference the path to the image instead of being added inline?

import arrowWhite from "../../images/icons/right-arrow-white.svg";

<img src={arrowWhite}/>

This makes an output of something like:

<img src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMTg0cHgiIGhlaWdodD0iMjFweCIgdmlld0JveD0iMCAwIDE4NCAyMSIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIj4KICAgIDx0aXRsZT5CaXRtYXA8L3RpdGxlPgogICAgPGcgaWQ9IlBhZ2UtMSIgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+CiAgICAgICAgPGcgaWQ9IjAwX2hvbWVwYWdlIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTY0LjAwMDAwMCwgLTM3NDYuMDAwMDAwKSI+CiAgICAgICAgICAgIDxnIGlkPSJHcm91cC0zIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMS4wMDAwMDAsIDM3MDguMDAwMDAwKSI+CiAgICAgICAgICAgICAgICA8aW1hZ2UgaWQ9IkJpdG1hcCIgeD0iMTY1IiB5PSIzOCIgd2lkdGg9IjE4NCIgaGVpZ2h0PSIyMSIgeGxpbms6aHJlZj0iZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFWb0FBQUFvQ0FZQUFBQy96RElJQUFBQUJHZEJUVUVBQUxHT2ZQdFJrd0FBQUVSbFdFbG1UVTBBS2dBQUFBZ0FBWWRwQUFRQUFBQUJBQUFBR2dBQUFBQUFBNkFCQUFNQUFBQUJBQUVBQUtBQ0FBUUFBQUFCQUFBQldxQURBQVFBQUFBQkFBQUFLQUFBQUFBbFBJNzVBQUFTZjBsRVFWUjRBZTJiQy9nWFV4ckhLOVUvcFlzdTVOS1dub1JZbHhTRjNDKzVycXhMZUt4YTF1YjZhTm5Gcm9ld0h2ZlZlbGgzWVYxeVo3RnVVVUpZUkx1NUpQOVNrV3NsSXBXeW4yODc0emxOTTNQT3pHOW1mci8rTysvemZKdVpjOTdiZVg5bnpublBPLzhhTjZwZGFvSnJuY0U2WUczdnVwWjMzNDZyMEJhMDhhNnR1ZFlCVVF2ZzN5OXZNUDVad1AxUzcva3JydCtBcjcycjd0WDJCZmdFZkE0K0JaK0JqNEJrU3lvalVFYWdqRUNpQ0RST3hMMHljM09hRGdPbkF1bTZBWXdHV3F4Y1NQSTlQV3pNdFR2bzV1Rm5YSnVCV3FJdmNXYTZnZmU1ZjhlREZ1dVN5Z2lVRVNnanNGSUUwaTYwYTZEcEZIQVNVTVpwMGhJZXhvUG53VVF3RlNnelhBMzBCbjNCRm1Cem9FVldtV3REb0JrTTR....." />

Is there a way to import this so the compiled version references the path to the image?

<img src="/path/to/right-arrow-white.svg">

Issue #2 - Styled Components: This is injecting the same CSS into <style> tags into each compiled news article file.

const HeaderStyle = styled.div`
  position: relative;
  ...
}

<HeaderStyle>...</HeaderStyle>

Solution

  • Issue 1 - SVGs: Vector files are being added inline. Is there a way to have these reference the path to the image instead of being added inline?

    Besides the resolution is optimal: you are converting an image to base64 where, of course, the string is long as fuck, but it's extremely light for the web to handle. If you wish, you can import and inline the SVG using the approach in: Import SVG as a component in Gatsby

    Summarizing, just do:

    {
      resolve: 'gatsby-plugin-react-svg',
      options: {
        rule: {
          include: /svg-folder/
        }
      }
    } 
    

    Note: svg-folder must only contain SVG assets and you just need to place the folder name, not the path (since it's a regular expression).

    Then you can do:

    import ArrowWhite from "../../images/icons/right-arrow-white.svg";
    <ArrowWhite />
    

    Note the capitalization since it's a React component.

    This approach is more optimal than using the <img> tag.

    Issue #2 - Styled Components: This is injecting the same CSS into <style> tags into each compiled news article file.

    This is strictly related to the implementation, without further details I don't know what's wrong. My guess is that your styled-components are injected into each article. You can move the styling to any unique outer wrapper to inject it only once, like if they were "global" styles.