From a728d99692becf1aba619589efe32e53b5d71419 Mon Sep 17 00:00:00 2001 From: David Anyatonwu Date: Fri, 19 Jul 2024 09:59:53 +0100 Subject: [PATCH 1/5] feat(docs): add GraphQL in Vue guide with 5 data fetching approaches --- graphql/graphql-vue-clients.md | 908 +++++++++++++++++++++++++++++++++ graphql/sidebar.ts | 9 +- 2 files changed, 916 insertions(+), 1 deletion(-) create mode 100644 graphql/graphql-vue-clients.md diff --git a/graphql/graphql-vue-clients.md b/graphql/graphql-vue-clients.md new file mode 100644 index 0000000000..78e0d5e159 --- /dev/null +++ b/graphql/graphql-vue-clients.md @@ -0,0 +1,908 @@ +--- +title: "GraphQL in Vue: 5 Best Approaches for Data Fetching" +description: "Explore Apollo Vue, Villus, and other methods for efficient GraphQL integration in Vue applications, with detailed comparisons and error handling strategies." +sidebar_label: "GraphQL with Vue" +slug: graphql-vue-client +--- + +## Introduction + +### GraphQL in Vue: 5 Best Approaches for Data Fetching + +Hey there, Vue enthusiasts! πŸ‘‹ Are you ready to supercharge your data fetching game? Buckle up, because we're about to embark on an exhilarating journey through the world of GraphQL in Vue! + +You know that feeling when you're trying to fetch data for your Vue app, and it feels like you're wrestling with an octopus? πŸ™ Well, fear not! GraphQL is here to turn that octopus into a well-behaved pet that fetches exactly what you need, when you need it. + +In this guide, we'll explore five fantastic approaches to integrating GraphQL with Vue. It's like we're about to open a treasure chest of data fetching goodies, and trust me, you'll want to get your hands on these gems! πŸ’Ž + +So, whether you're a GraphQL newbie or a seasoned pro, there's something here for everyone. We'll dive deep into each method, compare them side by side, and even tackle the thorny issue of error handling. By the end of this article, you'll be slinging GraphQL queries like a data-fetching superhero! πŸ¦Έβ€β™€οΈ + +Ready to level up your Vue app? Let's dive in! + +### πŸ› οΈ Project Setup + +Let's start by setting up our Vue project with Vite, which provides a faster and leaner development experience: + +```bash +npm create vite@latest vue-graphql-tailcall-showcase -- --template vue-ts +cd vue-graphql-tailcall-showcase +npm install +``` + +This creates a new Vue 3 project with TypeScript support. Now, let's install the necessary dependencies for our GraphQL experiments: + +```bash +npm install @apollo/client @vue/apollo-composable graphql +npm install @urql/vue +npm install axios +npm install villus +``` + +These installations will allow us to explore different GraphQL client options in our Vue application. + +### πŸ”§ Tailcall Backend Configuration + +Now, let's set up our Tailcall backend that will wrap the JSONPlaceholder API, providing a GraphQL interface to RESTful data. + +First, create a `tailcall` directory in the project root: + +```bash +mkdir tailcall +``` + +Then, create a `jsonplaceholder.graphql` file in this directory: + +```graphql +# File: tailcall/jsonplaceholder.graphql + +schema + @server(port: 8000, hostname: "0.0.0.0") + @upstream( + baseURL: "http://jsonplaceholder.typicode.com" + httpCache: 42 + ) { + query: Query +} + +type Query { + posts: [Post] @http(path: "/posts") + user(id: Int!): User @http(path: "/users/{{.args.id}}") +} + +type User { + id: Int! + name: String! + username: String! + email: String! + phone: String + website: String +} + +type Post { + id: Int! + userId: Int! + title: String! + body: String! + user: User @http(path: "/users/{{.value.userId}}") +} +``` + +This GraphQL schema defines our API structure, mapping RESTful endpoints to GraphQL types and queries. + +To start the Tailcall server, you'll need to have Tailcall installed. If you haven't installed it yet, follow the installation instructions from the Tailcall documentation. Once installed, you can start the server with: + +```sh +tailcall start ./tailcall/jsonplaceholder.graphql +``` + +This command starts a GraphQL server on `http://localhost:8000`, which will act as a bridge between our Vue application and the JSONPlaceholder API. + +With this setup, we're ready to dive into the exciting world of GraphQL in Vue! πŸš€ Our Tailcall backend provides a perfect playground for exploring different GraphQL client approaches, allowing us to fetch posts and user data with the flexibility and power of GraphQL queries. In the following sections, we'll explore how to leverage this backend with various GraphQL clients in our Vue application. Get ready for some data-fetching magic! ✨ + +Alright, let's dive into our first approach: Apollo Client! πŸš€ + +## Approach 1: Apollo Client - The Swiss Army Knife of GraphQL + +Picture this: You're a data-fetching chef, and Apollo Client is your top-of-the-line kitchen knife set. It's sharp, versatile, and makes slicing through complex queries feel like cutting through butter. Let's see how we can whip up a delicious Vue dish with Apollo Client! + +### 1. Installation and Integration Steps + +First things first, let's get our ingredients ready. You'll need to install the following packages: + +```bash +npm install @apollo/client @vue/apollo-composable graphql +``` + +Now, let's set the table. In your `main.js` file, you'll need to create an Apollo Client instance and provide it to your Vue app. It's like setting up your kitchen before you start cooking! + +```javascript +import {createApp, provide, h} from "vue" +import { + ApolloClient, + InMemoryCache, +} from "@apollo/client/core" +import {DefaultApolloClient} from "@vue/apollo-composable" + +const apolloClient = new ApolloClient({ + uri: "YOUR_GRAPHQL_ENDPOINT", + cache: new InMemoryCache(), +}) + +const app = createApp({ + setup() { + provide(DefaultApolloClient, apolloClient) + }, + render: () => h(App), +}) +``` + +### 2. Code Snippets + +Now, let's get cooking! Here's how you can use Apollo Client in your Vue component: + +```typescript + + + +``` + +Isn't that neat? 😎 With Apollo Client, fetching data is as easy as pie. The `useQuery` composable does all the heavy lifting for you, serving up your data on a silver platter. + +### 3. Error Handling + +But wait, what if something goes wrong in our kitchen? Don't worry, Apollo Client has got your back with some top-notch error handling: + +```typescript +const networkError = (ref < string) | (null > null) +const graphqlError = (ref < string) | (null > null) +const unexpectedError = (ref < string) | (null > null) + +watch(error, (newError) => { + if (newError) { + if (newError.networkError) { + networkError.value = + "Network error: " + newError.networkError.message + } else if ( + newError.graphQLErrors && + newError.graphQLErrors.length > 0 + ) { + graphqlError.value = + "GraphQL error: " + + newError.graphQLErrors + .map((e) => e.message) + .join(", ") + } else { + unexpectedError.value = + "Unexpected error: " + newError.message + } + } else { + networkError.value = null + graphqlError.value = null + unexpectedError.value = null + } +}) +``` + +This error handling is like having a sous chef who catches any mishaps before they ruin your dish. Network errors, GraphQL errors, or unexpected issues - all neatly categorized and ready to be displayed to the user. + +### 4. Why Apollo Client Rocks + +1. **Powerful Caching**: Apollo Client comes with a built-in caching system that's smarter than your average bear. It automatically caches your query results, making subsequent requests lightning fast. + +2. **Real-time Updates**: With Apollo Client, your app can feel alive! It supports real-time updates out of the box, perfect for those dynamic, data-driven applications. + +3. **Optimistic UI**: Want to make your UI feel snappy? Apollo Client's optimistic UI features let you update the UI before the server responds. It's like time travel for your data! + +4. **Developer Tools**: The Apollo DevTools extension for Chrome is like having x-ray vision for your GraphQL queries. Debug, inspect cache, and watch your queries in real-time! + +So there you have it, folks! Apollo Client - the superhero of GraphQL clients. It's powerful, flexible, and comes with more features than you can shake a stick at. But is it the perfect fit for every scenario? Stay tuned as we explore more approaches and find out! + +Next up, we'll be looking at another contender in the GraphQL arena. Will it give Apollo a run for its money? Let's find out! πŸƒβ€β™‚οΈπŸ’¨ + +## Approach 2: URQL - The Lightweight Contender + +Ladies and gentlemen, put your hands together for URQL! πŸ‘ If Apollo Client is the heavyweight champion of GraphQL clients, URQL is the nimble featherweight that packs a surprising punch. Let's dive into this lean, mean, data-fetching machine! + +### 1. Installation and Integration Steps + +First things first, let's get URQL into our Vue ring. It's as easy as: + +```bash +npm install @urql/vue graphql +``` + +Now, let's set up our URQL client. It's like preparing a lightweight but powerful sports car for a race: + +```javascript +import {createApp} from "vue" +import urql, {createClient} from "@urql/vue" + +const client = createClient({ + url: "YOUR_GRAPHQL_ENDPOINT", +}) + +const app = createApp(App) +app.use(urql, client) +``` + +### 2. Code Snippets + +Alright, let's see URQL in action! Here's how you can use it in your Vue component: + +```typescript + + + +``` + +Wow, look at that sleek code! 😍 URQL keeps things simple and straightforward. The `useQuery` composable gives you everything you need to fetch data and handle the query state. + +### 3. Error Handling + +But what if our lightweight contender stumbles? No worries, URQL's got some nifty error handling moves: + +```typescript +const networkError = (ref < string) | (null > null) +const graphqlError = (ref < string) | (null > null) +const unexpectedError = (ref < string) | (null > null) + +watch(error, (newError) => { + if (newError) { + if (newError.networkError) { + networkError.value = + "Network error: " + newError.networkError.message + } else if ( + newError.graphQLErrors && + newError.graphQLErrors.length > 0 + ) { + graphqlError.value = + "GraphQL error: " + + newError.graphQLErrors + .map((e) => e.message) + .join(", ") + } else { + unexpectedError.value = + "Unexpected error: " + newError.message + } + } else { + networkError.value = null + graphqlError.value = null + unexpectedError.value = null + } +}) +``` + +This error handling is like having a skilled cornerman in your boxing match. It catches and categorizes errors, ensuring you're never caught off guard. + +### 4. Why URQL Rocks + +1. **Lightweight Champion**: URQL is like the minimalist's dream GraphQL client. It's small, fast, and doesn't come with unnecessary baggage. + +2. **Extensibility**: Don't let its size fool you! URQL is highly extensible. Need more features? Just add some exchanges (URQL's middleware system) and you're good to go! + +3. **Easy to Understand**: URQL's simplicity makes it a breeze to learn and use. It's like the "easy to pick up, hard to master" of GraphQL clients. + +4. **Built-in Cache**: While not as sophisticated as Apollo's, URQL comes with a built-in normalized cache that gets the job done for most use cases. + +So, there you have it! URQL - the lightweight contender that proves sometimes less is more. It's perfect for those who want a no-frills, straightforward GraphQL experience. + +But wait, we're not done yet! 🎭 We've seen the heavyweight and the lightweight, but what other flavors of GraphQL goodness await us? Stay tuned as we continue our journey through the GraphQL landscape in Vue! + +Up next, we'll be exploring yet another approach. Will it be the Goldilocks of GraphQL clients - just right? Let's find out! πŸ•΅οΈβ€β™€οΈ + +## Approach 3: Fetch API - The DIY Dynamo + +Alright, Vue enthusiasts! πŸ› οΈ It's time to roll up our sleeves and get our hands dirty with the Fetch API. If Apollo and URQL are like ordering a gourmet meal, using Fetch API is like cooking that meal yourself from scratch. It's time to channel your inner GraphQL chef! + +### 1. Installation and Integration Steps + +Here's the beauty of the Fetch API - it comes built-in with modern browsers! No need to install any extra packages. It's like finding out your kitchen already has all the tools you need. How's that for convenience? + +### 2. Code Snippets + +Let's dive into our DIY GraphQL solution: + +```typescript + + + +``` + +Look at that! We're crafting our GraphQL requests by hand. It's like being a data-fetching artisan. 🎨 + +### 3. Error Handling + +When you're cooking up your own GraphQL solution, you need to be prepared for things to get a little messy. But don't worry, we've got a robust error handling system: + +```javascript +try { + // ... fetch logic ... +} catch (err: any) { + if (err.message.startsWith('HTTP error!')) { + networkError.value = err.message + } else { + unexpectedError.value = err.message + } +} finally { + loading.value = false +} +``` + +This error handling is like having a fire extinguisher in your kitchen. It's there to catch and categorize any mishaps, ensuring your app doesn't go up in flames! + +### 4. Why Fetch API Rocks + +1. **Ultimate Control**: With Fetch API, you're the master of your own destiny. Want to customize how requests are sent? Go for it! The world is your oyster. + +2. **No Extra Dependencies**: Fetch API comes built-in with modern browsers. It's like discovering you already have a fully stocked pantry! + +3. **Learning Experience**: Using Fetch API gives you a deeper understanding of how GraphQL works under the hood. It's like learning to cook instead of just ordering takeout. + +4. **Lightweight**: Since you're not adding any extra libraries, your bundle size stays lean and mean. + +So there you have it, folks! The Fetch API approach - for when you want to roll up your sleeves and get intimate with your GraphQL requests. It's perfect for those who love control and aren't afraid of a little elbow grease. + +But wait, is this the end of our GraphQL journey? Not by a long shot! πŸš€ We've seen the heavyweight, the lightweight, and now the DIY approach. What other flavors of GraphQL goodness await us in the Vue universe? + +Stay tuned as we continue our expedition through the land of data fetching. Up next, we'll be exploring yet another approach. Will it be the secret ingredient your Vue app has been missing? Let's find out! πŸ•΅οΈβ€β™€οΈ + +## Approach 4: Axios - The Smooth Operator + +Ladies and gentlemen, put your hands together for Axios! 🎭 If Fetch API is like cooking from scratch, Axios is like having a sous chef who takes care of all the little details. It's time to add some finesse to our GraphQL requests! + +### 1. Installation and Integration Steps + +First things first, let's invite Axios to our Vue party: + +```bash +npm install axios +``` + +That's it! Axios is like that friend who's always ready to go - no complicated setup required. + +### 2. Code Snippets + +Now, let's see Axios strut its stuff: + +```typescript + + + +``` + +Look at that smooth operator! 😎 Axios makes our GraphQL requests look effortless. It's like watching a professional chef at work - everything just flows. + +### 3. Error Handling + +Axios comes with some nifty error handling capabilities out of the box. It's like having a safety net for your data fetching acrobatics: + +```typescript +try { + // ... axios request ... +} catch (err: any) { + if (err.response) { + networkError.value = `HTTP error! status: ${err.response.status}` + } else { + unexpectedError.value = err.message + } +} finally { + loading.value = false +} +``` + +This error handling is like having a personal assistant who categorizes all your problems neatly. Network issues? Check. Unexpected errors? Double-check. Axios has got you covered! + +### 4. Why Axios Rocks + +1. **Automatic Transforms**: Axios automatically transforms your response data. It's like having a translator who speaks both JSON and JavaScript fluently! + +2. **Request and Response Interceptors**: Need to add an auth token to every request? Or maybe log all responses? Axios interceptors have got your back. It's like having a bouncer who checks every guest at your data party. + +3. **Browser and Node.js Support**: Whether you're in the browser or on a server, Axios works the same way. It's the chameleon of HTTP clients! + +4. **Cancellation Support**: Changed your mind about that request? No problem! Axios lets you cancel requests on the fly. It's like having an "undo" button for your API calls. + +So there you have it, folks! Axios - the smooth operator of the HTTP request world. It's perfect for those who want a balance between control and convenience, with a dash of extra features thrown in for good measure. + +But hold onto your hats, because our GraphQL journey isn't over yet! 🎩 We've seen the heavyweight, the lightweight, the DIY approach, and now the smooth operator. What other GraphQL wonders await us in the Vue universe? + +Stay tuned as we wrap up our expedition through the land of data fetching. We've got one more approach up our sleeve, and it might just be the cherry on top of your GraphQL sundae! Will it be the perfect finale to our data-fetching symphony? Let's find out! 🎡 + +## Approach 5: Villus - The Vue-Native Virtuoso + +Ladies and gentlemen, for our grand finale, let me introduce you to Villus! 🎭 If our GraphQL journey was a concert, Villus would be the show-stopping final act. It's the Vue-native GraphQL client that's about to make your data fetching sing! + +### 1. Installation and Integration Steps + +Let's roll out the red carpet for Villus: + +```bash +npm install villus graphql +``` + +Now, let's set the stage. In your `main.js` file: + +```typescript +import {createApp} from "vue" +import {createClient as villusClient, fetch} from "villus" + +const villus_client = villusClient({ + url: "/graphql", + use: [fetch()], +}) + +const app = createApp(App) + +app.use(villus_client) +``` + +### 2. Code Snippets + +Now, let's watch Villus perform its magic: + +```typescript + + + +``` + +Look at that performance! πŸŽ‰ Villus brings together the best of both worlds - the simplicity of Vue with the power of GraphQL. It's like watching a virtuoso play their instrument. + +### 3. Error Handling + +Villus doesn't just perform, it gracefully handles mishaps too: + +```typescript +try { + const result = await query.execute() + if (result.error) { + throw result.error + } + // ... handle successful result ... +} catch (e: any) { + if (e.message.startsWith("Network Error")) { + networkError.value = e.message + } else if (e.graphQLErrors) { + graphqlError.value = e.graphQLErrors + .map((err: any) => err.message) + .join(", ") + } else { + unexpectedError.value = e.message + } +} +``` + +This error handling is like having a stage manager who can handle any unexpected event. Network issues? GraphQL errors? Unexpected problems? Villus has got it all covered! + +### 4. Why Villus Rocks + +1. **Vue-Native**: Villus is built specifically for Vue. It's like having a custom-tailored suit for your Vue app - it just fits perfectly! + +2. **Lightweight**: Villus keeps things lean and mean. It's the gymnast of GraphQL clients - flexible and lightweight. + +3. **Composable**: With its composition API support, Villus plays beautifully with Vue 3. It's like adding a harmony to your Vue melody. + +4. **Smart Defaults**: Villus comes with smart defaults that just work, but it's also highly customizable. It's like having an instrument that's ready to play out of the box, but can be tuned to your exact preferences. + +And there you have it, folks! Villus - the Vue-native virtuoso that brings your GraphQL queries to life with style and grace. + +## Comparison Table + +| Feature | Apollo Client | URQL | Fetch API | Axios | Villus | +| ---------------------------------- | ------------------------------------------------- | ------------------------- | ------------------ | --------------------------------------------------- | ------------------------- | +| Bundle Size (Minified + Gzipped)\* | 47.8 kB | 10.2 kB | 2.8kB | 13.2kB | 4.6kB | +| Learning Curve | Steep | Moderate | Low | Low | Moderate | +| Caching Capabilities | Advanced | Good | Manual | Manual | Good | +| Community Support | Extensive | Growing | Widespread | Extensive | Limited | +| Additional Features | Rich ecosystem, dev tools, local state management | Lightweight, customizable | Native browser API | Request/response interceptors, automatic transforms | Vue-specific, lightweight | + +\*Bundle sizes culled from bundlephobia.com + +Here's a brief explanation of the ratings: + +1. Learning Curve: + + - Apollo Client: Steep due to its extensive features and concepts. + - URQL: Moderate as it's simpler than Apollo but still has GraphQL-specific concepts. + - Fetch API: Low as it's a basic browser API. + - Axios: Low as it's straightforward to use for HTTP requests. + - Villus: Moderate as it's Vue-specific but simpler than Apollo. + +2. Caching Capabilities: + + - Apollo Client: Advanced with sophisticated normalization and cache policies. + - URQL: Good built-in caching with customizable options. + - Fetch API: Manual caching required. + - Axios: Manual caching required. + - Villus: Good basic caching capabilities. + +3. Community Support: + + - Apollo Client: Extensive due to its popularity in the GraphQL ecosystem. + - URQL: Growing community, but not as large as Apollo's. + - Fetch API: Widespread as it's a web standard. + - Axios: Extensive due to its popularity for HTTP requests. + - Villus: Limited as it's a newer and more niche library. + +4. Additional Features: + - Apollo Client: Rich ecosystem with developer tools and local state management. + - URQL: Lightweight and highly customizable. + - Fetch API: Native browser API, no extra features. + - Axios: Request/response interceptors, automatic transforms for data. + - Villus: Vue-specific integration, lightweight alternative to Apollo. + +This table provides a high-level comparison of the different approaches for GraphQL data fetching in Vue. Each approach has its strengths and may be more suitable depending on the specific requirements of a project. + +### Caching Capabilities + +1. Apollo Client: + + - Offers a sophisticated normalized cache + - Supports various cache policies (cache-first, network-only, etc.) + - Allows for fine-grained cache updates and invalidation + - Provides optimistic UI updates + +2. URQL: + + - Implements a document cache by default + - Supports customizable caching strategies + - Offers a normalized cache through the Normalized Cache exchange + - Provides easy cache updates and invalidation + +3. Fetch API: + + - No built-in caching mechanism + - Requires manual implementation of caching logic + - Can leverage browser's HTTP cache or custom in-memory/storage solutions + +4. Axios: + + - No built-in caching mechanism for GraphQL + - Requires manual implementation of caching logic + - Can be combined with external caching libraries + +5. Villus: + - Provides a simple document cache + - Supports cache policies similar to Apollo (cache-first, network-only) + - Offers manual cache manipulation methods + - Lighter weight caching compared to Apollo + +## Common Issues and Resolutions + +1. Apollo Client: + + - Issue: Over-fetching data + Resolution: Use fragments and optimized queries + - Issue: Cache inconsistencies + Resolution: Manually update cache or use refetchQueries + - Issue: Performance with large datasets + Resolution: Implement pagination or infinite scrolling + +2. URQL: + + - Issue: Lack of advanced caching features out-of-the-box + Resolution: Use additional exchanges like the Normalized Cache exchange + - Issue: Limited dev tools compared to Apollo + Resolution: Rely on browser network tab or implement custom logging + - Issue: Learning curve for exchanges concept + Resolution: Start with basic setup and gradually add exchanges as needed + +3. Fetch API: + + - Issue: Verbose syntax for GraphQL requests + Resolution: Create utility functions to simplify request creation + - Issue: No built-in error handling for GraphQL errors + Resolution: Implement custom error checking and handling logic + - Issue: Manual caching and state management + Resolution: Use state management libraries like Vuex or Pinia alongside Fetch + +4. Axios: + + - Issue: Not GraphQL-specific, requiring more boilerplate + Resolution: Create custom wrapper functions for GraphQL operations + - Issue: Handling GraphQL errors separately from HTTP errors + Resolution: Implement middleware to check for and handle GraphQL-specific errors + - Issue: No built-in caching for GraphQL queries + Resolution: Implement custom caching layer or use with a state management solution + +5. Villus: + - Issue: Limited ecosystem compared to Apollo + Resolution: Combine with other Vue libraries for missing features + - Issue: Less community resources and examples + Resolution: Refer to official documentation and reach out to maintainers for support + - Issue: Potential performance issues with larger applications + Resolution: Consider using more robust solutions like Apollo for very complex apps + +Each approach has its own set of challenges, but also offers unique advantages. The choice between them often depends on the specific requirements of your project, the complexity of your GraphQL operations, and your team's familiarity with the tools. + +## The Grand Finale + +We've journeyed through the land of GraphQL in Vue, exploring five fantastic approaches: + +1. Apollo Client: The Swiss Army knife +2. URQL: The lightweight contender +3. Fetch API: The DIY dynamo +4. Axios: The smooth operator +5. Villus: The Vue-native virtuoso + +Each approach has its own strengths, like instruments in an orchestra. The choice depends on your project's needs, your team's expertise, and the symphony you want to create. + +Remember, in the world of web development, there's no one-size-fits-all solution. It's about finding the right tool for your unique masterpiece. So go forth, experiment, and may your Vue apps be forever data-rich and performant! + +And with that, we bring down the curtain on our GraphQL in Vue extravaganza. But don't worry, the show never really ends in the ever-evolving world of web development. Keep learning, keep coding, and most importantly, keep having fun! πŸŽ­πŸš€ diff --git a/graphql/sidebar.ts b/graphql/sidebar.ts index a9e8e752ff..f2dfb21851 100644 --- a/graphql/sidebar.ts +++ b/graphql/sidebar.ts @@ -5,7 +5,14 @@ const sidebars: SidebarsConfig = { { type: "category", label: "Guides", - items: ["graphql", "graphql-vs-rest", "graphql-react-client", "cto-guide", "problem-statement"], + items: [ + "graphql", + "graphql-vs-rest", + "graphql-react-client", + "cto-guide", + "problem-statement", + "graphql-vue-clients", + ], }, { type: "category", From d32e0a9740a71f0e2dd1072d7a23bd7e0ea44903 Mon Sep 17 00:00:00 2001 From: David Anyatonwu Date: Sat, 20 Jul 2024 22:00:08 +0100 Subject: [PATCH 2/5] fix: move to blog add author info and cover image --- .../graphql-vue-clients-2024-07-20.md | 11 ++++++++++- graphql/sidebar.ts | 9 +-------- static/images/blog/vue-with-graphql.png | Bin 0 -> 37460 bytes 3 files changed, 11 insertions(+), 9 deletions(-) rename graphql/graphql-vue-clients.md => blog/graphql-vue-clients-2024-07-20.md (98%) create mode 100644 static/images/blog/vue-with-graphql.png diff --git a/graphql/graphql-vue-clients.md b/blog/graphql-vue-clients-2024-07-20.md similarity index 98% rename from graphql/graphql-vue-clients.md rename to blog/graphql-vue-clients-2024-07-20.md index 78e0d5e159..3e424570ee 100644 --- a/graphql/graphql-vue-clients.md +++ b/blog/graphql-vue-clients-2024-07-20.md @@ -1,9 +1,18 @@ --- +authors: + - name: David Onyedikachi + title: NodeJs-Golang Backend Developer, with experience in Python, Rust, and Solidity + url: https://github.com/onyedikachi-david + image_url: https://avatars.githubusercontent.com/u/51977119?v=4 +tags: [GraphQL, Vue, Apollo client] +hide_table_of_contents: true title: "GraphQL in Vue: 5 Best Approaches for Data Fetching" description: "Explore Apollo Vue, Villus, and other methods for efficient GraphQL integration in Vue applications, with detailed comparisons and error handling strategies." -sidebar_label: "GraphQL with Vue" +sidebar_label: "GraphQL in Vue" slug: graphql-vue-client +image: /image/blog/vue-with-graphql.png --- +![Cover Image for Vue in GraphQL](../static/images/blog/vue-with-graphql.png) ## Introduction diff --git a/graphql/sidebar.ts b/graphql/sidebar.ts index f2dfb21851..a9e8e752ff 100644 --- a/graphql/sidebar.ts +++ b/graphql/sidebar.ts @@ -5,14 +5,7 @@ const sidebars: SidebarsConfig = { { type: "category", label: "Guides", - items: [ - "graphql", - "graphql-vs-rest", - "graphql-react-client", - "cto-guide", - "problem-statement", - "graphql-vue-clients", - ], + items: ["graphql", "graphql-vs-rest", "graphql-react-client", "cto-guide", "problem-statement"], }, { type: "category", diff --git a/static/images/blog/vue-with-graphql.png b/static/images/blog/vue-with-graphql.png new file mode 100644 index 0000000000000000000000000000000000000000..ebbe321957ada8eb90943c34e7e640e67c533d29 GIT binary patch literal 37460 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

)bMikjr1C`SO8{q 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 literal 0 HcmV?d00001 From 41a603d4c06084a1f3bbfa94d09b9efcc70cfc02 Mon Sep 17 00:00:00 2001 From: David Anyatonwu Date: Sat, 20 Jul 2024 22:05:21 +0100 Subject: [PATCH 3/5] fix: prettier --- blog/graphql-vue-clients-2024-07-20.md | 1 + 1 file changed, 1 insertion(+) diff --git a/blog/graphql-vue-clients-2024-07-20.md b/blog/graphql-vue-clients-2024-07-20.md index 3e424570ee..5f404a1bff 100644 --- a/blog/graphql-vue-clients-2024-07-20.md +++ b/blog/graphql-vue-clients-2024-07-20.md @@ -12,6 +12,7 @@ sidebar_label: "GraphQL in Vue" slug: graphql-vue-client image: /image/blog/vue-with-graphql.png --- + ![Cover Image for Vue in GraphQL](../static/images/blog/vue-with-graphql.png) ## Introduction From 581183a54a64114403675603361b3443b05726ad Mon Sep 17 00:00:00 2001 From: David Anyatonwu Date: Wed, 31 Jul 2024 15:02:07 +0100 Subject: [PATCH 4/5] chore: revamped the tutorial --- blog/graphql-vue-clients-2024-07-20.md | 918 --------------- blog/graphql-vue-clients-2024-07-31.md | 1429 ++++++++++++++++++++++++ 2 files changed, 1429 insertions(+), 918 deletions(-) delete mode 100644 blog/graphql-vue-clients-2024-07-20.md create mode 100644 blog/graphql-vue-clients-2024-07-31.md diff --git a/blog/graphql-vue-clients-2024-07-20.md b/blog/graphql-vue-clients-2024-07-20.md deleted file mode 100644 index 5f404a1bff..0000000000 --- a/blog/graphql-vue-clients-2024-07-20.md +++ /dev/null @@ -1,918 +0,0 @@ ---- -authors: - - name: David Onyedikachi - title: NodeJs-Golang Backend Developer, with experience in Python, Rust, and Solidity - url: https://github.com/onyedikachi-david - image_url: https://avatars.githubusercontent.com/u/51977119?v=4 -tags: [GraphQL, Vue, Apollo client] -hide_table_of_contents: true -title: "GraphQL in Vue: 5 Best Approaches for Data Fetching" -description: "Explore Apollo Vue, Villus, and other methods for efficient GraphQL integration in Vue applications, with detailed comparisons and error handling strategies." -sidebar_label: "GraphQL in Vue" -slug: graphql-vue-client -image: /image/blog/vue-with-graphql.png ---- - -![Cover Image for Vue in GraphQL](../static/images/blog/vue-with-graphql.png) - -## Introduction - -### GraphQL in Vue: 5 Best Approaches for Data Fetching - -Hey there, Vue enthusiasts! πŸ‘‹ Are you ready to supercharge your data fetching game? Buckle up, because we're about to embark on an exhilarating journey through the world of GraphQL in Vue! - -You know that feeling when you're trying to fetch data for your Vue app, and it feels like you're wrestling with an octopus? πŸ™ Well, fear not! GraphQL is here to turn that octopus into a well-behaved pet that fetches exactly what you need, when you need it. - -In this guide, we'll explore five fantastic approaches to integrating GraphQL with Vue. It's like we're about to open a treasure chest of data fetching goodies, and trust me, you'll want to get your hands on these gems! πŸ’Ž - -So, whether you're a GraphQL newbie or a seasoned pro, there's something here for everyone. We'll dive deep into each method, compare them side by side, and even tackle the thorny issue of error handling. By the end of this article, you'll be slinging GraphQL queries like a data-fetching superhero! πŸ¦Έβ€β™€οΈ - -Ready to level up your Vue app? Let's dive in! - -### πŸ› οΈ Project Setup - -Let's start by setting up our Vue project with Vite, which provides a faster and leaner development experience: - -```bash -npm create vite@latest vue-graphql-tailcall-showcase -- --template vue-ts -cd vue-graphql-tailcall-showcase -npm install -``` - -This creates a new Vue 3 project with TypeScript support. Now, let's install the necessary dependencies for our GraphQL experiments: - -```bash -npm install @apollo/client @vue/apollo-composable graphql -npm install @urql/vue -npm install axios -npm install villus -``` - -These installations will allow us to explore different GraphQL client options in our Vue application. - -### πŸ”§ Tailcall Backend Configuration - -Now, let's set up our Tailcall backend that will wrap the JSONPlaceholder API, providing a GraphQL interface to RESTful data. - -First, create a `tailcall` directory in the project root: - -```bash -mkdir tailcall -``` - -Then, create a `jsonplaceholder.graphql` file in this directory: - -```graphql -# File: tailcall/jsonplaceholder.graphql - -schema - @server(port: 8000, hostname: "0.0.0.0") - @upstream( - baseURL: "http://jsonplaceholder.typicode.com" - httpCache: 42 - ) { - query: Query -} - -type Query { - posts: [Post] @http(path: "/posts") - user(id: Int!): User @http(path: "/users/{{.args.id}}") -} - -type User { - id: Int! - name: String! - username: String! - email: String! - phone: String - website: String -} - -type Post { - id: Int! - userId: Int! - title: String! - body: String! - user: User @http(path: "/users/{{.value.userId}}") -} -``` - -This GraphQL schema defines our API structure, mapping RESTful endpoints to GraphQL types and queries. - -To start the Tailcall server, you'll need to have Tailcall installed. If you haven't installed it yet, follow the installation instructions from the Tailcall documentation. Once installed, you can start the server with: - -```sh -tailcall start ./tailcall/jsonplaceholder.graphql -``` - -This command starts a GraphQL server on `http://localhost:8000`, which will act as a bridge between our Vue application and the JSONPlaceholder API. - -With this setup, we're ready to dive into the exciting world of GraphQL in Vue! πŸš€ Our Tailcall backend provides a perfect playground for exploring different GraphQL client approaches, allowing us to fetch posts and user data with the flexibility and power of GraphQL queries. In the following sections, we'll explore how to leverage this backend with various GraphQL clients in our Vue application. Get ready for some data-fetching magic! ✨ - -Alright, let's dive into our first approach: Apollo Client! πŸš€ - -## Approach 1: Apollo Client - The Swiss Army Knife of GraphQL - -Picture this: You're a data-fetching chef, and Apollo Client is your top-of-the-line kitchen knife set. It's sharp, versatile, and makes slicing through complex queries feel like cutting through butter. Let's see how we can whip up a delicious Vue dish with Apollo Client! - -### 1. Installation and Integration Steps - -First things first, let's get our ingredients ready. You'll need to install the following packages: - -```bash -npm install @apollo/client @vue/apollo-composable graphql -``` - -Now, let's set the table. In your `main.js` file, you'll need to create an Apollo Client instance and provide it to your Vue app. It's like setting up your kitchen before you start cooking! - -```javascript -import {createApp, provide, h} from "vue" -import { - ApolloClient, - InMemoryCache, -} from "@apollo/client/core" -import {DefaultApolloClient} from "@vue/apollo-composable" - -const apolloClient = new ApolloClient({ - uri: "YOUR_GRAPHQL_ENDPOINT", - cache: new InMemoryCache(), -}) - -const app = createApp({ - setup() { - provide(DefaultApolloClient, apolloClient) - }, - render: () => h(App), -}) -``` - -### 2. Code Snippets - -Now, let's get cooking! Here's how you can use Apollo Client in your Vue component: - -```typescript - - - -``` - -Isn't that neat? 😎 With Apollo Client, fetching data is as easy as pie. The `useQuery` composable does all the heavy lifting for you, serving up your data on a silver platter. - -### 3. Error Handling - -But wait, what if something goes wrong in our kitchen? Don't worry, Apollo Client has got your back with some top-notch error handling: - -```typescript -const networkError = (ref < string) | (null > null) -const graphqlError = (ref < string) | (null > null) -const unexpectedError = (ref < string) | (null > null) - -watch(error, (newError) => { - if (newError) { - if (newError.networkError) { - networkError.value = - "Network error: " + newError.networkError.message - } else if ( - newError.graphQLErrors && - newError.graphQLErrors.length > 0 - ) { - graphqlError.value = - "GraphQL error: " + - newError.graphQLErrors - .map((e) => e.message) - .join(", ") - } else { - unexpectedError.value = - "Unexpected error: " + newError.message - } - } else { - networkError.value = null - graphqlError.value = null - unexpectedError.value = null - } -}) -``` - -This error handling is like having a sous chef who catches any mishaps before they ruin your dish. Network errors, GraphQL errors, or unexpected issues - all neatly categorized and ready to be displayed to the user. - -### 4. Why Apollo Client Rocks - -1. **Powerful Caching**: Apollo Client comes with a built-in caching system that's smarter than your average bear. It automatically caches your query results, making subsequent requests lightning fast. - -2. **Real-time Updates**: With Apollo Client, your app can feel alive! It supports real-time updates out of the box, perfect for those dynamic, data-driven applications. - -3. **Optimistic UI**: Want to make your UI feel snappy? Apollo Client's optimistic UI features let you update the UI before the server responds. It's like time travel for your data! - -4. **Developer Tools**: The Apollo DevTools extension for Chrome is like having x-ray vision for your GraphQL queries. Debug, inspect cache, and watch your queries in real-time! - -So there you have it, folks! Apollo Client - the superhero of GraphQL clients. It's powerful, flexible, and comes with more features than you can shake a stick at. But is it the perfect fit for every scenario? Stay tuned as we explore more approaches and find out! - -Next up, we'll be looking at another contender in the GraphQL arena. Will it give Apollo a run for its money? Let's find out! πŸƒβ€β™‚οΈπŸ’¨ - -## Approach 2: URQL - The Lightweight Contender - -Ladies and gentlemen, put your hands together for URQL! πŸ‘ If Apollo Client is the heavyweight champion of GraphQL clients, URQL is the nimble featherweight that packs a surprising punch. Let's dive into this lean, mean, data-fetching machine! - -### 1. Installation and Integration Steps - -First things first, let's get URQL into our Vue ring. It's as easy as: - -```bash -npm install @urql/vue graphql -``` - -Now, let's set up our URQL client. It's like preparing a lightweight but powerful sports car for a race: - -```javascript -import {createApp} from "vue" -import urql, {createClient} from "@urql/vue" - -const client = createClient({ - url: "YOUR_GRAPHQL_ENDPOINT", -}) - -const app = createApp(App) -app.use(urql, client) -``` - -### 2. Code Snippets - -Alright, let's see URQL in action! Here's how you can use it in your Vue component: - -```typescript - - - -``` - -Wow, look at that sleek code! 😍 URQL keeps things simple and straightforward. The `useQuery` composable gives you everything you need to fetch data and handle the query state. - -### 3. Error Handling - -But what if our lightweight contender stumbles? No worries, URQL's got some nifty error handling moves: - -```typescript -const networkError = (ref < string) | (null > null) -const graphqlError = (ref < string) | (null > null) -const unexpectedError = (ref < string) | (null > null) - -watch(error, (newError) => { - if (newError) { - if (newError.networkError) { - networkError.value = - "Network error: " + newError.networkError.message - } else if ( - newError.graphQLErrors && - newError.graphQLErrors.length > 0 - ) { - graphqlError.value = - "GraphQL error: " + - newError.graphQLErrors - .map((e) => e.message) - .join(", ") - } else { - unexpectedError.value = - "Unexpected error: " + newError.message - } - } else { - networkError.value = null - graphqlError.value = null - unexpectedError.value = null - } -}) -``` - -This error handling is like having a skilled cornerman in your boxing match. It catches and categorizes errors, ensuring you're never caught off guard. - -### 4. Why URQL Rocks - -1. **Lightweight Champion**: URQL is like the minimalist's dream GraphQL client. It's small, fast, and doesn't come with unnecessary baggage. - -2. **Extensibility**: Don't let its size fool you! URQL is highly extensible. Need more features? Just add some exchanges (URQL's middleware system) and you're good to go! - -3. **Easy to Understand**: URQL's simplicity makes it a breeze to learn and use. It's like the "easy to pick up, hard to master" of GraphQL clients. - -4. **Built-in Cache**: While not as sophisticated as Apollo's, URQL comes with a built-in normalized cache that gets the job done for most use cases. - -So, there you have it! URQL - the lightweight contender that proves sometimes less is more. It's perfect for those who want a no-frills, straightforward GraphQL experience. - -But wait, we're not done yet! 🎭 We've seen the heavyweight and the lightweight, but what other flavors of GraphQL goodness await us? Stay tuned as we continue our journey through the GraphQL landscape in Vue! - -Up next, we'll be exploring yet another approach. Will it be the Goldilocks of GraphQL clients - just right? Let's find out! πŸ•΅οΈβ€β™€οΈ - -## Approach 3: Fetch API - The DIY Dynamo - -Alright, Vue enthusiasts! πŸ› οΈ It's time to roll up our sleeves and get our hands dirty with the Fetch API. If Apollo and URQL are like ordering a gourmet meal, using Fetch API is like cooking that meal yourself from scratch. It's time to channel your inner GraphQL chef! - -### 1. Installation and Integration Steps - -Here's the beauty of the Fetch API - it comes built-in with modern browsers! No need to install any extra packages. It's like finding out your kitchen already has all the tools you need. How's that for convenience? - -### 2. Code Snippets - -Let's dive into our DIY GraphQL solution: - -```typescript - - - -``` - -Look at that! We're crafting our GraphQL requests by hand. It's like being a data-fetching artisan. 🎨 - -### 3. Error Handling - -When you're cooking up your own GraphQL solution, you need to be prepared for things to get a little messy. But don't worry, we've got a robust error handling system: - -```javascript -try { - // ... fetch logic ... -} catch (err: any) { - if (err.message.startsWith('HTTP error!')) { - networkError.value = err.message - } else { - unexpectedError.value = err.message - } -} finally { - loading.value = false -} -``` - -This error handling is like having a fire extinguisher in your kitchen. It's there to catch and categorize any mishaps, ensuring your app doesn't go up in flames! - -### 4. Why Fetch API Rocks - -1. **Ultimate Control**: With Fetch API, you're the master of your own destiny. Want to customize how requests are sent? Go for it! The world is your oyster. - -2. **No Extra Dependencies**: Fetch API comes built-in with modern browsers. It's like discovering you already have a fully stocked pantry! - -3. **Learning Experience**: Using Fetch API gives you a deeper understanding of how GraphQL works under the hood. It's like learning to cook instead of just ordering takeout. - -4. **Lightweight**: Since you're not adding any extra libraries, your bundle size stays lean and mean. - -So there you have it, folks! The Fetch API approach - for when you want to roll up your sleeves and get intimate with your GraphQL requests. It's perfect for those who love control and aren't afraid of a little elbow grease. - -But wait, is this the end of our GraphQL journey? Not by a long shot! πŸš€ We've seen the heavyweight, the lightweight, and now the DIY approach. What other flavors of GraphQL goodness await us in the Vue universe? - -Stay tuned as we continue our expedition through the land of data fetching. Up next, we'll be exploring yet another approach. Will it be the secret ingredient your Vue app has been missing? Let's find out! πŸ•΅οΈβ€β™€οΈ - -## Approach 4: Axios - The Smooth Operator - -Ladies and gentlemen, put your hands together for Axios! 🎭 If Fetch API is like cooking from scratch, Axios is like having a sous chef who takes care of all the little details. It's time to add some finesse to our GraphQL requests! - -### 1. Installation and Integration Steps - -First things first, let's invite Axios to our Vue party: - -```bash -npm install axios -``` - -That's it! Axios is like that friend who's always ready to go - no complicated setup required. - -### 2. Code Snippets - -Now, let's see Axios strut its stuff: - -```typescript - - - -``` - -Look at that smooth operator! 😎 Axios makes our GraphQL requests look effortless. It's like watching a professional chef at work - everything just flows. - -### 3. Error Handling - -Axios comes with some nifty error handling capabilities out of the box. It's like having a safety net for your data fetching acrobatics: - -```typescript -try { - // ... axios request ... -} catch (err: any) { - if (err.response) { - networkError.value = `HTTP error! status: ${err.response.status}` - } else { - unexpectedError.value = err.message - } -} finally { - loading.value = false -} -``` - -This error handling is like having a personal assistant who categorizes all your problems neatly. Network issues? Check. Unexpected errors? Double-check. Axios has got you covered! - -### 4. Why Axios Rocks - -1. **Automatic Transforms**: Axios automatically transforms your response data. It's like having a translator who speaks both JSON and JavaScript fluently! - -2. **Request and Response Interceptors**: Need to add an auth token to every request? Or maybe log all responses? Axios interceptors have got your back. It's like having a bouncer who checks every guest at your data party. - -3. **Browser and Node.js Support**: Whether you're in the browser or on a server, Axios works the same way. It's the chameleon of HTTP clients! - -4. **Cancellation Support**: Changed your mind about that request? No problem! Axios lets you cancel requests on the fly. It's like having an "undo" button for your API calls. - -So there you have it, folks! Axios - the smooth operator of the HTTP request world. It's perfect for those who want a balance between control and convenience, with a dash of extra features thrown in for good measure. - -But hold onto your hats, because our GraphQL journey isn't over yet! 🎩 We've seen the heavyweight, the lightweight, the DIY approach, and now the smooth operator. What other GraphQL wonders await us in the Vue universe? - -Stay tuned as we wrap up our expedition through the land of data fetching. We've got one more approach up our sleeve, and it might just be the cherry on top of your GraphQL sundae! Will it be the perfect finale to our data-fetching symphony? Let's find out! 🎡 - -## Approach 5: Villus - The Vue-Native Virtuoso - -Ladies and gentlemen, for our grand finale, let me introduce you to Villus! 🎭 If our GraphQL journey was a concert, Villus would be the show-stopping final act. It's the Vue-native GraphQL client that's about to make your data fetching sing! - -### 1. Installation and Integration Steps - -Let's roll out the red carpet for Villus: - -```bash -npm install villus graphql -``` - -Now, let's set the stage. In your `main.js` file: - -```typescript -import {createApp} from "vue" -import {createClient as villusClient, fetch} from "villus" - -const villus_client = villusClient({ - url: "/graphql", - use: [fetch()], -}) - -const app = createApp(App) - -app.use(villus_client) -``` - -### 2. Code Snippets - -Now, let's watch Villus perform its magic: - -```typescript - - - -``` - -Look at that performance! πŸŽ‰ Villus brings together the best of both worlds - the simplicity of Vue with the power of GraphQL. It's like watching a virtuoso play their instrument. - -### 3. Error Handling - -Villus doesn't just perform, it gracefully handles mishaps too: - -```typescript -try { - const result = await query.execute() - if (result.error) { - throw result.error - } - // ... handle successful result ... -} catch (e: any) { - if (e.message.startsWith("Network Error")) { - networkError.value = e.message - } else if (e.graphQLErrors) { - graphqlError.value = e.graphQLErrors - .map((err: any) => err.message) - .join(", ") - } else { - unexpectedError.value = e.message - } -} -``` - -This error handling is like having a stage manager who can handle any unexpected event. Network issues? GraphQL errors? Unexpected problems? Villus has got it all covered! - -### 4. Why Villus Rocks - -1. **Vue-Native**: Villus is built specifically for Vue. It's like having a custom-tailored suit for your Vue app - it just fits perfectly! - -2. **Lightweight**: Villus keeps things lean and mean. It's the gymnast of GraphQL clients - flexible and lightweight. - -3. **Composable**: With its composition API support, Villus plays beautifully with Vue 3. It's like adding a harmony to your Vue melody. - -4. **Smart Defaults**: Villus comes with smart defaults that just work, but it's also highly customizable. It's like having an instrument that's ready to play out of the box, but can be tuned to your exact preferences. - -And there you have it, folks! Villus - the Vue-native virtuoso that brings your GraphQL queries to life with style and grace. - -## Comparison Table - -| Feature | Apollo Client | URQL | Fetch API | Axios | Villus | -| ---------------------------------- | ------------------------------------------------- | ------------------------- | ------------------ | --------------------------------------------------- | ------------------------- | -| Bundle Size (Minified + Gzipped)\* | 47.8 kB | 10.2 kB | 2.8kB | 13.2kB | 4.6kB | -| Learning Curve | Steep | Moderate | Low | Low | Moderate | -| Caching Capabilities | Advanced | Good | Manual | Manual | Good | -| Community Support | Extensive | Growing | Widespread | Extensive | Limited | -| Additional Features | Rich ecosystem, dev tools, local state management | Lightweight, customizable | Native browser API | Request/response interceptors, automatic transforms | Vue-specific, lightweight | - -\*Bundle sizes culled from bundlephobia.com - -Here's a brief explanation of the ratings: - -1. Learning Curve: - - - Apollo Client: Steep due to its extensive features and concepts. - - URQL: Moderate as it's simpler than Apollo but still has GraphQL-specific concepts. - - Fetch API: Low as it's a basic browser API. - - Axios: Low as it's straightforward to use for HTTP requests. - - Villus: Moderate as it's Vue-specific but simpler than Apollo. - -2. Caching Capabilities: - - - Apollo Client: Advanced with sophisticated normalization and cache policies. - - URQL: Good built-in caching with customizable options. - - Fetch API: Manual caching required. - - Axios: Manual caching required. - - Villus: Good basic caching capabilities. - -3. Community Support: - - - Apollo Client: Extensive due to its popularity in the GraphQL ecosystem. - - URQL: Growing community, but not as large as Apollo's. - - Fetch API: Widespread as it's a web standard. - - Axios: Extensive due to its popularity for HTTP requests. - - Villus: Limited as it's a newer and more niche library. - -4. Additional Features: - - Apollo Client: Rich ecosystem with developer tools and local state management. - - URQL: Lightweight and highly customizable. - - Fetch API: Native browser API, no extra features. - - Axios: Request/response interceptors, automatic transforms for data. - - Villus: Vue-specific integration, lightweight alternative to Apollo. - -This table provides a high-level comparison of the different approaches for GraphQL data fetching in Vue. Each approach has its strengths and may be more suitable depending on the specific requirements of a project. - -### Caching Capabilities - -1. Apollo Client: - - - Offers a sophisticated normalized cache - - Supports various cache policies (cache-first, network-only, etc.) - - Allows for fine-grained cache updates and invalidation - - Provides optimistic UI updates - -2. URQL: - - - Implements a document cache by default - - Supports customizable caching strategies - - Offers a normalized cache through the Normalized Cache exchange - - Provides easy cache updates and invalidation - -3. Fetch API: - - - No built-in caching mechanism - - Requires manual implementation of caching logic - - Can leverage browser's HTTP cache or custom in-memory/storage solutions - -4. Axios: - - - No built-in caching mechanism for GraphQL - - Requires manual implementation of caching logic - - Can be combined with external caching libraries - -5. Villus: - - Provides a simple document cache - - Supports cache policies similar to Apollo (cache-first, network-only) - - Offers manual cache manipulation methods - - Lighter weight caching compared to Apollo - -## Common Issues and Resolutions - -1. Apollo Client: - - - Issue: Over-fetching data - Resolution: Use fragments and optimized queries - - Issue: Cache inconsistencies - Resolution: Manually update cache or use refetchQueries - - Issue: Performance with large datasets - Resolution: Implement pagination or infinite scrolling - -2. URQL: - - - Issue: Lack of advanced caching features out-of-the-box - Resolution: Use additional exchanges like the Normalized Cache exchange - - Issue: Limited dev tools compared to Apollo - Resolution: Rely on browser network tab or implement custom logging - - Issue: Learning curve for exchanges concept - Resolution: Start with basic setup and gradually add exchanges as needed - -3. Fetch API: - - - Issue: Verbose syntax for GraphQL requests - Resolution: Create utility functions to simplify request creation - - Issue: No built-in error handling for GraphQL errors - Resolution: Implement custom error checking and handling logic - - Issue: Manual caching and state management - Resolution: Use state management libraries like Vuex or Pinia alongside Fetch - -4. Axios: - - - Issue: Not GraphQL-specific, requiring more boilerplate - Resolution: Create custom wrapper functions for GraphQL operations - - Issue: Handling GraphQL errors separately from HTTP errors - Resolution: Implement middleware to check for and handle GraphQL-specific errors - - Issue: No built-in caching for GraphQL queries - Resolution: Implement custom caching layer or use with a state management solution - -5. Villus: - - Issue: Limited ecosystem compared to Apollo - Resolution: Combine with other Vue libraries for missing features - - Issue: Less community resources and examples - Resolution: Refer to official documentation and reach out to maintainers for support - - Issue: Potential performance issues with larger applications - Resolution: Consider using more robust solutions like Apollo for very complex apps - -Each approach has its own set of challenges, but also offers unique advantages. The choice between them often depends on the specific requirements of your project, the complexity of your GraphQL operations, and your team's familiarity with the tools. - -## The Grand Finale - -We've journeyed through the land of GraphQL in Vue, exploring five fantastic approaches: - -1. Apollo Client: The Swiss Army knife -2. URQL: The lightweight contender -3. Fetch API: The DIY dynamo -4. Axios: The smooth operator -5. Villus: The Vue-native virtuoso - -Each approach has its own strengths, like instruments in an orchestra. The choice depends on your project's needs, your team's expertise, and the symphony you want to create. - -Remember, in the world of web development, there's no one-size-fits-all solution. It's about finding the right tool for your unique masterpiece. So go forth, experiment, and may your Vue apps be forever data-rich and performant! - -And with that, we bring down the curtain on our GraphQL in Vue extravaganza. But don't worry, the show never really ends in the ever-evolving world of web development. Keep learning, keep coding, and most importantly, keep having fun! πŸŽ­πŸš€ diff --git a/blog/graphql-vue-clients-2024-07-31.md b/blog/graphql-vue-clients-2024-07-31.md new file mode 100644 index 0000000000..d86c0c1fb9 --- /dev/null +++ b/blog/graphql-vue-clients-2024-07-31.md @@ -0,0 +1,1429 @@ +--- +authors: + - name: David Onyedikachi + title: NodeJs-Golang Backend Developer, with experience in Python, Rust, and Solidity + url: https://github.com/onyedikachi-david + image_url: https://avatars.githubusercontent.com/u/51977119?v=4 +tags: [GraphQL, Vue, Apollo client, URQL, Fetch API, Villus] +hide_table_of_contents: true +title: "GraphQL in Vue: 5 Best Approaches for Data Fetching" +description: "Unleash the power of GraphQL in your Vue applications! Explore the top 5 methods for seamless data fetching, including in-depth comparisons and error handling strategies." +sidebar_label: "GraphQL in Vue" +slug: graphql-vue-client +image: /image/blog/vue-with-graphql.png +--- + +![Cover Image for Vue in GraphQL](../static/images/blog/vue-with-graphql.png) + +## Introduction + +### GraphQL in Vue: 5 Best Approaches for Data Fetching + +Are you tired of wrestling with complex data fetching logic in your Vue applications? If you've ever felt like you're battling an octopus to retrieve the data you need, then GraphQL is here to be your data fetching hero! + +GraphQL empowers you to take control of your data requests in Vue.js, ensuring you receive only the specific data your application requires. This translates to cleaner code, faster performance, and a more delightful developer experience. + +In this comprehensive guide, we'll unveil the top 5 approaches to seamlessly integrate GraphQL into your Vue projects. It's like opening a treasure chest overflowing with powerful data fetching techniques! + +Whether you're a GraphQL novice or a seasoned pro, this blog post caters to all skill levels. We'll delve into each method, providing in-depth explanations, clear comparisons, and practical error handling strategies. Buckle up and prepare to transform into a data-fetching superhero with the power of GraphQL! + +Ready to elevate your Vue development experience? Let's dive in! + +### πŸ› οΈ Project Setup + +Let's start by setting up our Vue project with Vite, which provides a faster and leaner development experience: + +```bash +npm create vite@latest vue-graphql-tailcall-showcase -- --template vue-ts +cd vue-graphql-tailcall-showcase +npm install +``` + +This creates a new Vue 3 project with TypeScript support. Now, let's install the necessary dependencies for our GraphQL experiments: + +```bash +npm install @apollo/client @vue/apollo-composable graphql +npm install @urql/vue +npm install axios +npm install villus +``` + +These installations will allow us to explore different GraphQL client options in our Vue application. + +### πŸ”§ Tailcall Backend Configuration + +Now, let's set up our Tailcall backend that will wrap the JSONPlaceholder API, providing a GraphQL interface to RESTful data. + +First, create a `tailcall` directory in the project root: + +```bash +mkdir tailcall +``` + +Then, create a `jsonplaceholder.graphql` file in this directory: + +```graphql +# File: tailcall/jsonplaceholder.graphql + +schema + @server(port: 8000, hostname: "0.0.0.0") + @upstream( + baseURL: "http://jsonplaceholder.typicode.com" + httpCache: 42 + ) { + query: Query +} + +type Query { + posts: [Post] @http(path: "/posts") + user(id: Int!): User @http(path: "/users/{{.args.id}}") +} + +type User { + id: Int! + name: String! + username: String! + email: String! + phone: String + website: String +} + +type Post { + id: Int! + userId: Int! + title: String! + body: String! + user: User @http(path: "/users/{{.value.userId}}") +} +``` + +This GraphQL schema defines our API structure, mapping RESTful endpoints to GraphQL types and queries. + +To start the Tailcall server, you'll need to have Tailcall installed. If you haven't installed it yet, follow the installation instructions from the Tailcall documentation. Once installed, you can start the server with: + +```sh +tailcall start ./tailcall/jsonplaceholder.graphql +``` + +This command starts a GraphQL server on `http://localhost:8000`, which will act as a bridge between our Vue application and the JSONPlaceholder API. + +With this setup, we're ready to dive into the exciting world of GraphQL in Vue! πŸš€ Our Tailcall backend provides a perfect playground for exploring different GraphQL client approaches, allowing us to fetch posts and user data with the flexibility and power of GraphQL queries. In the following sections, we'll explore how to leverage this backend with various GraphQL clients in our Vue application. Get ready for some data-fetching magic! ✨ + +Alright, let's dive into our first approach: Apollo Client! πŸš€ + +## Approach 1: Apollo Client - The Swiss Army Knife of GraphQL + +Apollo Client stands out in the GraphQL ecosystem due to its comprehensive feature set, including intelligent caching, real-time updates, and optimistic UI rendering. For Vue developers working on data-intensive applications, Apollo Client provides a sophisticated approach to state management and data fetching. + +## 1. Setting Up Apollo Client in a Vue.js Project + +### Installation + +Begin by installing the necessary packages: + +```bash +npm install @apollo/client @vue/apollo-composable graphql +``` + +### Configuration + +Set up Apollo Client in your Vue application: + +```typescript +// src/apollo.ts +import { + ApolloClient, + InMemoryCache, + createHttpLink, +} from "@apollo/client/core" + +const httpLink = createHttpLink({ + uri: "https://your-graphql-endpoint.com/graphql", +}) + +export const apolloClient = new ApolloClient({ + link: httpLink, + cache: new InMemoryCache(), + defaultOptions: { + watchQuery: { + fetchPolicy: "cache-and-network", + }, + }, +}) + +// main.ts +import {createApp, provide, h} from "vue" +import {DefaultApolloClient} from "@vue/apollo-composable" +import App from "./App.vue" +import {apolloClient} from "./apollo" + +const app = createApp({ + setup() { + provide(DefaultApolloClient, apolloClient) + }, + render: () => h(App), +}) + +app.mount("#app") +``` + +This configuration creates an Apollo Client instance with a default in-memory cache and provides it to the entire Vue application. + +## 2. Executing Queries with Apollo Client + +Apollo Client provides the `useQuery` composable for executing GraphQL queries. Here's an example of fetching a list of posts: + +```typescript + + + +``` + +This example demonstrates: + +1. Defining a GraphQL query using `gql` tag +2. Using the `useQuery` composable to manage the query execution +3. Handling loading, error, and success states +4. Implementing a refetch mechanism for manual query execution + +## 3. Mutations and Optimistic Updates + +Apollo Client supports GraphQL mutations with optimistic updates for responsive UIs: + +```typescript + + + +``` + +This example showcases: + +1. Defining a GraphQL mutation +2. Using the `useMutation` composable +3. Implementing optimistic updates for immediate UI feedback +4. Handling form submission and mutation execution + +## 4. Advanced Apollo Client Features + +### Caching and Normalization + +Apollo Client's normalized cache is a powerful feature for efficient data management: + +```typescript +import {InMemoryCache, makeVar} from "@apollo/client/core" + +export const cache = new InMemoryCache({ + typePolicies: { + Query: { + fields: { + posts: { + merge(existing, incoming) { + return incoming + }, + }, + }, + }, + Post: { + fields: { + isLiked: { + read() { + return likedPostsVar().includes(this.id) + }, + }, + }, + }, + }, +}) + +export const likedPostsVar = makeVar([]) +``` + +This setup demonstrates: + +1. Custom merge functions for query results +2. Computed fields based on reactive variables +3. Using reactive variables for local state management + +### Error Handling and Retry Logic + +Implement robust error handling and retry logic: + +```typescript +import {ApolloLink} from "@apollo/client/core" +import {onError} from "@apollo/client/link/error" +import {RetryLink} from "@apollo/client/link/retry" + +const errorLink = onError( + ({graphQLErrors, networkError}) => { + if (graphQLErrors) + graphQLErrors.forEach(({message, locations, path}) => + console.log( + `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`, + ), + ) + if (networkError) + console.log(`[Network error]: ${networkError}`) + }, +) + +const retryLink = new RetryLink({ + delay: { + initial: 300, + max: Infinity, + jitter: true, + }, + attempts: { + max: 5, + retryIf: (error, _operation) => !!error, + }, +}) + +const link = ApolloLink.from([ + errorLink, + retryLink, + httpLink, +]) +``` + +This configuration adds comprehensive error logging and automatic retry for failed requests. + +## 5. Performance Optimization + +To optimize performance when using Apollo Client with Vue: + +1. **Implement pagination** for large datasets: + +```typescript + +``` + +2. **Use fragments** for reusable query parts: + +```typescript +import gql from "graphql-tag" + +export const POST_FRAGMENT = gql` + fragment PostDetails on Post { + id + title + body + createdAt + } +` + +export const GET_POSTS = gql` + ${POST_FRAGMENT} + query GetPosts { + posts { + ...PostDetails + } + } +` +``` + +3. **Leverage Apollo Client DevTools** for performance monitoring and cache inspection. + +## Conclusion + +Apollo Client provides a powerful and flexible solution for integrating GraphQL into Vue.js applications. Its advanced features like normalized caching, optimistic updates, and comprehensive error handling make it an excellent choice for complex, data-intensive applications. + +Key takeaways: + +- Apollo Client offers a robust caching system that optimizes data fetching and management +- The `useQuery` and `useMutation` composables provide a clean API for GraphQL operations +- Optimistic updates enable responsive UIs even before server responses +- Advanced features like custom cache policies and reactive variables offer fine-grained control over data management +- Performance optimization techniques such as pagination and fragments are crucial for scalable applications + +## Approach 2: URQL - A Lightweight GraphQL Client for Modern Web Development + +URQL stands out for its simplicity and modularity, making it an excellent choice for Vue.js projects that require GraphQL integration without the overhead of more complex libraries. Its lightweight nature contributes to faster load times and improved performance, especially in resource-constrained environments. + +### Key Features of URQL: + +- Minimal bundle size +- Built-in cache and normalized caching option +- Easy to extend with custom exchanges +- First-class TypeScript support + +## 2. Setting Up URQL in a Vue.js Project + +### Installation + +Begin by installing URQL and its Vue integration: + +```bash +npm install @urql/vue graphql +``` + +### Configuration + +Set up the URQL client in your Vue application: + +```typescript +import {createApp} from "vue" +import urql, {createClient} from "@urql/vue" +import App from "./App.vue" + +const client = createClient({ + url: "https://your-graphql-endpoint.com/graphql", +}) + +const app = createApp(App) +app.use(urql, client) +app.mount("#app") +``` + +This configuration creates an URQL client and integrates it with Vue's plugin system, making it available throughout your application. + +## 3. Executing Queries with URQL + +URQL provides a `useQuery` composable for executing GraphQL queries. Here's an example of fetching a list of posts: + +```typescript + + + +``` + +This example demonstrates how to: + +1. Define a GraphQL query +2. Use the `useQuery` composable to manage the query execution +3. Handle loading, error, and success states +4. Manually trigger the query execution + +## 4. Mutations and State Updates + +URQL also supports GraphQL mutations for modifying data. Here's an example of creating a new post: + +```typescript + + + +``` + +This example showcases: + +1. Defining a GraphQL mutation +2. Using the `useMutation` composable +3. Handling form submission and mutation execution +4. Managing loading and error states for the mutation + +## 5. Advanced URQL Features and Best Practices + +### Caching and Normalization + +URQL provides a document cache by default, but for more complex applications, you might want to use the normalized cache: + +```typescript +import { + createClient, + dedupExchange, + cacheExchange, + fetchExchange, +} from "@urql/vue" +import {normalizedCache} from "@urql/exchange-graphcache" + +const client = createClient({ + url: "https://your-graphql-endpoint.com/graphql", + exchanges: [ + dedupExchange, + normalizedCache({ + keys: { + Post: (data) => data.id, + }, + resolvers: { + Query: { + post: (_, args) => ({ + __typename: "Post", + id: args.id, + }), + }, + }, + }), + fetchExchange, + ], +}) +``` + +This setup enables more efficient caching and automatic updates for related queries when mutations occur. + +### Error Handling and Retry Logic + +Implement robust error handling and retry logic: + +```typescript +import {retry} from "@urql/exchange-retry" + +const client = createClient({ + // ... other configuration + exchanges: [ + dedupExchange, + cacheExchange, + retry({ + retryIf: (error) => + !!(error.networkError || error.graphQLErrors), + maxNumberAttempts: 3, + }), + fetchExchange, + ], +}) +``` + +This configuration adds automatic retry for network errors or GraphQL errors, improving the resilience of your application. + +## 6. Performance Optimization + +To optimize performance when using URQL with Vue: + +1. **Leverage server-side rendering (SSR)** for initial data loading: + +```typescript +import {createClient, ssrExchange} from "@urql/vue" + +const ssr = ssrExchange({ + isClient: typeof window !== "undefined", +}) + +const client = createClient({ + url: "https://your-graphql-endpoint.com/graphql", + exchanges: [ + dedupExchange, + cacheExchange, + ssr, + fetchExchange, + ], +}) +``` + +2. **Implement pagination** for large datasets: + +```typescript + +``` + +3. **Use fragments** for reusable query parts: + +```typescript +const PostFragment = ` + fragment PostDetails on Post { + id + title + body + createdAt + } +` + +const postsQuery = ` + ${PostFragment} + query GetPosts { + posts { + ...PostDetails + } + } +` +``` + +## Conclusion + +URQL provides a lightweight yet powerful solution for integrating GraphQL into Vue.js applications. Its simplicity, coupled with advanced features like normalized caching and SSR support, makes it an excellent choice for developers seeking efficiency and flexibility. By following the best practices and optimization techniques outlined in this tutorial, you can build performant, scalable Vue applications with GraphQL. + +Key takeaways: + +- URQL offers a minimal bundle size and easy integration with Vue.js +- The `useQuery` and `useMutation` composables provide a clean API for GraphQL operations +- Advanced features like normalized caching and SSR support enhance application performance +- Proper error handling and retry logic improve application resilience +- Performance optimization techniques such as pagination and fragments are crucial for scalable applications + +As you implement URQL in your Vue projects, remember to stay updated with the latest developments in both URQL and the GraphQL ecosystem to leverage new features and best practices as they emerge. + +## Approach 3: Fetch API - The DIY Dynamo + +In modern web development, effective data fetching is a cornerstone for building dynamic and responsive applications. While powerful libraries like Apollo and URQL offer extensive features for GraphQL integration, there are situations where a more hands-on approach is desirable. Enter the Fetch API: a versatile, built-in tool for making network requests, allowing developers to craft their GraphQL interactions from the ground up. This tutorial will guide you through using the Fetch API for GraphQL data fetching in Vue.js, providing a deep understanding of the process and its practical applications. + +## Step-by-Step Instructions + +### Installation and Integration Steps + +One of the key advantages of the Fetch API is its built-in availability in modern browsers. This means no additional package installations are required, simplifying the setup process. + +### Code Snippets + +Let's start by setting up a basic Vue component that uses the Fetch API to query a GraphQL endpoint. + +```typescript + + + +``` + +### Error Handling + +Handling errors effectively is crucial in any data-fetching scenario. The above code includes a robust error-handling system that categorizes errors into network errors, GraphQL errors, and unexpected errors. + +```typescript +try { + // ... fetch logic ... +} catch (err: any) { + if (err.message.startsWith("HTTP error!")) { + networkError.value = err.message + } else { + unexpectedError.value = err.message + } +} finally { + loading.value = false +} +``` + +This approach ensures that your application can gracefully handle and display errors, enhancing user experience. + +## Industry Best Practices and Potential Technical Challenges + +### Best Practices + +1. **Modular Code**: Break down your Fetch API logic into reusable functions or composables to promote code reusability and maintainability. +2. **Error Handling**: Implement comprehensive error handling to manage different types of errors (network, GraphQL, unexpected) effectively. +3. **Security**: Always validate and sanitize input data, especially when constructing GraphQL queries dynamically. + +### Technical Challenges + +1. **Verbose Error Handling**: Handling errors manually can be verbose and requires meticulous coding to cover all edge cases. +2. **Scalability**: For larger projects, the Fetch API might lack the convenience features offered by dedicated GraphQL clients, such as caching and automatic batching. +3. **State Management**: Managing loading states and errors can become complex, especially as the application grows. + +## Real-World Applications + +### Professional Development Scenarios + +1. **Custom Solutions**: In scenarios where fine-grained control over GraphQL requests is needed, such as specific headers or request configurations, the Fetch API shines. +2. **Learning and Prototyping**: Using the Fetch API is a great way to learn the basics of GraphQL and network requests, making it suitable for educational purposes and prototyping. +3. **Lightweight Applications**: For smaller applications or micro-frontends where adding a full-fledged GraphQL client is overkill, the Fetch API provides a lightweight alternative. + +## Comparison to Alternative Technologies + +### Apollo Client + +- **Pros**: Robust, feature-rich, automatic caching, extensive community support. +- **Cons**: Heavier bundle size, additional dependencies, potentially overkill for simple use cases. + +### URQL + +- **Pros**: Lightweight, flexible, built-in support for common GraphQL patterns. +- **Cons**: Less mature than Apollo, fewer built-in features. + +### Axios + +- **Pros**: Versatile HTTP client, can be used with GraphQL, additional features like request cancellation. +- **Cons**: Requires additional configuration for GraphQL, less intuitive compared to dedicated GraphQL clients. + +## Summary of Key Technical Insights + +1. **Control and Flexibility**: The Fetch API offers unmatched control over GraphQL requests, making it ideal for custom solutions. +2. **Built-In Availability**: No need for additional dependencies, simplifying the development and deployment process. +3. **Error Handling**: Robust error handling is crucial to manage different types of errors effectively. +4. **Learning Opportunity**: Using the Fetch API provides a deeper understanding of GraphQL and network requests, beneficial for both entry-level and intermediate developers. + +## Conclusion + +The Fetch API serves as a powerful tool for developers looking to craft their GraphQL solutions with precision and control. While it may not offer the convenience and features of dedicated GraphQL clients, it provides a lightweight and versatile alternative. By following best practices and understanding potential challenges, developers can effectively leverage the Fetch API for various professional development scenarios, gaining valuable insights and experience in the process. + +## Approach 4: Axios - The Smooth Operator + +In the world of HTTP clients, Axios is like a sous chef in your kitchen, handling the tedious tasks and ensuring your GraphQL requests are prepared with finesse. Unlike the Fetch API, Axios simplifies and streamlines data fetching, making it an attractive option for developers seeking efficiency without sacrificing control. Let's dive into how Axios can enhance your Vue.js application with smooth and efficient GraphQL data fetching. + +### 1. Installation and Integration Steps + +First, we need to install Axios in our Vue project. This can be done quickly via npm: + +```bash +npm install axios +``` + +That's it! Axios is now ready to use, providing a smooth and easy setup process. + +### 2. Code Snippets + +Here's how you can use Axios to fetch data from a GraphQL endpoint in a Vue component: + +```typescript + + + +``` + +Axios simplifies the process of making GraphQL requests, handling much of the boilerplate code associated with Fetch API. This makes your code cleaner and easier to maintain. + +### 3. Error Handling + +Axios provides robust error handling capabilities, making it easier to manage different types of errors: + +```typescript +try { + // ... axios request ... +} catch (err: any) { + if (err.response) { + networkError.value = `HTTP error! status: ${err.response.status}` + } else { + unexpectedError.value = err.message + } +} finally { + loading.value = false +} +``` + +This error-handling structure allows you to neatly categorize and handle various error scenarios, ensuring your application remains robust and user-friendly. + +### 4. Why Axios Rocks + +1. **Automatic Transforms**: Axios automatically transforms your response data, allowing for smoother data handling. It's like having a translator who speaks both JSON and JavaScript fluently. +2. **Request and Response Interceptors**: Need to add an auth token to every request or log all responses? Axios interceptors handle these tasks effortlessly, acting like a gatekeeper for your requests. + +3. **Browser and Node.js Support**: Axios works seamlessly in both browser and Node.js environments, providing flexibility for different project requirements. + +4. **Cancellation Support**: Axios allows you to cancel requests, providing an "undo" button for your API calls. This is particularly useful for handling stale or unnecessary requests. + +## Industry Best Practices and Potential Technical Challenges + +### Best Practices + +1. **Use Interceptors**: Leverage Axios interceptors to manage repetitive tasks like setting headers or logging requests and responses. +2. **Error Handling**: Implement comprehensive error handling to ensure your application can gracefully recover from various error conditions. +3. **Modular Code**: Organize your Axios requests into reusable functions or composables to keep your codebase clean and maintainable. + +### Technical Challenges + +1. **Bundle Size**: Although Axios is relatively lightweight, it's still an additional dependency that can increase your project's bundle size. +2. **Customization**: While Axios is highly customizable, it may require additional setup compared to more specialized GraphQL clients. + +## Real-World Applications + +### Professional Development Scenarios + +1. **API Integration**: Axios is ideal for integrating with RESTful and GraphQL APIs, providing a consistent and efficient approach for data fetching. +2. **Middleware Implementation**: Use Axios interceptors to implement middleware for logging, authentication, or other cross-cutting concerns. +3. **Server-Side Rendering (SSR)**: With its support for both browser and Node.js environments, Axios is well-suited for SSR applications, ensuring consistent data fetching across platforms. + +## Summary of Key Technical Insights + +1. **Efficiency and Convenience**: Axios offers a balance of control and convenience, making it easier to manage GraphQL requests with minimal boilerplate. +2. **Robust Error Handling**: Built-in error handling features help manage network and unexpected errors effectively. +3. **Flexibility**: With support for both browser and Node.js environments, Axios is versatile and adaptable to various project needs. +4. **Interceptors and Cancellation**: Advanced features like request/response interceptors and request cancellation provide additional control and flexibility. + +## Conclusion + +Axios stands out as a versatile and efficient tool for handling GraphQL requests in Vue.js applications. Its combination of automatic data transformation, robust error handling, and advanced features like interceptors and cancellation support make it a powerful choice for developers seeking a smooth and streamlined data-fetching experience. By incorporating best practices and understanding potential challenges, developers can leverage Axios to build robust and responsive applications, gaining valuable insights and experience in the process. + +Stay tuned as we continue our journey through the world of GraphQL data fetching in Vue.js. Our final approach will bring everything together, providing the ultimate guide to mastering GraphQL in your Vue applications. + +## Approach 5: Villus - The Vue-Native Virtuoso + +For the grand finale of our GraphQL journey, let's introduce Villus! 🎭 If our previous approaches were a warm-up, Villus is the show-stopping final act. It's a Vue-native GraphQL client that makes your data fetching seamless and elegant, tailored perfectly for Vue.js applications. + +### 1. Installation and Integration Steps + +First, let's set up Villus in your Vue project: + +```bash +npm install villus graphql +``` + +Next, configure Villus in your `main.js` file: + +```typescript +import {createApp} from "vue" +import {createClient as createVillusClient} from "villus" +import App from "./App.vue" + +const villusClient = createVillusClient({ + url: "/graphql", +}) + +const app = createApp(App) + +app.use(villusClient) + +app.mount("#app") +``` + +### 2. Code Snippets + +Here's how to use Villus to fetch data from a GraphQL endpoint in a Vue component: + +```typescript + + + +``` + +Villus integrates seamlessly with Vue, providing a smooth and elegant way to handle GraphQL queries. + +### 3. Error Handling + +Villus comes with robust error handling, making it easy to manage various error scenarios: + +```typescript +try { + const result = await query.execute() + if (result.error) { + throw result.error + } + // ... handle successful result ... +} catch (e: any) { + if (e.message.startsWith("Network Error")) { + networkError.value = e.message + } else if (e.graphQLErrors) { + graphqlError.value = e.graphQLErrors + .map((err: any) => err.message) + .join(", ") + } else { + unexpectedError.value = e.message + } +} +``` + +This error-handling structure ensures that your application can gracefully recover from various issues, providing a robust user experience. + +### 4. Why Villus Rocks + +1. **Vue-Native**: Villus is built specifically for Vue, making it a perfect fit for Vue applications. It's like having a custom-tailored suit for your Vue app. +2. **Lightweight**: Villus is lightweight and efficient, ensuring that your application remains fast and responsive. +3. **Composable**: With its composition API support, Villus integrates seamlessly with Vue 3, enhancing the development experience. +4. **Smart Defaults**: Villus comes with smart defaults that work out of the box, but it is also highly customizable to fit your specific needs. + +### Industry Best Practices and Potential Technical Challenges + +#### Best Practices + +1. **Use the Composition API**: Leveraging Vue's composition API with Villus makes your code more modular and maintainable. +2. **Error Handling**: Implement comprehensive error handling to ensure a robust application. +3. **Modular Code**: Organize your Villus queries into reusable functions or composables to keep your codebase clean. + +#### Technical Challenges + +1. **Learning Curve**: For developers new to GraphQL or the composition API, there might be a learning curve. +2. **Customization**: While Villus is highly customizable, it may require additional setup for more complex use cases. + +### Real-World Applications + +#### Professional Development Scenarios + +1. **API Integration**: Villus is perfect for integrating with GraphQL APIs in Vue applications, providing a seamless data fetching experience. +2. **State Management**: Villus can be used alongside Vue's reactive state management, providing a powerful combination for managing application state. +3. **Server-Side Rendering (SSR)**: With its support for both client-side and server-side rendering, Villus ensures consistent data fetching across platforms. + +### Summary of Key Technical Insights + +1. **Efficiency and Convenience**: Villus offers a balance of efficiency and convenience, making it easy to manage GraphQL requests in Vue applications. +2. **Robust Error Handling**: Built-in error handling features help manage network and unexpected errors effectively. +3. **Vue-Native Integration**: Villus is built specifically for Vue, providing seamless integration and enhancing the development experience. +4. **Lightweight and Composable**: Villus is lightweight and leverages the composition API, making it a powerful tool for modern Vue development. + +### Conclusion + +Villus stands out as a versatile and efficient tool for handling GraphQL requests in Vue.js applications. Its Vue-native design, robust error handling, and lightweight nature make it an excellent choice for developers seeking a seamless data-fetching experience. By incorporating best practices and understanding potential challenges, developers can leverage Villus to build robust and responsive applications, gaining valuable insights and experience in the process. + +With this, we've completed our exploration of various data-fetching approaches in Vue. Each approach offers unique strengths and is suited for different scenarios, providing you with the tools and knowledge to choose the best solution for your projects. Happy coding! πŸŽ‰ + +## Comparison Table + +| Feature | Apollo Client | URQL | Fetch API | Axios | Villus | +| ---------------------------------- | ------------------------------------------------- | ------------------------- | ------------------ | --------------------------------------------------- | ------------------------- | +| Bundle Size (Minified + Gzipped)\* | 47.8 kB | 10.2 kB | 2.8kB | 13.2kB | 4.6kB | +| Learning Curve | Steep | Moderate | Low | Low | Moderate | +| Caching Capabilities | Advanced | Good | Manual | Manual | Good | +| Community Support | Extensive | Growing | Widespread | Extensive | Limited | +| Additional Features | Rich ecosystem, dev tools, local state management | Lightweight, customizable | Native browser API | Request/response interceptors, automatic transforms | Vue-specific, lightweight | + +\*Bundle sizes culled from bundlephobia.com + +Here's a brief explanation of the ratings: + +1. Learning Curve: + + - Apollo Client: Steep due to its extensive features and concepts. + - URQL: Moderate as it's simpler than Apollo but still has GraphQL-specific concepts. + - Fetch API: Low as it's a basic browser API. + - Axios: Low as it's straightforward to use for HTTP requests. + - Villus: Moderate as it's Vue-specific but simpler than Apollo. + +2. Caching Capabilities: + + - Apollo Client: Advanced with sophisticated normalization and cache policies. + - URQL: Good built-in caching with customizable options. + - Fetch API: Manual caching required. + - Axios: Manual caching required. + - Villus: Good basic caching capabilities. + +3. Community Support: + + - Apollo Client: Extensive due to its popularity in the GraphQL ecosystem. + - URQL: Growing community, but not as large as Apollo's. + - Fetch API: Widespread as it's a web standard. + - Axios: Extensive due to its popularity for HTTP requests. + - Villus: Limited as it's a newer and more niche library. + +4. Additional Features: + - Apollo Client: Rich ecosystem with developer tools and local state management. + - URQL: Lightweight and highly customizable. + - Fetch API: Native browser API, no extra features. + - Axios: Request/response interceptors, automatic transforms for data. + - Villus: Vue-specific integration, lightweight alternative to Apollo. + +This table provides a high-level comparison of the different approaches for GraphQL data fetching in Vue. Each approach has its strengths and may be more suitable depending on the specific requirements of a project. + +### Caching Capabilities + +1. Apollo Client: + + - Offers a sophisticated normalized cache + - Supports various cache policies (cache-first, network-only, etc.) + - Allows for fine-grained cache updates and invalidation + - Provides optimistic UI updates + +2. URQL: + + - Implements a document cache by default + - Supports customizable caching strategies + - Offers a normalized cache through the Normalized Cache exchange + - Provides easy cache updates and invalidation + +3. Fetch API: + + - No built-in caching mechanism + - Requires manual implementation of caching logic + - Can leverage browser's HTTP cache or custom in-memory/storage solutions + +4. Axios: + + - No built-in caching mechanism for GraphQL + - Requires manual implementation of caching logic + - Can be combined with external caching libraries + +5. Villus: + - Provides a simple document cache + - Supports cache policies similar to Apollo (cache-first, network-only) + - Offers manual cache manipulation methods + - Lighter weight caching compared to Apollo + +## Common Issues and Resolutions + +1. Apollo Client: + + - Issue: Over-fetching data + Resolution: Use fragments and optimized queries + - Issue: Cache inconsistencies + Resolution: Manually update cache or use refetchQueries + - Issue: Performance with large datasets + Resolution: Implement pagination or infinite scrolling + +2. URQL: + + - Issue: Lack of advanced caching features out-of-the-box + Resolution: Use additional exchanges like the Normalized Cache exchange + - Issue: Limited dev tools compared to Apollo + Resolution: Rely on browser network tab or implement custom logging + - Issue: Learning curve for exchanges concept + Resolution: Start with basic setup and gradually add exchanges as needed + +3. Fetch API: + + - Issue: Verbose syntax for GraphQL requests + Resolution: Create utility functions to simplify request creation + - Issue: No built-in error handling for GraphQL errors + Resolution: Implement custom error checking and handling logic + - Issue: Manual caching and state management + Resolution: Use state management libraries like Vuex or Pinia alongside Fetch + +4. Axios: + + - Issue: Not GraphQL-specific, requiring more boilerplate + Resolution: Create custom wrapper functions for GraphQL operations + - Issue: Handling GraphQL errors separately from HTTP errors + Resolution: Implement middleware to check for and handle GraphQL-specific errors + - Issue: No built-in caching for GraphQL queries + Resolution: Implement custom caching layer or use with a state management solution + +5. Villus: + - Issue: Limited ecosystem compared to Apollo + Resolution: Combine with other Vue libraries for missing features + - Issue: Less community resources and examples + Resolution: Refer to official documentation and reach out to maintainers for support + - Issue: Potential performance issues with larger applications + Resolution: Consider using more robust solutions like Apollo for very complex apps + +Each approach has its own set of challenges, but also offers unique advantages. The choice between them often depends on the specific requirements of your project, the complexity of your GraphQL operations, and your team's familiarity with the tools. + +## The Grand Finale + +We've journeyed through the land of GraphQL in Vue, exploring five fantastic approaches: + +1. Apollo Client: The Swiss Army knife +2. URQL: The lightweight contender +3. Fetch API: The DIY dynamo +4. Axios: The smooth operator +5. Villus: The Vue-native virtuoso + +Each approach has its own strengths, like instruments in an orchestra. The choice depends on your project's needs, your team's expertise, and the symphony you want to create. + +Remember, in the world of web development, there's no one-size-fits-all solution. It's about finding the right tool for your unique masterpiece. So go forth, experiment, and may your Vue apps be forever data-rich and performant! + +And with that, we bring down the curtain on our GraphQL in Vue extravaganza. But don't worry, the show never really ends in the ever-evolving world of web development. Keep learning, keep coding, and most importantly, keep having fun! πŸŽ­πŸš€ From 3d31f7307dcae3ba252a3afc61f4cb586105eaeb Mon Sep 17 00:00:00 2001 From: amit Date: Fri, 2 Aug 2024 18:55:13 +0530 Subject: [PATCH 5/5] chore: update cover and add links --- ...1.md => graphql-vue-clients-2024-08-01.md} | 562 ++++++++++-------- static/images/blog/vue-with-graphql.png | Bin 37460 -> 41817 bytes 2 files changed, 319 insertions(+), 243 deletions(-) rename blog/{graphql-vue-clients-2024-07-31.md => graphql-vue-clients-2024-08-01.md} (83%) diff --git a/blog/graphql-vue-clients-2024-07-31.md b/blog/graphql-vue-clients-2024-08-01.md similarity index 83% rename from blog/graphql-vue-clients-2024-07-31.md rename to blog/graphql-vue-clients-2024-08-01.md index d86c0c1fb9..70ffe09c7d 100644 --- a/blog/graphql-vue-clients-2024-07-31.md +++ b/blog/graphql-vue-clients-2024-08-01.md @@ -15,12 +15,10 @@ image: /image/blog/vue-with-graphql.png ![Cover Image for Vue in GraphQL](../static/images/blog/vue-with-graphql.png) -## Introduction - -### GraphQL in Vue: 5 Best Approaches for Data Fetching - Are you tired of wrestling with complex data fetching logic in your Vue applications? If you've ever felt like you're battling an octopus to retrieve the data you need, then GraphQL is here to be your data fetching hero! + + GraphQL empowers you to take control of your data requests in Vue.js, ensuring you receive only the specific data your application requires. This translates to cleaner code, faster performance, and a more delightful developer experience. In this comprehensive guide, we'll unveil the top 5 approaches to seamlessly integrate GraphQL into your Vue projects. It's like opening a treasure chest overflowing with powerful data fetching techniques! @@ -29,7 +27,7 @@ Whether you're a GraphQL novice or a seasoned pro, this blog post caters to all Ready to elevate your Vue development experience? Let's dive in! -### πŸ› οΈ Project Setup +## πŸ› οΈ Project Setup Let's start by setting up our Vue project with Vite, which provides a faster and leaner development experience: @@ -111,13 +109,11 @@ With this setup, we're ready to dive into the exciting world of GraphQL in Vue! Alright, let's dive into our first approach: Apollo Client! πŸš€ -## Approach 1: Apollo Client - The Swiss Army Knife of GraphQL +## Apollo Client - The Swiss Army Knife of GraphQL Apollo Client stands out in the GraphQL ecosystem due to its comprehensive feature set, including intelligent caching, real-time updates, and optimistic UI rendering. For Vue developers working on data-intensive applications, Apollo Client provides a sophisticated approach to state management and data fetching. -## 1. Setting Up Apollo Client in a Vue.js Project - -### Installation +### 1. Setting Up Apollo Client in a Vue.js Project Begin by installing the necessary packages: @@ -125,7 +121,7 @@ Begin by installing the necessary packages: npm install @apollo/client @vue/apollo-composable graphql ``` -### Configuration +#### Configuration Set up Apollo Client in your Vue application: @@ -169,15 +165,15 @@ app.mount("#app") This configuration creates an Apollo Client instance with a default in-memory cache and provides it to the entire Vue application. -## 2. Executing Queries with Apollo Client +### 2. Executing Queries with Apollo Client Apollo Client provides the `useQuery` composable for executing GraphQL queries. Here's an example of fetching a list of posts: -```typescript +```vue @@ -289,8 +296,14 @@ const submitPost = async () => { @@ -303,7 +316,7 @@ This example showcases: 3. Implementing optimistic updates for immediate UI feedback 4. Handling form submission and mutation execution -## 4. Advanced Apollo Client Features +### 4. Advanced Apollo Client Features ### Caching and Normalization @@ -344,7 +357,7 @@ This setup demonstrates: 2. Computed fields based on reactive variables 3. Using reactive variables for local state management -### Error Handling and Retry Logic +#### Error Handling and Retry Logic Implement robust error handling and retry logic: @@ -387,76 +400,79 @@ const link = ApolloLink.from([ This configuration adds comprehensive error logging and automatic retry for failed requests. -## 5. Performance Optimization +### 5. Performance Optimization To optimize performance when using Apollo Client with Vue: 1. **Implement pagination** for large datasets: -```typescript - -``` + ```vue + + ``` 2. **Use fragments** for reusable query parts: -```typescript -import gql from "graphql-tag" - -export const POST_FRAGMENT = gql` - fragment PostDetails on Post { - id - title - body - createdAt - } -` - -export const GET_POSTS = gql` - ${POST_FRAGMENT} - query GetPosts { - posts { - ...PostDetails - } - } -` -``` + ```typescript + import gql from "graphql-tag" + + export const POST_FRAGMENT = gql` + fragment PostDetails on Post { + id + title + body + createdAt + } + ` + + export const GET_POSTS = gql` + ${POST_FRAGMENT} + query GetPosts { + posts { + ...PostDetails + } + } + ` + ``` 3. **Leverage Apollo Client DevTools** for performance monitoring and cache inspection. -## Conclusion +### Conclusion Apollo Client provides a powerful and flexible solution for integrating GraphQL into Vue.js applications. Its advanced features like normalized caching, optimistic updates, and comprehensive error handling make it an excellent choice for complex, data-intensive applications. @@ -468,7 +484,7 @@ Key takeaways: - Advanced features like custom cache policies and reactive variables offer fine-grained control over data management - Performance optimization techniques such as pagination and fragments are crucial for scalable applications -## Approach 2: URQL - A Lightweight GraphQL Client for Modern Web Development +## URQL - A Lightweight GraphQL Client for Modern Web Development URQL stands out for its simplicity and modularity, making it an excellent choice for Vue.js projects that require GraphQL integration without the overhead of more complex libraries. Its lightweight nature contributes to faster load times and improved performance, especially in resource-constrained environments. @@ -479,9 +495,9 @@ URQL stands out for its simplicity and modularity, making it an excellent choice - Easy to extend with custom exchanges - First-class TypeScript support -## 2. Setting Up URQL in a Vue.js Project +### 2. Setting Up URQL in a Vue.js Project -### Installation +#### Installation Begin by installing URQL and its Vue integration: @@ -489,7 +505,7 @@ Begin by installing URQL and its Vue integration: npm install @urql/vue graphql ``` -### Configuration +#### Configuration Set up the URQL client in your Vue application: @@ -509,14 +525,14 @@ app.mount("#app") This configuration creates an URQL client and integrates it with Vue's plugin system, making it available throughout your application. -## 3. Executing Queries with URQL +### 3. Executing Queries with URQL URQL provides a `useQuery` composable for executing GraphQL queries. Here's an example of fetching a list of posts: -```typescript +```vue @@ -607,8 +630,14 @@ const createPost = async () => { @@ -621,9 +650,9 @@ This example showcases: 3. Handling form submission and mutation execution 4. Managing loading and error states for the mutation -## 5. Advanced URQL Features and Best Practices +### 5. Advanced URQL Features and Best Practices -### Caching and Normalization +#### Caching and Normalization URQL provides a document cache by default, but for more complex applications, you might want to use the normalized cache: @@ -660,7 +689,7 @@ const client = createClient({ This setup enables more efficient caching and automatic updates for related queries when mutations occur. -### Error Handling and Retry Logic +#### Error Handling and Retry Logic Implement robust error handling and retry logic: @@ -684,83 +713,86 @@ const client = createClient({ This configuration adds automatic retry for network errors or GraphQL errors, improving the resilience of your application. -## 6. Performance Optimization +### 6. Performance Optimization To optimize performance when using URQL with Vue: 1. **Leverage server-side rendering (SSR)** for initial data loading: -```typescript -import {createClient, ssrExchange} from "@urql/vue" + ```typescript + import {createClient, ssrExchange} from "@urql/vue" -const ssr = ssrExchange({ - isClient: typeof window !== "undefined", -}) + const ssr = ssrExchange({ + isClient: typeof window !== "undefined", + }) -const client = createClient({ - url: "https://your-graphql-endpoint.com/graphql", - exchanges: [ - dedupExchange, - cacheExchange, - ssr, - fetchExchange, - ], -}) -``` + const client = createClient({ + url: "https://your-graphql-endpoint.com/graphql", + exchanges: [ + dedupExchange, + cacheExchange, + ssr, + fetchExchange, + ], + }) + ``` 2. **Implement pagination** for large datasets: -```typescript - -``` + ```vue + + ``` 3. **Use fragments** for reusable query parts: -```typescript -const PostFragment = ` - fragment PostDetails on Post { - id - title - body - createdAt - } -` - -const postsQuery = ` - ${PostFragment} - query GetPosts { - posts { - ...PostDetails - } - } -` -``` + ```typescript + const PostFragment = ` + fragment PostDetails on Post { + id + title + body + createdAt + } + ` + + const postsQuery = ` + ${PostFragment} + query GetPosts { + posts { + ...PostDetails + } + } + ` + ``` -## Conclusion +### Conclusion URQL provides a lightweight yet powerful solution for integrating GraphQL into Vue.js applications. Its simplicity, coupled with advanced features like normalized caching and SSR support, makes it an excellent choice for developers seeking efficiency and flexibility. By following the best practices and optimization techniques outlined in this tutorial, you can build performant, scalable Vue applications with GraphQL. @@ -774,36 +806,46 @@ Key takeaways: As you implement URQL in your Vue projects, remember to stay updated with the latest developments in both URQL and the GraphQL ecosystem to leverage new features and best practices as they emerge. -## Approach 3: Fetch API - The DIY Dynamo +## Fetch API - The DIY Dynamo In modern web development, effective data fetching is a cornerstone for building dynamic and responsive applications. While powerful libraries like Apollo and URQL offer extensive features for GraphQL integration, there are situations where a more hands-on approach is desirable. Enter the Fetch API: a versatile, built-in tool for making network requests, allowing developers to craft their GraphQL interactions from the ground up. This tutorial will guide you through using the Fetch API for GraphQL data fetching in Vue.js, providing a deep understanding of the process and its practical applications. -## Step-by-Step Instructions +### Step-by-Step Instructions -### Installation and Integration Steps +#### Installation and Integration Steps One of the key advantages of the Fetch API is its built-in availability in modern browsers. This means no additional package installations are required, simplifying the setup process. -### Code Snippets +#### Code Snippets Let's start by setting up a basic Vue component that uses the Fetch API to query a GraphQL endpoint. -```typescript +```vue ``` -### Error Handling +#### Error Handling Handling errors effectively is crucial in any data-fetching scenario. The above code includes a robust error-handling system that categorizes errors into network errors, GraphQL errors, and unexpected errors. @@ -937,7 +983,7 @@ This approach ensures that your application can gracefully handle and display er The Fetch API serves as a powerful tool for developers looking to craft their GraphQL solutions with precision and control. While it may not offer the convenience and features of dedicated GraphQL clients, it provides a lightweight and versatile alternative. By following best practices and understanding potential challenges, developers can effectively leverage the Fetch API for various professional development scenarios, gaining valuable insights and experience in the process. -## Approach 4: Axios - The Smooth Operator +## Axios - The Smooth Operator In the world of HTTP clients, Axios is like a sous chef in your kitchen, handling the tedious tasks and ensuring your GraphQL requests are prepared with finesse. Unlike the Fetch API, Axios simplifies and streamlines data fetching, making it an attractive option for developers seeking efficiency without sacrificing control. Let's dive into how Axios can enhance your Vue.js application with smooth and efficient GraphQL data fetching. @@ -955,10 +1001,10 @@ That's it! Axios is now ready to use, providing a smooth and easy setup process. Here's how you can use Axios to fetch data from a GraphQL endpoint in a Vue component: -```typescript +```vue