Build a Remix app with Apollo and GraphQL
TLDR;
Lately at Carbonable we faced technical challenges to manage data complexity and efficient server-side rendering.
However, with the power of Remix for full-stack web development, Apollo Client for querying our GraphQL schema and GraphQL Codegen for generating TypeScript types, we turned these hurdles into stepping stones.
This is simple tutorial of how you can build a fully functional web app within minutes with the lessons we’ve learned along the way.
The Tech
Remix.run (full stack web framework)
Apollo Client (Querying GraphQL Tool)
GraphQL Codegen (Generate typescript types from GraphQL schema)
Full code available here 👇
https://github.com/schwepps/remix-graphql
Context
At Carbonable we have integrated GraphQL to one of our project lately and we wanted to share the basics to setup a project from scratch based on our tech stack.
Let’s code stuff!
Prerequisites
- Start a remix project
npx create-remix@latest
#Then choose the following options
? Where would you like to create your app? ./auth-app
? What type of app do you want to create? Just the basics
? Where do you want to deploy? Choose Remix App Server if you're unsure; it's easy to change deployment targets. Remix App Server
? TypeScript or JavaScript? TypeScript
? Do you want me to run `npm install`? Y
2. Install Apollo Client
npm install @apollo/client graphql
3. Install CodeGen tools for GraphQL type generation in typescript
npm install --save-dev @graphql-codegen/cli @graphql-codegen/client-preset
5. Have a GraphQL schema ready to query
In this article, we will use one of the free graphQL schema: https://countries.trevorblades.com/graphql
You can pick your favorite one here: https://www.apollographql.com/blog/community/backend/8-free-to-use-graphql-apis-for-your-projects-and-demos/
Create Apollon Client
root.tsx
First we need to initialize an ApolloClient working with server side rendering
import { ApolloClient, ApolloProvider, InMemoryCache, createHttpLink } from "@apollo/client";
// Initialize Apollo client
const graphQLClient = new ApolloClient({
ssrMode: true, // Indicates that we want to use server side rendering
link: createHttpLink({ // Use createHttpLink instead of uri
uri: 'https://countries.trevorblades.com/graphql', //Path to GraphQL schema
headers: {
'Access-Control-Allow-Origin': '*', //Cors management
},
}),
cache: new InMemoryCache(), // Cache management
});
Then we inject this client in the Apollo Provider which is working as a global context to make the client working anywhere in the remix app.
<ApolloProvider client={graphQLClient}>
<Outlet />
<ScrollRestoration />
<Scripts />
<LiveReload />
</ApolloProvider>
Generate code from GraphQL schema
In this section we will generate amongst other things the typescript types from remote graphQL schema.
Create codegen.ts at the root of the project
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
schema: 'https://countries.trevorblades.com/graphql',
documents: ['src/**/*.tsx'],
generates: {
'./app/graphql/__generated__/': {
preset: 'client',
plugins: [],
presetConfig: {
gqlTagName: 'gql',
}
}
},
ignoreNoDocuments: true,
};
export default config;
Note 1: Here the code will be generated in ./app/graphql/__generated__/
You can choose any folder you want inside your project.
Note 2: It’s recommended to add the generated code to your .gitignore
Note 3: In this example we generate the code from a free of use GraphQL Schema: https://countries.trevorblades.com/graphql
Add scripts in package.json
"scripts": {
"compile": "graphql-codegen",
"watch": "graphql-codegen -w"
},
Generate code from graphQL schema
# Run the following command to generate the files
npm run compile
Query the data
Create the query
Create a file named queries.ts in the graphql folder automatically created by the script above and add the following query:
import { gql } from "@apollo/client";
// This query will only return the code, the name and the flag of the countries
export const GET_ALL_COUNTRIES = gql`
query GetAllCountries {
countries {
code
name
emoji
}
}
`;
Display the data
In _index.tsx add the following code to query the countries:
import { useQuery } from "@apollo/client";
import type { V2_MetaFunction } from "@remix-run/node";
import type { Country } from "~/graphql/__generated__/graphql";
import { GET_ALL_COUNTRIES } from "~/graphql/queries";
export const meta: V2_MetaFunction = () => {
return [
{ title: "Countries" },
{ name: "description", content: "Query countries with remix and graphQL" },
];
};
export default function Index() {
const { loading, error, data } = useQuery(GET_ALL_COUNTRIES);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error : {error.message}</p>;
return (
<div>
{data.countries.map((country: Country) => (
<div key={country.code}>
<h2>{country.emoji} {country.name}</h2>
</div>
))}
</div>
);
}
Note 1: As you can see we can use the autogenerated type Country directly in our code.
Note 2: We can call useQuery from Apollo Client in component of the app.
Congrats 🥳
You’ve made it to the end!
Check the result by running npm run dev in your terminal.
You should see the list of countries like this.
Going further
This is just a simple example to display data with free resources.
With a dedicated graphQL schema and the Apollo documentation you can add very useful functionalities to your project such as:
- Mutations (to add, edit or delete data)
- Pagination (for better performances and UX)
I also highly encourage to follow the best practices!