Gatsby - Prevent small images from being inlined as a data URI
Asked Answered
H

2

8

I'm attempting to provide images for each of the apple-touch-icon sizes in my head tag. I'm doing this like so:

// not shown: import all image files: logo57, logo76, etc
<link rel="apple-touch-icon" sizes="57x57" href={logo57} />
<link rel="apple-touch-icon" sizes="76x76" href={logo76} />
<link rel="apple-touch-icon" sizes="120x120" href={logo120} />
<link rel="apple-touch-icon" sizes="152x152" href={logo152} />
<link rel="apple-touch-icon" sizes="167x167" href={logo167} />
<link rel="apple-touch-icon" sizes="180x180" href={logo180} />

The problem is that when the page is rendered, all of these images are included directly in the page as base 64 in data URIs, not relative urls. Like so:

<link rel="apple-touch-icon" sizes="180x180" href="data:image/png;base64,iVBORw0KGgoAAAA....">

This is problematic for a few reasons. For one, these images are only needed in the progressive web app scenario; they are not needed by normal desktop browsers and yet desktop browsers are forced to download all of these chunks of base 64, slowing down the page load. Secondly, even in the PWA scenario, each device will only need one of these images, not all of them, so page load time is slowed there as well.

This is a documented optimization for images <10,000 bytes, so it may be a negligible difference that they are all loaded here. But, the total size of the original pngs totals about 27kb (I don't know about after converting to base 64), and it seems like I'd rather not include this data in every page if it is not needed.

I've found that I can move the images all to the /static folder and reference them with href="logo57.png", but then I lose the compile time verification that these images are in fact present at the given href, as well as the including of the image hash in the file name (for caching reasons).

How can I tell Gatsby to not inline these images directly into the page as data URI's?

Handcrafted answered 22/10, 2018 at 3:21 Comment(3)
I've never used this tool before, but it seems like you don't want to use import for these files, and instead use the withPrefix function and a static assets folder, to use actual URLs that cause HTTP(S) requests to happen. gatsbyjs.org/docs/adding-images-fonts-files/… As an aside, check out ImageOptim for shrinking image files (with no visible changes). I'm not affiliated with them, I just love the free tool and use it all the time. imageoptim.comLautrec
Did you try the RAW loader? Like import txt from 'raw-loader!./file.txt';Asclepiadaceous
It still converts images into dataURI which are less than 10Kb.Wauters
R
4

Rather than using Webpack for these assets (import x from "...") you should place them in your static folder and reference them directly. If your Gatsby site doesn't have a prefix (i.e. an index.js file is served from /) then you can hardcode the paths (e.g. href="/favicon.png"). Otherwise you'll want to use withPrefix to provide the prefix in production.

Revocation answered 22/10, 2018 at 20:22 Comment(3)
Thanks for the answer, I was able to get the icons working from the static folder, but as mentioned I lose some of the advantages of using webpack. Is there any way to control the image inlining via some config either in Gatsby or Webpack?Handcrafted
@PatrickGoley You can override Gatsby's webpack loader for these files, but you're not getting any benefit out of using Webpack. Even the official Gatsby website uses this approach.Revocation
It still converts images into dataURI which are less than 10Kb.Wauters
E
0

You could also use GraphQL for this. If for example you have the logo in a folder called images your code would be something like this:

const data = useStaticQuery(graphql`
  query Logo {
    file(absolutePath: { regex: "/images/logo.png/" }) {
      publicURL
    }
  }
`)

return <link rel="apple-touch-icon" sizes="57x57" href={data.file.publicURL} />

Please note, you'd need to use gatsby-source-filesystem for your images to be available in GraphQL. It's already used by Gatsby internally so no need to install it. Simply add it to your gatsby-config.js:

module.exports = {
  plugins: [
    { resolve: `gatsby-source-filesystem`, options: { path: `${__dirname}/src/images` } },
    // other plugins here...
  ],
}
Earmark answered 9/7, 2020 at 18:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.