

9th Nov 2016
Berlin
3
2
1

GO!
Hallo
Ich bin Kamil
back to English...
Warsaw
Berlin
some sea
some sea
some sea
some border
some border
some border
some border
some city
some city
some city
some city
some city
some city
some city
some city
I live here
you live here

kamilkisiela
GraphQL and Angular
Landing on the ngMoon with Apollo


today
components
components
app is based on components

app



components
app = component
app





data
components need data
    @Component({
      template: `
        Author: {{comment.author}}
        Text: {{comment.text}}
      `
    })
    class CommentComponent {
      comment: Comment;
    }data
provide it directly
    @Component({
      template: `
        Author: {{comment?.author}}
        Text: {{comment?.text}}
      `
    })
    class CommentComponent {
      comment: Comment;
      @Input() commentId: number;
      constructor(private http: Http) {}
      ngOnInit() {
        this.http.get(`https://api.com/comment/${this.commentId}`)
          .map(res => res.json())
          .subscribe((comment) => this.comment = comment);
      }
    }problem?
where is the problem?
with data
managing data is not ideal now
there must be a better way!
components

Smart
Dumb



Container
Presentational
=
components
what it means "smart and dumb"?


data
provide
display
Smart component
Dumb component
back to the example
data
data is provided directly
    @Component({
      template: `
        Author: {{comment?.author}}
        Text: {{comment?.text}}
      `
    })
    class CommentComponent {
      comment: Comment;
      @Input() commentId: number;
      constructor(private http: Http) {}
      ngOnInit() {
        this.http.get(`https://api.com/comment/${this.commentId}`)
          .map(res => res.json())
          .subscribe((comment) => this.comment = comment);
      }
    }data
make it dumb
    @Component({
      template: `
        Author: {{comment?.author}}
        Text: {{comment?.text}}
      `
    })
    class CommentComponent {
      @Input() comment: Comment;
    }data
add the brain
    @Component({
      template: `
        <comment [comment]="comment | async"></comment>
      `
    })
    class CommentContainerComponent {
      @Input() commentId: number;
      comment: Observable<Comment>;
      constructor(private http: Http) {}
      ngOnInit() {
        this.comment = this.http
          .get(`https://api.com/comment/${this.commentId}`)
          .map(res => res.json())
      }
    }still not a good idea
services!
yes, services, we love them!
service
use a service to handle data fetching
    @Component({
      template: `
        <comment [comment]="comment | async"></comment>
      `
    })
    class CommentContainerComponent {
      @Input() commentId: number;
      comment: Observable<Comment>;
      constructor(private commentsApi: CommentsApi) {}
      ngOnInit() {
        this.comment = this.commentsApi.single(this.commentId);
      }
    }pff... done
now everyone is happy
besides your clients...
and your developers!
problems
overloaded network
overloaded network





API
http
unnecessary requests
unnecessary requests



API
http
comment #1
comment #3
comment #4
comment #2


inconsistent data

inconsistent data

time
comment
comment
{
  id: 13
  likes: 20
}
{
  id: 13
  likes: 21
}
someone likes the comment
overfetched data
overfetched data
size does matter
GraphQL is awesome!
posted by Kamil
{ text: "GraphQL is awesome!", postedBy: "Kamil", createdAt: 1478368227, likes: 2 }

adjustments
adjustments
data structure doesn't always fit the actual needs
{
  contents: "GraphQL is awesome!",
  author:   "Kamil"
}

{{comment.text}} by {{comment.postedBy}}
client depends on API
API change requires a reflection in an app
solutions
use GraphQL
THE END
thank you
NOT
"oh no... he continues"
not the end?
they say GraphQL is a cure for everything!
GraphQL is helpful
but... it doesn't solve every of those problems
what it solves
separation
GraphQL makes client totally independent
client depends on API
define what you need
and change it any time you want in any component
overfetched data
own the structure
define exact shape of data you want to use
adjustments
use fragments
bound it with components
use fragments
to define what a component needs
    // Comment component
    CommentInfoFragment = gql`
      fragment CommentInfo on Comment {
        id
        text
        author
      }
    `;
    // CommentsPage Component
    const ALL_COMMENTS_QUERY = gql`
      query getAllComments {
        allComments {
          ...CommentInfo
        }
      }
      ${CommentInfoFragment}
    `;
    this.apollo.watchQuery({
      query: ALL_COMMENTS_QUERY
    });
what about the network?
GraphQL is just a language
back to the example
let's find proper solutions
    @Component({
      template: `
        <comment [comment]="comment | async"></comment>
      `
    })
    class CommentContainerComponent {
      @Input() commentId: number;
      comment: Observable<Comment>;
      constructor(private commentsApi: CommentsApi) {}
      ngOnInit() {
        this.comment = this.commentsApi.single(this.commentId);
      }
    }back to the example
where we left off
CommentsApi
our service to fetch comments from the API
    class CommentsApi {
      url: string = `https://api.com/comment/`;
 
      constructor(private http: Http) {}
 
      single(id: number) {
        return this.http.get(this.url + id)
          .map(res => res.json());
      }
    }CommentsApi
how it looks now
implement GraphQL
    class CommentsApi {
      url: string = `https://api.com/query?=`;
 
      constructor(private http: Http) {}
 
      single(id: number) {
        const query = `
          query getComment {
            Comment(id: ${id}) {
              text
              postedBy
            }
          }
        `;
        return this.query(query);
      }
      query(query: string) {
        return this.http.get(this.url + JSON.stringify(query))
          .map(res => res.json().data.comment)
      }
    }CommentsApi
with GraphQL
catch them all!
and use only one
unnecessary requests
Request batching
wait for some time to catch the same requests
time





10 ms
batching

server
solved for requests
with batching we don't get different results
for the same queries
inconsistent data
caching
use store to keep all the results
overloaded network
caching
use store to cache a query


cache

server
request
UI
bigger and bigger
our service is getting more and more complex
open-source it!
looks like it could be helpful for many people
someone did
somewhere there is a magic tool!
it's called
apollo
what is Apollo?
GraphQL client
solves the problems we talked about
exactly what we need
to create modern web apps
so
we own the network
but...
what about UX?
Apollo to the rescue
UX
latency
users don't like to wait
Optimistic UI

Optimistic UI
don't make them wait
1. We submit a comment
2. Request is made
2. We update the UI in the same moment
3. We get the response from the server later
1.
2.
2.
3.
Optimistic UI
how it works

Mutation


UI
optimistic response
real response
latency yet again
how to make an app even faster?
prefetching
prefetching
without
1. Enter the route
2. Request is made
3. Wait for the response
4. Update the UI

prefetching
with
1. User puts cursor over the link
2. Request is made to fetch the query
3. We put the response inside the cache
4. User enters the page imidiately

real time
get the experience
Subscriptions
Subscriptions
keep things updated


action
server

clients
pub sub
SEO
people should visit!
server side rendering
click the logo to see a working example
server side rendering
prefetch queries on the server
server
client


fetch query
save to store


fetch query
render with the same store
update the UI imidiately
still not enough
make it even faster
Ahead-of-Time
compilation to speed up the runtime
what if...
we could make just one request with all queries
Query Batching
one request per render
Query batching
You can even specify your custom batch interval
time




10 ms
batching

server
interval
cool


angular?
 
only for Angular?
can I use it with other frameworks?
YES!
with Angular 1.X

and many others
all share the same principals
enough
hit me with any questions!
?
it was fun!
feel free to message me
come to Poland!
thanks
*danke

bye bye bye bye bye bye
Copy of GraphQL and Angular
By Kamil Kisiela
Copy of GraphQL and Angular
Let's talk about problems with data management in Angular and why we should use GraphQL and Apollo. Is it a solution for modern web apps that we're all looking for?
- 728
 



