Gatsby has best-in-class image support with its gatsby-plugin-image
feature. With it you can easily add responsive, optimized images to sites in all modern formats. Traditionally, images were downloaded and transformed to enable this behavior. Image CDN solves this by skipping image processing during the build, and instead deferring and offloading it to a dedicated image CDN. Visitors still get images in the most optimized formats such as AVIF and WebP, but site builds complete in a fraction of the time.
By the end of this part of the tutorial, you will be able to:
gatsby-plugin-image
in your example siteGatsby’s Image CDN feature can be added to any Gatsby source plugin. We recommend using it over manual file downloading for the reasons above. As long as your API gives back a URL to an image, you should be able to implement the required code. Basically, for Image CDN to work you need two things:
RemoteFile
interfaceRemoteFile
expectsIn Part 3 you learned that root node types need to implement the Node
interface. Similarly to Node
, RemoteFile
is also provided by Gatsby itself and will handle all the complicated pieces of Image CDN behind the scenes.
Pro tip: Gatsby’s Image CDN feature is smart enough to work on all platforms, even if no CDN provider like on Gatsby Cloud or Netlify is available. In those cases (including locally on your computer) it automatically falls back to processing images during the build. This won’t give users a build improvement but things on the frontend will still behave the same and builds won’t fail.
The RemoteFile
interface has the following shape:
For node types implementing RemoteFile
this means:
publicUrl
(the url to the image/file), mimeType
(e.g. image/jpg
or application/pdf
), and filename
. publicUrl
will be defined through url
during node creation.width
, height
, resize
, and gatsbyImage
can be null. This is because the RemoteFile
interface can also handle assets other than images, like PDFs.For node types that are images this means: publicUrl
, mimeType
, filename
, width
, and height
are mandatory.
Pro tip: resize
and gatsbyImage
will be provided by Gatsby. They are GraphQL resolvers relying on the existing data on the GraphQL node. You’ll use gatsbyImage
later to get your data for the <GatsbyImage />
comopnent.
Here’s an example of a GraphQL root node that implements RemoteFile
and creates nodes with all required fields for images:
Schema customization to implement RemoteFile
on ImageAsset
:
Creating the ImageAsset
node with all required fields:
As you can see the ImageAsset
node holds all required fields but you can also add your own additional, arbitrary fields (like alt
shown in the example). Once ImageAsset
is created, you’ll be able to call gatsbyImage
and resize
on these GraphQL nodes and use Image CDN.
The URL you provide to the url
field should link to the image version with the highest resolution, so if e.g. your API can provide image URLs in different sizes, pick the one with the best resolution.
One field that hasn’t been mentioned yet is the placeholderUrl
. The <GatsbyImage />
component supports displaying a placeholder while the image loads. You can tell Image CDN to use your placeholderUrl
to generate said placeholder. If your API supports returning different sized images through URL segments or URL params, you can place %width%
and %height%
into the URL. This tutorial uses Unsplash as it supports dynamically resizing images and thus both are used with the w
query param. Alternatively, you could also provide the smallest possible image available from your API to this field.
Are width and height missing from the API response? Not every API returns width, height, and mimeType for an image. You can use probe-image-size
to get these information from your remote URL.
probe-image-size
example
probe-image-size
returns a Promise so you’ll need to await
its result. You could use it something like this:
createAssetNode
utility
Time to apply your theoretical knowledge about Image CDN to your own plugin.
You’ll create a new root node called Asset
through a createAssetNode
utility. You can think of it as a more specialized version of the nodeBuilder
utility, only responsible for creating nodes that should become Asset
and hence Image CDN capable. Creating a separate Asset
type will also make schema customization in the next task easier.
Open plugin/src/constants.ts
and add a new node type:
Open plugin/src/source-nodes.ts
. Add the type imports for IRemoteImageNodeInput
and IPostImageInput
, create a shell for createAssetNode
at the end of the file:
Similar to nodeBuilder
it receives gatsbyApi
to call the various node helpers but data
must be in the shape of IPostImageInput
. This TypeScript type is identical to the image
object shape inside each post in api/src/data.ts
.
Create the function body for createAssetNode
by following what nodeBuilder
is doing:
TypeScript should complain about missing fields on asstNode
:
These are exactly the fields that are required for image assets.
Add the missing fields to the node:
And that’s it, you can create Asset
nodes now! In the next task you’ll actually use createAssetNode
.
So far your createAssetNode
utility isn’t doing anything. You’ll need to use it inside the nodeBuilder
utility to add an additional image
field to Post
nodes. However, this will only work once you have successfully implemented the second requirement of Image CDN: That Asset
implements the RemoteFile
interface.
A lot of this task builds upon your knowledge from Part 3, specifically the foreign-key relationship section. Feel free to revisit those sections if you need a refresher.
You’ll implement the RemoteFile
interface for Asset
and make it a root node. Then you’ll create a foreign-key relationship between Asset
and the image
field on Post
.
Open plugin/src/create-schema-customization.ts
. Change the name of PostImage
to Asset
and implement both Node
and RemoteFile
for it:
Nodes that createAssetNode
creates will be GraphQL root nodes now.
If you’re not using the SDL syntax but type builders, you’d add it like this:
Create a foreign-key relationship between Post
and Asset
through @link
on the image
field.
If you remember from Part 3, the default behavior of @link
is to use the id
from the target node. Keep that in mind for the following instructions.
Open the plugin/src/source-nodes.ts
file and add a return statement to the createAssetNode
function. Return the generated id
:
A node of type Post
should have the generated id
of Asset
as its image
field. Because only posts can have images, you can conditionally add data to the node if certain conditions are met like this:
The some-id
string should be replaced by the Asset
id of course. Since createAssetNode
returns the id
, you can use its result:
Restart the develop:site
script and open GraphiQL at http://localhost:8000/___graphql
. Run the following query:
You should get a result back like this:
It works! Note: <long-string>
is added above to make things easier to read. If you’re seeing an error, stop the develop:site
script, run yarn clean:site
and retry yarn develop:site
again.
In the next task you’ll be able to use the result from gatsbyImage
inside your pages.
When using gatsby-plugin-image
you use the gatsbyImageData
GraphQL field to access the necessary data. With Image CDN this name changes to gatsbyImage
— you’ve learned this in the last task. The only relevant difference between gatsbyImageData
and gatsbyImage
is that the latter requires a width
or height
argument.
Refer to the gatsby-plugin-image
how-to for instructions on its usage as this tutorial won’t go into details about that.
Open site/src/pages/{Post.slug}.tsx
and add image
to the GraphQL query:
Import the necessary gatsby-plugin-image
helpers and components and use them with image
:
Go to http://localhost:8000/post-1/
. You should see a dog image on the page:
Magnificent! Your posts now have photos of cute dogs.
Take a moment to think back on what you’ve learned so far. Challenge yourself to answer the following questions from memory:
RemoteFile
support?RemoteFile
expects?RemoteFile
interface and have all required fields on their node.gatsbyImage
in your GraphQL result together with gatsby-plugin-image
like you’re used to.Share Your Feedback!
Our goal is for this tutorial to be helpful and easy to follow. We’d love to hear your feedback about what you liked or didn’t like about this part of the tutorial.
Use the “Was this doc helpful to you?” form at the bottom of this page to let us know what worked well and what we can improve.
What’s coming next?In Part 7 advanced topics like Content Sync, testing, debugging, and more will be explained.
Continue to Part 7Start building today on
Netlify!
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4