Announcing: Artemis

Jul 1, 2018

I've been on a hiatus working on Artemis, a small companion package that works with Apollo. I'll talk about its benefits and how it works in this post:

Initial State creation & cache restoration

One of the pain points I wanted to see alleviated was a cleaner API for initializing Apollo's cache state. A lot of other methods required you to hand-write your own code, so I set out to write a simple API that would be clear and concise. This can be used anywhere you use Apollo inside of Next.js:

import App, { Container } from "next/app";
import React from "react";
import { ApolloProvider } from "apollo-provider";
import { ApolloClient } from "apollo-client";
import WithArtemis, { ArtemisState } from "next-artemis";
 
interface AppProps {
    artemisClient: ArtemisState<ApolloClient<any>>; //where <any> is your apollo client shape
}
 
class MyApp extends App<AppProps> {
    public render () {
        const { Component, pageProps, router, artemisClient } = this.props;
        return (
            <ApolloProvider client={artemisClient}/>
                <Container>
                    <Component {...pageProps}/>
                </Container>
            </ApolloProvider>
        );
    }
}
 
export default WithArtemis(MyApp);

WithArtemis exposes a prop called artemisClient, which is an improved version of ApolloClient with initial state creation, single data connections per client, and many more little features to improve your GraphQL experience.

To initialize your Artemis cache, which will subsequently be passed to Apollo:

import { initArtemis } from "next-artemis";

const client = initArtemis({
    data: {
        foo: "bar",
        baz: "foo"
    }
});

Whatever is inside of the object that you pass into initArtemis will be the shape that ApolloClient will cache to. Usually these cache shapes are generated via types from the excellent apollo-codegen library. If no data is provided, Artemis will fall back to an empty object, which is when Apollo will take over with it's own caching.

Environment-based GraphQL Endpoints

Because Artemis hooks into NextJS's getConfig() method, it's even easier to declare environment-based endpoints (great for pointing QA vs Prod environments!)

Inside of your next.config.js file:

module.exports = {
    publicRuntimeConfig: {
        graphQLEndpoint: // the value here is where Artemis will point your graphQL endpoint to
        }
   }
};

Yep, it is that easy! You can just as easily map graphQLEndpoint into NodeJS's environment variable with process.env.NODE_ENV, or use the fantastic dotenv library.

GetDataFromTree

GetDataFromTree is a GraphQL function provided by React-Apollo. What this does is it crawls through your codebase, searches for all GQL queries, stitches them all together, and makes a single query from that schema. Whatever is returned is subsequently disseminated to the components that requested it. Artemis has this built into it, and it will log out the full error stack if the query ever fails.

Rewinding NextJS Head()

One of the problems I noticed while developing NextJS apps with getDataFromTree was that getDataFromTree doesn't actually call componentWillUnmount(), so our NextJS <Head/> can get out of sync. Artemis will automatically clear and re-render the component for you.

Built with TypeScript

I built this library with TypeScript in accordance with the rest of the Apollo libraries, to make it easier to work with. The library is also compiled to JS files, but you'd be losing out on the static types. Next-Artemis exposes ArtemisState, an extended interface that wraps around ApolloClient. This interface assists in typing some of the unique props that Artemis passes down to Apollo.

Check it out!

https://www.npmjs.com/package/next-artemis