This is a complimentary blog post to a video from the ShopifyDevs YouTube channel. In this article, Chuck Kosman, a Launch Engineer at Shopify Plus, will walk you through some key features of GraphQL that are handy for building applications at scale. It is the first video in a five-part series of tutorials designed to educate and improve your knowledge of the benefits of GraphQL.
In this tutorial, Chuck will explore GraphQL operation names and variables.
Note: All images in this article are hyperlinked to the associated timestamps of the YouTube video, so you can click on them for more information.
Using GraphQL to create a basic query
Here I'm using the graphical IDE. This is an app installed on a development store where I have some products, customers, and orders populated. If any of that sounded like jargon, take a look at our Getting Started with GraphQL article in the Shopify Developer series to get started with the setup.
This is a pretty simple product query. All I'm doing is retrieving a product by its ID
, and I'm supplying that GraphQL ID
to the ID
argument here. Now this will work, so I'll press play here, and I should get this data back.
While it works, this is not really going to be usable at scale. You would have to pass this query in, literally, somewhere when I make an HTTP
request. That means that if you want to change out the ID
s, you’re going to have to compose the query each time using string interpolation.
While that's OK, it's not ideal, and it's not really taking advantage of GraphQL's typing system either.
Build for the world’s entrepreneurs
Want to check out the other videos in this series before they are posted on the blog? Subscribe to the ShopifyDevs YouTube channel. Get development inspiration, useful tips, and practical takeaways.
SubscribeDefining a name in GraphQL
There’s a few things that we can add right at the beginning of the body of this query to make this more reusable. Those are both operation names and variables. Keep in mind, this is implicitly a query because I've left out the query keyword. I’m going to need to provide the query keyword for the next operation, though.
You might also like: Getting Started with GraphQL.
I can name the operation whatever I want by entering an operation name right after the query keyword. I could equally well do this for mutation too. If this said mutation
and then I had a space, I could do this. The convention is PascalCase and describes what you're getting back.
I'm going to say ProductTitleAndDescription
. When I run this again you'll see that nothing actually changes, but we’re free to add the operation name.
Defining a variable with GraphQL
The next part of this is variables. The variables syntax looks like this:
I'm going to open parentheses after the operation name, and let’s say I'm going to supply a variable ID
. The $
sign is used to indicate that this is a variable. I'm going to put a :
and then I'm going to say that this variable is of type ID
. The importance of variables is that you actually have to specify the type.
We’re going to change this query slightly. I'm going to copy this to my clipboard, and I'm going to say that the ID
that I'm supplying to this product field is the ID
variable.
Now, I haven't actually supplied a variable. When I hit play it's going to say, hey, we were expecting you to supply type ID
to this ID
variable. You didn't provide a valid value, you actually supplied nothing.
This is where the query variables pane comes in use in things like HTTP
clients or the graphical app and the syntax for actually supplying variables looks like this:
I'm going to open a set of curly braces, and I'm going to say the ID
value, and notice here that it actually picked up that I am trying to supply an ID
variable of type ID
, It already knows this based on the way that I've set up my query up there.
So I'm just going to copy and paste that ID
that I grabbed before and I'll run this. What the IDE is doing in the background is it's substituting the value into the ID
variable without having to do any string interpolation of my own.
"What the IDE is doing in the background is it's substituting the value into the ID
variable without having to do any string interpolation of my own."
The actual feature of the GraphQL language is allowing me to do this. Now, this isn't terribly descriptive just because we're working in an IDE, but we can see what this looks like in just a really simple client application.
So we’re going to flip over to Visual Studio Code and see where these might come in handy at scale.
Using names and variables in an app
Over in Visual Studio Code I've built a very simple application using a client library called graphql-request
. This is just a very lightweight way of making GraphQL requests using node. Essentially, these few lines are just to get this application to cooperate in the node environment rather than a browser environment.
Note that I'm also using dotenv
so that when I actually go to make this request, I'm not in this screen cast exposing my private app password to you, dear reader. All that I'm doing is I've hard-coded the endpoints that I'm making the requests against.
https://getting-starter-with-graphql.myshopify.com/admin/api/2020-20/graphql.json
happens to be the address of the test store that I'm using. I'm instantiating graphQLClient
and supplying the requisite headers, namely application/JSON
, and then the actual password that belongs to my private app, process.env.API_PASSWORD
.
When you work with GraphQL and apps, you'll often see queries defined in this way, where the client that you're working with usually has a tagged template literal function, where you are passing in a string that is your request, whether it's a query or a mutation.
You’ll see that I am using the variable syntax. I'm saying that I'm going to supply an ID
of type ID
, and then I will supply that to the argument ID
. There are many different uses of ID
, but they all serve their own distinct purposes.
Next, what I'm doing down here is I'm defining the variables that I'm going to pass in. Just like in that query variables pane of GraphiQL, I'm specifying an object of key ID
and then the actual string that corresponds to the product ID
. I'm issuing that request according to the method that's defined in the GraphQL request package and I'm supplying the query along with the variables I've defined.
I don't have to do my own string interpolation, then I'm just console logging that result. I'm going to run this script, and then I get back the data that I expect.
Now, here's where variables come in handy.
I have some other variables to find, where I'm issuing a different product ID
. I'm going to issue that request in exactly the same way. I'm going to say issue the same query, but supply the otherVariables
that I've defined. So not this product, but this product, and then also console log that. So I'm just going to run that as well.
And now I get both.
This is the importance of variables. I didn't have to do any of my own string interpolation, that's already built into GraphQL. Right now, this query is unnamed. It's not using any operation name. If I comment this out again, let’s just say I'm going to make one request. Let's say I introduced a syntax error, I forgot a curly brace. If I ran this script again, after I saved it, it's going to yell at me saying, "Hey, you didn't do this correctly."
"This is the importance of variables. I didn't have to do any of my own string interpolation, that's already built into GraphQL."
What's interesting is I'm looking directly at the query itself, and without naming this operation, it's really hard for me to go through.
Now, this is a very simple application that's just making one request. You could imagine that at scale you'd want to see if a request was failing. You'd want to know which request it was. I don't want to have to go through my entire application and figure out where a query of this structure was. I want my logs to be able to figure that out based on an operation name.
You might also like: The Shopify GraphQL Learning Kit.
GraphQL operations: naming for debugging at scale
So, I can arbitrarily introduce an operation name. Let’s say ProductIdAndTitle
, just because that's the information that I'm getting back in this query. Without fixing the syntax error, I'm just going to clear and run this again.
Now, when it fails, at least I have the operation name in my logs. That's where the importance of operation names comes in. It’s really kind of analogous to the difference between an anonymous function, and a named function.
In anonymous functions, they are functions without names, so it's very difficult in a stack trace to actually ascertain where the error is occurring. That's the recommendation of why you would name functions; in a stack trace, it says this function of this name is failing. That’s exactly the same principle here in that you don't have to name queries or mutations, but it's very useful for the purpose of debugging at scale.
Stay tuned for part two of this five-part tutorial where we'll be looking at another feature for working at scale: aliases.
Build for the world’s entrepreneurs
Want to check out the other videos in this series before they are posted on the blog? Subscribe to the ShopifyDevs YouTube channel. Get development inspiration, useful tips, and practical takeaways.
SubscribeRead more
- Shopify Fulfillment Orders API: A Better Fulfillment Experience
- How to Build a Shopify App: The Complete Guide
- How to Work with Shopify’s query Argument in GraphQL
- Storefront API Learning Kit
- Build Forms on Shopify: How to Use Liquid to Build Robust Forms for Shopify Themes
- How to Use Relative Pagination In Your Application
- How to Work With Shopify Theme Blocks
- Building Icon Systems With SVG
- 6 Phases of the App Development Process: From Idea to Post-Launch
- Ensuring trust and quality in the Shopify App Store