Baked-in static data
You saw lots of loading spinners in the previous exercise. But the list of SpaceX launches doesn't change that often.
Time to look into JAMStack's biggest selling point 👉 data baked into the initial HTML.
Gatsby's useStaticQuery
Gatsby uses GraphQL throughout its stack. Everything is data and all data is GraphQL. It comes with a built-in useStaticQuery hook that lets you run GraphQL queries during build-time.
Exercise
Continue with your Gatsby project from before, or jump into mine in exercise-5. Make a copy of your <LaunchList> component using a static query.
Install gatsby-source-graphql and configure it in gatsby-config.js
// gatsby-config.js{resolve: 'gatsby-source-graphql',options: {typeName: 'SPACEX',fieldName: 'spacex',url: 'https://api.spacex.land/graphql'}}
You can now query the SpaceX API from anywhere in Gatsby. Use it to create new pages based on data in gatsby-node.js, or as a static query in any React component.
import { graphql, useStaticQuery } from "gatsby"export const LaunchList = ({ limit = 10 }) => {const data = useStaticQuery(graphql`query LaunchesPast {spacex {launchesPast(limit: 10) {mission_namelinks {article_linkvideo_link}rocket {rocket_name}}}}`)// list launches, they're in data.spacex.launchesPast}
Note that you have to wrap your query in the spacex namespace, as defined in gatsby-source-graphql config. And you can't pass-in variables.
Solution
Find mine in the exercise-5-solution branch.
NextJS's getServerSideProps
NextJS gives you 2 options to bake data into your HTML. On-demand with getServerSideProps and statically with getStaticProps.
You can use GraphQL or REST to populate those values, we'll go with the React Query approach. The integration is fantastic.
Exercise
Take your NextJS project from exercise-3, or jump into mine at exercise-5. Use the SpaceX REST API to create a page that lists SpaceX's last 10 launches.
Copy the REST API fetch function from your Gatsby project. Use it to populate the launches prop of a new page.
// pages/launches.jsasync function getLaunches(limit) {const res = await fetch(`https://api.spacex.land/rest/launches-past?limit=${limit}`)return res.json()}export async function getServerSideProps() {const launches = await getLaunches(10)return {props: {launches,},}}const Launches = ({ launches }) => {// render here}
Look at your network log. Notice there's no API request, yet the data shows up 🤘
NextJS makes the request for you as it generates the page.
Solution
Find mine in the exercise-5-solution branch.
NextJS's getStaticProps
Fetching SpaceX launch data on every page load seems wasteful. It doesn't change that often.
NextJS lets you fetch data at build-time using getStaticProps.
Exercise
Change getServerSideProps to getStaticProps. That's it :)
Notice how much faster the page loads now.
Solution
Find mine in the exercise-5-solution branch.
Bonus exercise
Try to create a page for each SpaceX rocket with Gatsby and NextJS
Gatsby
You'll have to create a new Rocket template and create pages in gatsby-node like we did for dynamic routing. Use graphql to get a list of rockets and call createPage for each.
Use a static query to list all the rockets with links to individual pages.
This is the query to fetch all the rockets with some info:
{rockets {activeboosterscompanycost_per_launchengines {engine_loss_maxlayoutnumber}countrydescriptionheight {meters}first_flightidname}}
NextJS
Use dynamic routing to define a new [rocket] page. Then fetch its data with getStaticProps. You'll need to define all possible pages with getStaticPaths.
// pages/[rocket].jsexport async function getStaticPaths() {// get list of rockets// create pathsconst paths = rockets.map((rocket) => ({params: { rocket: rocket.id },}))return {paths,// 404 when hitting an unknown pagefallback: false,}}
If you fetch a page's data with getServerSideProps, you don't need to pre-define paths.
The REST API to list rockets is https://api.spacex.land/rest/rockets, for individual rockets, use https://api.spacex.land/rest/rocket/{id}.