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?
- 652