This page demonstrates the steps to creating a GraphQL demo using Apollo. For a full example scope, see learnbit-vue.graphql
To make the whole GraphQL demo works, we need to create the following components:
- A custom Vue env for Apollo particularly
- An entity component for your data
- A pair of Apollo client and Apollo server
- A reusable Vue composable to consume data via the Apollo client
- A Vue app to eventually render the data
If you want to go straightforwardly to see the final result in advance, run the following to generate a workspace with the components in this tutorial:
Run the following to create a workspace which includes a custom Vue env:
Here, you only need to modify the jest config in the Vue env to ignore transforming the @apollo
scope:
// config/jest.config.js const vueJestConfig = require('@bitdev/vue.dev-services.tester.vue-jest-config'); const { generateNodeModulesPattern, } = require('@teambit/dependencies.modules.packages-excluder'); // Override the Jest config to ignore transpiling from specific folders const packagesToExclude = ['@teambit', '@apollo']; const transformIgnorePatterns = [ generateNodeModulesPattern({ packages: packagesToExclude, excludeComponents: true }), ] module.exports = { ...vueJestConfig, transformIgnorePatterns, };
The other Vue components we will create will be based on this env.
Create an entity component to define the structure of data being fetched, and provide the methods required for the manipulation of that data. This component serves a a source-of-truth for any component handling that type of data, client-side and server-side.
You can create a new entity component using the following command:
Implement the entity:
export type User = { firstName: string; lastName: string; } export function getFullname(user: User): string { return `${user.firstName} ${user.lastName}`; }
Most of the time, the type definition and necessary util functions would be enough.
It also would be great if you create some mocked data in user.mock.ts
for further usage:
import { User } from "./user"; export const mockedUser: User = { firstName: 'Barry', lastName: 'Allen', };
Another common way to implement an entity is to use an ES class. In this way, you can couple the entity with its methods. However, this is not our focus in this guide.
Create an Apollo client and an Apollo server to handle the GraphQL requests and responses. The client and server are two separate components, but they are usually created together.
However, if the Apollo server is provided by an existing one or a third party, you can skip the server part and only create the client part.
We create a Node app to serve as the Apollo server. You can create a new Node app using the following command:
Implement the server:
// my-apollo-server.ts import { ApolloServer } from '@apollo/server'; import { startStandaloneServer } from '@apollo/server/standalone'; const typeDefs = ` type User { firstName: String lastName: String } type Query { user: User } schema { query: Query } `; export const resolvers = { Query: { user () { return { firstName: 'Barry', lastName: 'Allen', } }, }, }; export const createApolloServer = async (port = 4000) => { const server = new ApolloServer({ typeDefs, resolvers, }); const { url } = await startStandaloneServer(server, { listen: { port }, }); console.log(`🚀 Server ready at: ${url}`); };
This app will serve a simple user data in GraphQL.
Then give the app a name my-apollo-server
and a way to get port number, which is 4000
by default.
// my-apollo-server.node-app.ts import { NodeAppOptions } from '@teambit/node'; export const myApolloServer: NodeAppOptions = { name: 'my-apollo-server', entry: require.resolve('./my-apollo-server.app-root'), portRange: [3000, 4000] }; export default myApolloServer;
// my-apollo-server.app-root.ts import { createApolloServer } from './my-apollo-server'; const port = parseInt(process.argv[2] || '4000', 10); createApolloServer(port);
To run it, you can use the following command:
We create another component to serve as the Apollo client. It would be reusable in all places in your client side. You can create a new component using the following command:
Implement the client:
import fetch from 'cross-fetch' import { ApolloClient, createHttpLink, InMemoryCache } from '@apollo/client/core' // HTTP connection to the API const httpLink = createHttpLink({ // You should use an absolute URL here uri: 'http://localhost:4000/graphql', fetch, }) // Cache implementation const cache = new InMemoryCache() // Create the apollo client export const apolloClient = new ApolloClient({ link: httpLink, cache, })
To be notice that the port number should be the same as the one you use in the server.
We create a Vue composable to consume GraphQL data using the following command:
Implement the composable:
import { computed } from 'vue'; import gql from 'graphql-tag'; import { provideApolloClient, useQuery } from "@vue/apollo-composable"; import { apolloClient } from '@learnbit-vue/graphql.clients.my-apollo-client' import { User, getFullname } from '@learnbit-vue/graphql.entities.user' const GET_USERS = gql` query user { user { firstName lastName } } ` const emptyUser: User = { firstName: '', lastName: '', } export const useUser = () => { const query = provideApolloClient(apolloClient)(() => useQuery(GET_USERS)) const username = computed(() => getFullname(query.result.value?.user || emptyUser)) return username }
To be notice that it uses:
@vue/apollo-composable
: the library to integrate Apollo into Vue@learnbit-vue/graphql.clients.my-apollo-client
: the Apollo client that we integrate@learnbit-vue/graphql.entities.user
: the data entity that we consume
To test your composable, you can use the Apollo server in real world, however, it's highly recommend to mock the Apollo server locally, with the data you mocked previously. In this demo, we do it via the library called msw:
import { graphql } from 'msw' import { setupServer } from 'msw/node' import { mockedUser } from '@learnbit-vue/graphql.entities.user' // import your composable here const server = setupServer( graphql.query('user', (_, res, ctx) => { return res( ctx.data({ user: mockedUser }), ) }) ) test('basic case', async () => { server.listen() // write the test code here server.close() })
We create a Vue app to render the data using the following command:
Implement the app:
<script setup lang="ts"> import { useUser } from '@learnbit-vue/graphql.composables.user'; const username = useUser(); </script> <template> <div id="app"> <h1>Hello</h1> <p> {{ username }} </p> </div> </template>
To be notice that it uses the composable to get user information and render it on the page.
To run the whole GraphQL demo, you can use the following command:
Then you can open the browser to see the result.
To get the whole example locally, you can use this starter:
Now you already know how to create a GraphQL demo using Apollo.
Once again, we recommend:
- create entities for your data structure
- prepare a GraphQL server necessarily
- mock data locally for testing your composables
You can use the same approach to create your own GraphQL demo.