{"id":284086,"date":"2019-03-12T07:24:15","date_gmt":"2019-03-12T14:24:15","guid":{"rendered":"http:\/\/css-tricks.com\/?p=284086"},"modified":"2019-03-12T07:24:15","modified_gmt":"2019-03-12T14:24:15","slug":"getting-into-graphql-with-aws-appsync","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/getting-into-graphql-with-aws-appsync\/","title":{"rendered":"Getting into GraphQL with AWS AppSync"},"content":{"rendered":"

GraphQL<\/a> is becoming increasingly popular. The problem is that if you are a front-end developer, you are only half of the way there. GraphQL is not just a client technology. The server also has to be implemented according to the specification. This means that in order to implement GraphQL into your application, you need to learn not only GraphQL on the front end, but also GraphQL best practices, server-side development, and everything that goes along with it on the back end.<\/p>\n

<\/p>\n

There will come a time when you will also have to deal with issues like scaling your server, complex authorization scenarios, malicious queries, and more issues that require more expertise and even deeper knowledge around what is traditionally categorized as back-end development.<\/p>\n

Thankfully, we have an array of managed back-end service providers today that allow front-end developers to only worry about implementing features on the front end without having to deal with all of the traditional back-end work.<\/p>\n

Services like Firebase<\/a> (API) \/ AWS AppSync<\/a> (database), Cloudinary<\/a> (media), Algolia<\/a> (search) and Auth0<\/a> (authentication) allow us to offload our complex infrastructure to a third-party provider and instead focus on delivering value to end users in the form of new features instead.<\/p>\n

In this tutorial, we\u2019ll learn how to take advantage of AWS AppSync, a managed GraphQL service, to build a full-stack application without writing a single line of back-end code.<\/p>\n

While the framework we\u2019re working in is React, the concepts and API calls we will be using are framework-agnostic and will work the same in Angular, Vue, React Native, Ionic or any other JavaScript framework or application.<\/p>\n

We will be building a restaurant review app. In this app, we will be able to create a restaurant, view restaurants, create a review for a restaurant, and view reviews for a restaurant.<\/p>\n

\"An<\/figure>\n

The tools and frameworks that we will be using are React, AWS Amplify, and AWS AppSync.<\/p>\n

AWS Amplify is a framework that allows us to create and connect to cloud services, like authentication, GraphQL APIs, and Lambda functions, among other things. AWS AppSync is a managed GraphQL service.<\/p>\n

We\u2019ll use Amplify to create and connect to an AppSync API, then write the client side React code to interact with the API.<\/p>\n

View Repo<\/a><\/p>\n

Getting started<\/h3>\n

The first thing we\u2019ll do is create a React project and move into the new directory:<\/p>\n

npx create-react-app ReactRestaurants\r\n\r\ncd ReactRestaurants<\/code><\/pre>\n

Next, we\u2019ll install the dependencies we\u2019ll be using for this project. AWS Amplify<\/a> is the JavaScript library we\u2019ll be using to connect to the API, and we\u2019ll use Glamor<\/a> for styling.<\/p>\n

yarn add aws-amplify glamor<\/code><\/pre>\n

The next thing we need to do to is install and configure the Amplify CLI:<\/p>\n

npm install -g @aws-amplify\/cli\r\n\r\namplify configure<\/code><\/pre>\n

Amplify\u2019s configure will walk you through the steps needed to begin creating AWS services in your account. For a walkthrough of how to do this, check out this video<\/a>.<\/p>\n

Now that the app has been created and Amplify is ready to go, we can initialize a new Amplify project.<\/p>\n

amplify init<\/code><\/pre>\n

Amplify init will walk you through the steps to initialize a new Amplify project. It will prompt you for your desired project name, environment name, and text editor of choice. The CLI will auto-detect your React environment and select smart defaults for the rest of the options.<\/p>\n

Creating the GraphQL API<\/h3>\n

One we\u2019ve initialized a new Amplify project, we can now add the Restaurant Review GraphQL API. To add a new service, we can run the amplify add<\/code> command.<\/p>\n

amplify add api<\/code><\/pre>\n

This will walk us through the following steps to help us set up the API:<\/p>\n

? Please select from one of the below mentioned services GraphQL\r\n? Provide API name bigeats\r\n? Choose an authorization type for the API API key\r\n? Do you have an annotated GraphQL schema? N\r\n? Do you want a guided schema creation? Y\r\n? What best describes your project: Single object with fields\r\n? Do you want to edit the schema now? Y<\/code><\/pre>\n

The CLI should now open a basic schema in the text editor. This is going to be the schema for our GraphQL API.<\/p>\n

Paste the following schema and save it.<\/p>\n

\/\/ amplify\/backend\/api\/bigeats\/schema.graphql\r\n\r\ntype Restaurant @model {\r\n  id: ID!\r\n  city: String!\r\n  name: String!\r\n  numRatings: Int\r\n  photo: String!\r\n  reviews: [Review] @connection(name: \"RestaurantReview\")\r\n}\r\ntype Review @model {\r\n  rating: Int!\r\n  text: String!\r\n  createdAt: String\r\n  restaurant: Restaurant! @connection(name: \"RestaurantReview\")\r\n}<\/code><\/pre>\n

In this schema, we\u2019re creating two main types: Restaurant<\/strong> and Review<\/strong>. Notice that we have @model<\/strong> and @connection<\/strong> directives in our schema.<\/p>\n

These directives are part of the GraphQL Transform<\/a> tool built into the Amplify CLI. GraphQL Transform will take a base schema decorated with directives and transform our code into a fully functional API that implements the base data model.<\/p>\n

If we were spinning up our own GraphQL API, then we\u2019d have to do all of this manually:<\/p>\n

    \n
  1. Define the schema<\/li>\n
  2. Define the operations against the schema (queries, mutations, and subscriptions)<\/li>\n
  3. Create the data sources<\/li>\n
  4. Write resolvers that map between the schema operations and the data sources.<\/li>\n<\/ol>\n

    With the @model<\/strong> directive, the GraphQL Transform tool will scaffold out all schema operations, resolvers, and data sources so all we have to do is define the base schema (step 1). The @connection<\/strong> directive will let us model relationships between the models and scaffold out the appropriate resolvers for the relationships.<\/p>\n

    In our schema, we use @connection<\/strong> to define a relationship between Restaurant and Reviews. This will create a unique identifier for the restaurant ID for the review in the final generated schema.<\/p>\n

    Now that we\u2019ve created our base schema, we can create the API in our account.<\/p>\n

    amplify push<\/code><\/pre>\n
    ? Are you sure you want to continue? Yes\r\n? Do you want to generate code for your newly created GraphQL API Yes\r\n? Choose the code generation language target javascript\r\n? Enter the file name pattern of graphql queries, mutations and subscriptions src\/graphql\/**\/*.js\r\n? Do you want to generate\/update all possible GraphQL operations - queries, mutations and subscriptions Yes<\/code><\/pre>\n

    Because we\u2019re creating a GraphQL application, we typically would need to write all of our local GraphQL queries, mutations and subscriptions from scratch. Instead, the CLI will be inspecting our GraphQL schema and then generating all of the definitions for us and saving them locally for us to use.<\/p>\n

    After this is complete, the back end has been created and we can begin accessing it from our React application.<\/p>\n

    If you\u2019d like to view your AppSync API in the AWS dashboard, visit https:\/\/console.aws.amazon.com\/appsync<\/a> and click on your API. From the dashboard you can view the schema, data sources, and resolvers. You can also perform queries and mutations using the built-in GraphQL editor.<\/p>\n

    Building the React client<\/h3>\n

    Now that the API is created and we can begin querying for and creating data in our API. There will be three operations we will be using to interact with our API:<\/p>\n

      \n
    1. Creating a new restaurant<\/li>\n
    2. Querying for restaurants and their reviews<\/li>\n
    3. Creating a review for a restaurant<\/li>\n<\/ol>\n

      Before we start building the app, let\u2019s take a look at how these operations will look and work.<\/p>\n

      Interacting with the AppSync GraphQL API<\/h4>\n

      When working with a GraphQL API, there are many GraphQL clients available.<\/p>\n

      We can use any GraphQL client we\u2019d would like to interact with an AppSync GraphQL API, but there are two that are configured specifically to work most easily. These are the Amplify client (what we will use) and the AWS AppSync JS SDK<\/a> (similar API to Apollo client).<\/p>\n

      The Amplify client is similar to the fetch API<\/a> in that it is promise-based and easy to reason about. The Amplify client does not support offline out of the box. The AppSync SDK is more complex but does support offline out of the box.<\/p>\n

      To call the AppSync API with Amplify, we use the API category. Here\u2019s an example of how to call a query<\/strong>:<\/p>\n

      import { API, graphqlOperation } from 'aws-amplify'\r\nimport * as queries from '.\/graphql\/queries'\r\n\r\nconst data = await API.graphql(graphqlOperation(queries.listRestaurants))<\/code><\/pre>\n

      For a mutation<\/strong>, it is very similar. The only difference is we need to pass in a a second argument for the data we are sending in the mutation:<\/p>\n

      import { API, graphqlOperation } from 'aws-amplify'\r\nimport * as mutations from '.\/graphql\/mutations'\r\n\r\nconst restaurant = { name: \"Babalu\", city: \"Jackson\" }\r\nconst data = await API.graphql(graphqlOperation(\r\n  mutations.createRestaurant,\r\n  { input: restaurant }\r\n))<\/code><\/pre>\n

      We use the graphql<\/code> method from the API category to call the operation, wrapping it in graphqlOperation<\/code>, which parses GraphQL query strings into the standard GraphQL AST.<\/p>\n

      We\u2019ll be using this API category for all of our GraphQL operation in the app.<\/p>\n

      Here is the repo<\/a> containing the final code for this project.<\/p>\n

      Configuring the React app with Amplify<\/h4>\n

      The first thing we need to do in our app is configure it to recognize our Amplify credentials. When we created our API, the CLI created a new file called aws-exports.js<\/code> in our src<\/code> folder. <\/p>\n

      This file is created and updated for us by the CLI as we create, update and delete services. This file is what we\u2019ll be using to configure the React application to know about our services.<\/p>\n

      To configure the app, open up src\/index.js<\/code> and add the following code:<\/p>\n

      import Amplify from 'aws-amplify'\r\nimport config from '.\/aws-exports'\r\nAmplify.configure(config)<\/code><\/pre>\n

      Next, we will create the files we will need for our components. In the src<\/strong> directory, create the following files:<\/p>\n