├── .gitignore ├── README.md ├── package.json ├── public ├── favicon.ico ├── index.html └── manifest.json ├── src ├── assets │ ├── PeggyPhoto.jpg │ ├── apollo-client-new.png │ ├── apollo-client-old.png │ ├── apollo.svg │ ├── boost.jpg │ ├── cache-diagram.png │ ├── curve.png │ ├── introspection.png │ ├── links.png │ ├── normalization-diagram.png │ ├── normalization.png │ ├── pupstagram.png │ ├── react-ecosystem-summary.png │ └── urql.png ├── code │ └── index.js ├── images.js ├── index.js ├── presentation.js └── registerServiceWorker.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # testing 7 | /coverage 8 | 9 | # production 10 | /build 11 | 12 | # misc 13 | .DS_Store 14 | .env.local 15 | .env.development.local 16 | .env.test.local 17 | .env.production.local 18 | 19 | npm-debug.log* 20 | yarn-debug.log* 21 | yarn-error.log* 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Give Your Data a Boost! 🚀 (ReactFest 2018) 2 | 3 | ### [View the slides!](http://reactfest-apollo.surge.sh/#/) 💻 4 | ### [Watch the video!](https://youtu.be/jFULzAMS-jI) 📺 5 | 6 | ## Further exploration 7 | - [Zero-config GraphQL state management, Peggy Rayzis](https://dev-blog.apollodata.com/zero-config-graphql-state-management-27b1f1b3c2c3) 8 | - [Pupstagram example app](https://codesandbox.io/s/r5qp83z0yq) 9 | - [Thanks For The Feedback, Douglas Stone](https://books.google.co.uk/books?id=Da_KAQAAQBAJ&printsec=frontcover&dq=thanks+for+the+feedback&hl=en&sa=X&ved=0ahUKEwiZu4vhot_ZAhWbHsAKHTuGBcgQ6AEIJzAA#v=onepage&q=thanks%20for%20the%20feedback&f=false) 10 | - [The future of state management, Peggy Rayzis](https://dev-blog.apollodata.com/the-future-of-state-management-dd410864cae2) 11 | - [Apollo Link State tutorial, Sara Vieira](https://youtu.be/2RvRcnD8wHY) 12 | - [Syntax.fm GraphQL episode, Wes Bos & Scott Tolinski](https://syntax.fm/show/027/graphql-here-is-what-you-need-to-know) 13 | - [React Apollo v2 Query Component CodeSandbox, James Baxley](https://codesandbox.io/embed/71ro40qk16) 14 | - [npm State of JavaScript, Laurie Voss](https://www.npmjs.com/npm/the-state-of-javascript-frameworks-2017-part-2-the-react-ecosystem) 15 | 16 | ## Questions 17 | If you have any questions about the presentation or state management with GraphQL, please feel free to open an issue or start a conversation on [Twitter](https://twitter.com/peggyrayzis). 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reactfest-apollo", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "react": "^16.2.0", 7 | "react-dom": "^16.2.0", 8 | "spectacle-scripts": "2.0.0" 9 | }, 10 | "scripts": { 11 | "deploy": "npm run build && surge -p build", 12 | "start": "react-scripts start", 13 | "build": "react-scripts build", 14 | "test": "react-scripts test --env=jsdom", 15 | "eject": "react-scripts eject" 16 | }, 17 | "devDependencies": { 18 | "surge": "^0.19.0" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/peggyrayzis/reactfest-apollo/b0494fe5fa4991769fd7bc4dbaaa76ccbcb2c0ce/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 | 8 | 12 | 13 | 14 | 23 |
100 | My name is Peggy Rayzis and I'm an open source engineer for Apollo
101 | where I build tools to help more people discover the magic that is
102 | GraphQL. If you ever have questions about integrating GraphQL into
103 | your React apps, feel free to reach out to me on Twitter anytime.
104 |
105 | People always wonder what I actually do as an open source
106 | engineer. It changes every day! No two days are ever the same for
107 | me - sometimes I'm building a new feature for Apollo Client,
108 | reviewing pull requests, or evangelizing our tools on Twitter and
109 | Medium.
110 |
154 | One thing I've learned over the course of my time at Apollo is
155 | that developing open source software is all about giving and
156 | receiving feedback. I'm constantly giving feedback throughout my
157 | day whether I'm reviewing a coworker's blog post or a
158 | contributor's PR. Our team also receives a lot of feedback on
159 | Twitter, in Github issues, and Slack from the developers that use
160 | our tools. Not all of that feedback is positive.
161 |
162 |
163 | I think sometimes we as maintainers pour so much energy into our
164 | projects that sometimes, negative feedback is hard to swallow. We
165 | get defensive and try to justify why the person is wrong. Maybe we
166 | think they're not qualified to give us the feedback or maybe we
167 | think that the criticism isn't grounded in facts.
168 |
169 |
170 | I don't think this wrong-spotting is very productive. Instead, we
171 | should try to look at negative feedback as an opportunity to grow.
172 |
179 | In order to learn from negative feedback, we have to first 180 | understand it. What data did the feedback giver observe to arrive 181 | at that conclusion? By trying to see things from the other 182 | person's perspective, you'll start to see shreds of truth hidden 183 | within negative feedback. 184 |
185 |192 | We recently ran into this situation at Apollo. A couple weeks ago, 193 | we noticed some alternative GraphQL clients popping up in the 194 | ecosystem, like urql by Formidable Labs. These new clients did a 195 | great job at delivering an easy setup experience for users, which 196 | sparked discussion that Apollo was too difficult to set up, 197 | especially for beginners, or that we had lost our focus on the 198 | developer experience. 199 |
200 |
209 | Hearing feedback that we needed to improve our developer
210 | experience was tough. We easily could have dismissed this feedback
211 | by wrong spotting. However, that's not going to help our users or
212 | help us learn from our mistakes. Instead, we decided to take this
213 | as an opportunity to really think about the getting started
214 | experience with Apollo and what we could do to make GraphQL more
215 | approachable.
216 |
217 |
218 | Training yourself how to view negative feedback is not an easy
219 | task, but there's a book I really enjoy that's helped me change my
220 | mindset about how I give and receive feedback. It's called Thanks
221 | for the Feedback and I highly recommend that you check it out,
222 | especially if you're an open source maintainer.
223 |
226 |243 |236 | In the end, wrong spotting not only defeats wrong feedback, it 237 | defeats learning. 238 |239 | 240 | Douglas Stone, "Thanks for the Feedback" 241 | 242 |
247 | One thing we were curious about was the timing of the feedback - 248 | our Apollo Client 2.0 API and setup process had been the same for 249 | over 6 months, so why were we just starting to see the feedback 250 | now? One thing we realized was that the rapid growth of Apollo 251 | over the past year was bringing a lot of newcomers into the 252 | project. If you look at the chart from Laurie Voss of npm, you can 253 | see that downloads of Apollo Client grew 350% last year, with a 254 | lot of that growth happening the second half of the year. 255 |
256 |
264 | Adoption of a particular technology comes in phases. If you look
265 | at the speed of adoption plotted as a bell curve, you can see that
266 | early growth comes from innovators and early adopters. These
267 | people are usually ok with a little uncertainty, maybe they don't
268 | mind reading the source code or diving in deep when they need to
269 | solve a particular problem. The transition from early adopters to
270 | early majority is pretty significant however as that's when an
271 | idea starts to become mainstream. The early majority doesn't want
272 | to spend their time digging in source code, they want an easy
273 | experience that works out of the box.
274 |
275 |
276 | That's precisely the situation we were facing. As Apollo grows in
277 | popularity, the less tolerance newcomers have for complicated
278 | setup. We need to put ourselves in their shoes to figure out how
279 | to make setup easier.
280 |
287 | Here's all of the packages you had to install before. Sara was 288 | joking with me at dinner last night that I should make a rap of 289 | all the packages. I'm going to spare you my rapping skills, but 290 | just look at this! You have to know about the Apollo cache and 291 | what a link is, it's a lot of mental energy to expend when you're 292 | just starting out. Now, it seems so obvious but when you work on 293 | an open-source project for a long time, it's easy to forget how it 294 | feels to be starting out for the first time. 295 |
296 |308 | Our setup for Apollo Boost, our new zero-config Apollo Client, cut 309 | those packages in half. Not too shabby! 310 |
311 |323 | Here's what setting up Apollo Client looked like before. Having a 324 | pluggable cache and link chain is great for more advanced users, 325 | but the vast majority of people getting started with Apollo Client 326 | were using the same InMemoryCache and HttpLink. We needed to find 327 | a solution that worked for both power users and beginners alike. 328 |
329 |344 | So, we came up with Apollo Boost! Apollo Boost sets up our 345 | recommended defaults like the InMemoryCache and HttpLink for you. 346 | All you have to do is pass your GraphQL endpoint in to create your 347 | client. In yesterday's GraphQL workshop, we used Apollo Boost and 348 | had everything up and running in less than 10 minutes, which was 349 | super awesome to see! It's also important to mention that nothing 350 | is going away about the old setup. Apollo Boost is a wrapper on 351 | top of Apollo Client that includes all our recommended settings. 352 |
353 |368 | We want Apollo Boost to transition beginners into creating their 369 | first production-ready apps, so we included some additional 370 | packages in Apollo Boost that reflect best practices. Including 371 | your GraphQL endpoint, there's a total of 6 configuration options, 372 | all optional, you can pass to Apollo Boost. Underneath the hood, 373 | these packages are Apollo Links for error link, client-side data, 374 | and HttpLink. The first config option is onError, which is a 375 | global error handling function that receives both graphql and 376 | network errors. The next one is clientState. clientState is an 377 | object with the same properties you would pass to 378 | apollo-link-state, which allows you to manage local data in Apollo 379 | Client alongside your remote data. We're going to learn more about 380 | that later. fetchOptions allow you to pass static fetch options to 381 | your http link. What about if we want to dynamically set fetch 382 | options like headers? 383 |
384 |404 | That's where our new request function comes in! Before, you had to 405 | write your own Apollo Link and know about Observables in order to 406 | perform authentication. Now, you just pass a function to the 407 | request property that takes your graphql operation. From there, 408 | you can set headers dynamically on the context, which will be 409 | picked up by the http link. We're really excited about this 410 | feature because it abstracts all of the complexity of Apollo Link 411 | away without sacrificing any of the power. The request function 412 | can also return a promise in case you need to perform any async 413 | lookups. 414 |
415 |432 | Apollo Boost has only been out for a month, but we've heard a 433 | great response from the community so far. Not only are beginners 434 | loving it, we're also getting great feedback from instructors who 435 | teach workshops. For his new course on Advanced React and Apollo, 436 | Wes Bos was able to cut 100 LOC from his Apollo Client setup code 437 | by switching to Boost. If you're creating content, this is huge! 438 | That's 100 lines he doesn't have to explain, which means you can 439 | get to querying faster. 440 |
441 |443 |459 |453 | Apollo Boost cut my config down by 100 LOC - thanks! 454 |455 | 456 | Wes Bos, @wesbos 457 | 458 |
463 | Just because Apollo Boost is marketed as an easy way to get 464 | started doesn't mean it gives up any features. Apollo Boost brings 465 | you the same, consistent Apollo Client experience you know and 466 | love. That means declarative data fetching and being able to 467 | colocate your data requirements next to your UI. It also means 468 | zero-config caching, which we'll explain in detail soon. With 469 | apollo-link-state, you can combine local and server data in one 470 | query, which is something no other state management library has 471 | ever been able to offer. You also gain a painfree debugging 472 | experience with the Apollo Dev Tools and a soon to be released VS 473 | code extension. 474 |
475 |497 | What exactly do I mean by declarative data fetching? Let's look at 498 | a sample query for a list of dogs. With GraphQL, we can specify 499 | only the properties our component needs. 500 |
501 |516 | Then, we bind that GraphQL query to our UI by creating a query 517 | component. This is our new React Apollo 2.1 API, which is 518 | currently in beta but is about to be released very soon. It uses 519 | render props, which makes it really easy to compose multiple 520 | queries in one component. Apollo Client takes care of fetching 521 | your query and updating your component when data comes back. You 522 | also don't have to worry about manually tracking error and loading 523 | states - Apollo does that for you too! We talked about caching 524 | briefly before, how does Apollo Client cache our data? 525 |
526 |541 | The Apollo cache is awesome because it normalizes and stores your 542 | data for you. You don't have to mess around with normalizr or set 543 | any of this up yourself. This is a good thing because it turns out 544 | caching a graph is pretty hard. Luckily, we've already solved it 545 | with normalization. 546 |
547 |555 | Normalization is important because there are often multiple paths 556 | to access the same data with GraphQL. Here we have a sample UI for 557 | an article feed and an editor detail view. We have a query to get 558 | all of the articless for our feed. Let's say we want to make a 559 | change to our article's title with the updateArticle mutation on 560 | the detail page. Ideally, we want the data on the articles feed 561 | page to update with the new title as well. Keeping your data 562 | consistent and in sync is exactly why we normalize. 563 |
564 |580 | So you understand what's going on under the hood, I'm going to try 581 | and demystify the Apollo cache's normalization process for you. 582 | First, we have our articles query. You'll also see we have our 583 | response payload, which comes back as the shape of the query, with 584 | the addition of one meta field. That meta field is called 585 | __typename and it's added automatically for you when the data 586 | comes back from the server. For each nested part of the query with 587 | a typename and id, we split them out into their own node in the 588 | cache in a flattened map. For the articles query, we can see that 589 | the cache value is a list of pointers. This is because the cache 590 | reconstructs each result from the flattened nodes in the cache. 591 |
592 |608 | Don't worry if this sounds a little complicated, you can fully 609 | inspect your cache in Apollo DevTools to see what's going on. On 610 | the left, you can explore all of the nodes in the cache and see 611 | this flattened structure in action. 612 |
613 |622 | One of the coolest features of Apollo Boost is that it includes 623 | one of our newest releases apollo-link-state, which allows you to 624 | manage your local data with Apollo Client and query it with 625 | GraphQL. link-state is truly pushing the boundaries of GraphQL 626 | outside the context of the server and it's super helpful if you're 627 | already using apollo for your remote data.. 628 |
629 |637 | For you to understand just how exciting apollo-link-state is, we 638 | first must look at Apollo's past. Historically, users put all of 639 | their remote data into Apollo Client. This equated to about 80% of 640 | their data, but what about the other 20% for things like boolean 641 | flags, device API results. For that local data, users maintained a 642 | separate Redux store. Keeping this store in sync with changes in 643 | our remote data became tricky, especially as Apollo Client 2.0 644 | moved off of Redux last year. 645 |
646 |655 | With state link, we now have the ability to query all of our 656 | application's local and remote data with GraphQL. This has several 657 | advantages - first, GraphQL becomes a unified interface for all of 658 | our data. It doesn't matter if that data is coming from a REST 659 | endpoint or your local cache, you query all of it the exact same 660 | way. Also, the Apollo cache becomes our single source of truth. No 661 | more managing a separate store - now you can manage your local 662 | data the same way you manage your remote data. You can even add 663 | client only properties to objects you get back from the server. 664 | Let's see an example of how we would do that: 665 |
666 |675 | In order to tell the Apollo Client network stack that we need to 676 | pull a field from the cache, we mark it with the @client 677 | directive. Here, you have a mixed query of both remote and local 678 | data. 679 |
680 |695 | Now that we have our query, how do we resolve the data from the 696 | cache? That's where our resolvers come in. The API you use to 697 | create resolvers on the server with graphql-tools is the exact 698 | same API you use to create resolvers on the client with link 699 | state. You have your root value, any arguments, and also your 700 | context, which is where you pull the cache from in order to 701 | directly read and write to it. Another cool feature is that you 702 | can also return values from mutations, but you don't have to. This 703 | can be useful if you're creating a todo and want to get back the 704 | new todo's id for example. 705 |
706 |718 | Next, you'll want to add your resolvers to Apollo Boost by passing 719 | them to the clientState config property. This is where all your 720 | configuration for apollo-link-state goes with the exception of the 721 | cache since we already pass that in for you. 722 |
723 |738 | Now that our resolvers are all hooked up, how do we fire a local 739 | mutation in our app? Here, we're using the @client directive again 740 | to indicate that this mutation should resolve locally. 741 |
742 |757 | Once you have your GraphQL mutation, just include it in your 758 | mutation component as you normally would. The render prop for the 759 | mutation component exposes a mutate function as the first argument 760 | that you can use in your component to actually trigger the 761 | mutation. 762 |
763 |778 | I encourage you to experiment with client side state management in 779 | Apollo Boost. You may find that it simplifies your current Redux 780 | code considerably, as it did for Scott. It's still pretty early 781 | but we're really excited about the idea of managing our local data 782 | with GraphQL and can't wait to see how it evolves. Now we're going 783 | to talk about what that might look like... 784 |
785 |787 |805 |797 | Switching from Redux to Apollo Link State simplified how I 798 | interact with my codebase significantly, by allowing me to 799 | integrate my local state with GraphQL & Apollo. 800 |801 | 802 | Scott Tolinski, Level Up Tuts (@stolinski) 803 | 804 |
809 | You probably noticed I didn't mention client-side schemas at all 810 | when talking about state-link. That's because they are a tricky 811 | problem to solve. Since the graphql modules for validating a 812 | schema are extremely large, we can't just include them the way we 813 | would on the server. Recently, we got a working prototype of the 814 | client-side schema working. While this schema does not perform 815 | type validation, it does allow you to write a schema in schema 816 | definition language and perform introspection against its AST. 817 |
818 |
832 | If we can perform introspection against a client-side schema, then
833 | we can integrate our client-side schema into our tooling!! We have
834 | an early prototype of client-side schema introspection stitched
835 | alongside our remote schema. This is huge! Now you can inspect
836 | your remote APIs alongside your client data without ever having to
837 | leave the devtools. This also brings a whole host of other
838 | features, such as autocomplete when running queries in GraphiQL
839 | and the ability to perform tracing analysis on our data. Right
840 | now, this feature is in alpha but we're hoping to release it very
841 | soon.
842 |
843 |
844 | If we can stitch together a client-schema with our remote-schema,
845 | we can stitch together anything. Imagine being able to explore
846 | your Gatsby schema for static data alongside your dynamic client
847 | data. GraphQL becomes a unified interface for accessing all of the
848 | data that flows through your application.
849 |
855 | Now that we have the ability to stitch together the schemas for
856 | multiple data sources, we'll be able to integrate introspection
857 | into a variety of different tools. The most obvious case is dev
858 | tools, but we also have a VS Code plugin in the works that will
859 | feature autocomplete as youre typing out your queries in your
860 | editor. We can also integrate our client data into Apollo Engine
861 | to analyze performance and tracing data. With GraphQL as our
862 | unified interface to all of our data, our tooling suddenly becomes
863 | more cohesive and unified across the stack. This is not only great
864 | for developer productivity, but it is the key in my opinion to
865 | reducing configuration fatigue. With GraphQL, you can teach
866 | someone how to build a resolver once and they'll automatically be
867 | able to apply their knowledge across the stack for both local and
868 | remote data.
869 |
870 |
871 | This is all so fresh and new, but I think we're on the cusp of
872 | something really exciting here that's revolutionizing how we
873 | interact with data in our React apps. I can't wait to see what the
874 | future holds for Apollo & GraphQL.
875 |
884 | We're almost at the end so I wanted to mention that all the code 885 | samples I showed you today are featured in our newest example app 886 | called pupstagram. It's like instagram but for favoriting pictures 887 | of dogs, which is honestly all I use instagram for anyways. It's 888 | up on CodeSandbox and I'll tweet the link after my talk. 889 |
890 |898 | Before I go, I want to leave you with one final message. 899 | Practicing empathy while building open source software is so so so 900 | important to make sure we're meeting the needs of a diverse base 901 | of users. I know it's not easy either. The longer you work on an 902 | open source project, the tougher it is to put yourselves in the 903 | shoes of someone who’s discovering the project for the first time. 904 | As library authors at Apollo, we want to work harder at this. Our 905 | main goal is to make GraphQL more approachable for everyone. For 906 | us, building Apollo Boost was an awesome chance for us to focus on 907 | empathy, and we’re really happy with the creative solutions that 908 | came from it. I challenge all of you to take a step back and 909 | practice empathy building your software too. 910 |
911 |