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
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
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
- JavaScript client for GraphQL (apollo-client)
- API to run queries and mutations (apollo-angular)
- Template literal (graphql-tag)
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
- Server side package to connect with the pub/sub system (graphql-subscriptions)
- WebSocket client + server (subscriptions-transport-ws)
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!
Building your first GraphQL Application using Angular (v4+)
By Gerard Sans
Building your first GraphQL Application using Angular (v4+)
In this hands-on workshop we are going to learn about GraphQL and how to build a basic application using the latest version of Angular, the Apollo Client and graphcool, a GraphQL backend as a service.
- 4,164