Building your first GraphQL Application  (v4+)  

by Gerard Sans (@gerardsans)

Laptops shiny and ready by 14:45

Install github.com/gsans/iwd2017-first-graphql-app

Agenda

14:45 Welcome

          Instructions and setup

          Slides

          Practice, Q&A

16:30 Wrapping up

Google Developer Expert

Blogger

Master of Ceremonies

International Speaker

Angular 2 Trainer

Community Leader

800

700

Angular

Features

  • Latest Web Standards
  • Simple
  • Lightning fast
  • Works everywhere

new in Angular

Angular Version

// index.html
<my-app ng-version="4.0.0-rc.2">
  <div>
    <h2>Hello Angular 4! 👋</h2>
  </div>
</my-app>

Semantic Versioning

  • v4 March 2017
  • v5 Sept/Oct 2017
  • v6 March 2018
  • v7 Sept/Oct 2018

new features

  • Improved AOT size
  • Separated animations bundle
  • latest TypeScript 2.2
  • platform-server (Universal)
  • *ngIf="condition; then a else b"

GraphQL

GraphQL co-authors

Lee Byron

Nick Schrock

Dan Schafer

GraphQL Timeline

2012

GraphQL created at Facebook

Support Mobile Native Teams

2015

Open sourced

First Specification

GraphQL.js

2016

GitHub announces GraphQL API

New GraphQL website

First GraphQL Summit

GraphQL First

 

2017

GraphQL Europe

Apollo Client 0.10.0 (RC-0)

graphql.org

Apollo Optics

May

graphql-europe.org

Speakers

Lee Byron

Sashko Stubailo

GraphQL Server

source: blog

Implementations

Query Language


// GET '/graphql'
{
 user(name: "gsans") {
  twitter
 }
}

// result
{
 "user": {
  "twitter": "@gerardsans"
 }
}

Who is using it?

Solution Architecture

demo

Components Tree

source: blog

Components Tree

<app>
  <add-todo>
    <input><button>Add todo</button>
  </add-todo>
  <todo-list>
    <ul>
      <todo id="0" completed="false"><li>buy milk</li></todo>
    </ul>
  </todo-list>
  <filters>
    Show: <filter-link><a>All</a><filter-link> ... 
  </filters>
</app>

GraphQL Schema

Type System

  • Scalar Types: Int, Float, String, Boolean, ID 
  • Object Types: Todo
  • Entry points: Query, Mutation, Subscription*

Schema Syntax

  • Nullable: String, Todo
  • Non-nullable: String!, Todo!
  • Arrays: [String], [Todo]

Todos Schema (1/2)

schema { 
  query: Query,  
  mutation: Mutation 
}

type Query {
  allTodoes(skip: Int, take: Int): [Todo!]!
}

type Todo {  
  id: ID!
  text: String!
  complete: Boolean!
}

Todos Schema (2/2)

schema { 
  query: Query,  
  mutation: Mutation,
}

type Mutation {
  createTodo(text: String!, complete: Boolean!): Todo
  updateTodo(id: ID!, text: String, complete: Boolean): Todo
}

GraphiQL

demo

Apollo Client

GraphQL Server

source: blog

Dependencies

Setup

// client.ts
import { ApolloClient, createNetworkInterface } from 'apollo-client';

const client = new ApolloClient({ 
  networkInterface: createNetworkInterface({
    uri: 'https://api.graph.cool/ZZZ'
  })
});

export function provideClient(): ApolloClient {
  return client;
}

Bootstrap

// app.module.ts
import { provideClient } from 'apollo-client';
import { ApolloModule } from 'angular2-apollo';
import { App } from './app.component';

@NgModule({
  imports: [
    BrowserModule,
    ApolloModule.withClient(provideClient)
  ],
  declarations: [ App ],
  bootstrap: [ App ]
})
class AppModule {}

platformBrowserDynamic().bootstrapModule(AppModule);

Main APIs

  • query (Observable)
  • watchQuery (Observable)
  • mutate (Observable)
  • updateQueries (reducer)

query (Observable)

// app.component.ts
@Component({ ... })
export class App { 
   constructor(private apollo: Angular2Apollo){
    let query$ = apollo.query({
      query: gql`query todos { 
        allTodoes { id complete text } }`, 
      forceFetch: true
    });
    let subscription = query$.subscribe({
      next: result => {
        // result.data.allTodoes
      },
      error: error => {
        console.log(`Error: ${error.message}`);
      }
    });
  }
}

mutate (Observable)

// todo.component.ts
@Component({ ... })
export class Todo {
 private onTodoClick(){ 
  let toggle$ = this.apollo.mutate({
   mutation: gql`
    mutation toggleTodo($id: ID!, $complete: Boolean!) {
     updateTodo(id: $id, complete: $complete) { id complete }
    }`,
   variables: { id: this.id, complete: !this.complete }
  });
  let subscription = toggle$.subscribe(
    ({ data }) => { // data.updateTodo.id }
  ); 
 }
}

watchQuery (Observable)

// todoList.component.ts
@Component({
  template:
    `<todo *ngFor="let todo of todos | async">{{todo.text}}</todo>`
})
class TodoList implements OnInit {
  todos: ApolloQueryObservable<any>;
  constructor(private apollo: Angular2Apollo) { }

  ngOnInit() {
    this.todos = this.apollo.watchQuery({ query: todosQuery })
      .map(({data}) => data.allTodoes);
  }
  // onRefresh = this.data.refetch;
}

demo

Subscriptions

(Experimental)

GraphQL Server

source: blog

Dependencies

Setup

// client.ts
import { Client } from 'subscriptions-transport-ws';

export const wsClient = new Client('ws://subscriptions.graph.cool/ZZZ', {
  timeout: 10000
});

Posts Schema

schema { 
  query: Query,  
  mutation: Mutation,
  subscription: Subscription 
}
type Post { 
  id: ID! 
  description: String! 
  imageUrl: String!
}
type Mutation {
  createPost(description: String!, imageUrl: String!): Post
}

type Subscription {
  createPost(): Post
}

wsClient.subscribe

// feed.component.ts

wsClient.subscribe({
  query: `subscription newPosts {
    createPost { id description imageUrl }  
  }`,
  variables: null
}, (err, res) => {
  // res.createPost = { id: 34, description: 'woot', imageUrl: '...' } 
  // err = [{ message: 'Connection Timeout', stack: '...' }]
});

demo

Why use GraphQL?

Some reasons

  • Declarative
  • De-coupled from storage
  • Validated and structured
  • Facilitates Collaboration
  • Super fast

Examples

Links

Thanks!