Skip to content

Instantly share code, notes, and snippets.

@beeman
Last active January 20, 2020 21:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save beeman/03dac20f601900fd3c56731542c95736 to your computer and use it in GitHub Desktop.
Save beeman/03dac20f601900fd3c56731542c95736 to your computer and use it in GitHub Desktop.
Installing Apollo Client in Angular

Set up Apollo for Angular

  • Install deps:
yarn add apollo-angular \
         apollo-angular-link-http \
         apollo-cache-inmemory \
         apollo-link-ws \
         subscriptions-transport-ws \
         apollo-link \
         apollo-utilities \
         apollo-client \
         graphql
  • Create graphql.module.ts based on the attached file.

  • Import GraphQLModule in app.module.ts.

GraphQL Code Generator

Create the folders for the SDK:

mkdir -p src/sdk/queries   // This is where we will add the queries
mkdir -p src/sdk/generated // This is where the generated SDK lives

Install the GraphQL Codegen CLI. We will use this tool to create our config file.

yarn add -D @graphql-codegen/cli

Once this is installed we run the following command to create the config file:

npx graphql-codegen init

Use the following options:

? What type of application are you building?
         Application built with Angular
? Where is your schema?: (path or url)
         http://localhost:4000/graphql
? Where are your operations and fragments?:
         src/sdk/queries/**/*.graphql
? Pick plugins:
         TypeScript (required by other typescript plugins)
         TypeScript Operations (operations and fragments)
         TypeScript Apollo Angular (typed GQL services)
? Where to write the output:
         src/sdk/generated/graphql.ts
? Do you want to generate an introspection file?
         Yes
? How to name the config file?
         codegen.yml
? What script in package.json should run the codegen?
         sdk

The contets gets saved to codegen.yml and the dependencies and a run-script are added to package.json.

Next we install the new dependencies:

yarn install

Once this is done we need to add a query to src/sdk/queries to the SDK has something to build.

Create the file src/sdk/queries/members.graphql and add the following content:

query Members {
  members {
    id
  }
}

With this in place, you can run the sdk script to generate the sdk:

yarn sdk

You should now see the file src/sdk/generated/graphql.ts.

To make the import path for our app shorter, let's generate the file src/sdk/index.ts and add this:

export * from './generated/graphql'

Next, we need to open codegen.yml and make 2 changes:

Add the config right below where we defined src/sdk/generated/graphql.ts:

  src/sdk/generated/graphql.ts:
    config:
      sdkClass: true

And add a hook that automatically invokes prettier when files are created:

hooks:
  afterAllFileWrite:
    - prettier --write

The complete config file should look like this:

overwrite: true
schema: "http://localhost:4000/graphql"
documents: "src/sdk/queries/**/*.graphql"
generates:
  src/sdk/generated/graphql.ts:
    config:
      sdkClass: true
    plugins:
      - "typescript"
      - "typescript-operations"
      - "typescript-apollo-angular"
  ./graphql.schema.json:
    plugins:
      - "introspection"

hooks:
  afterAllFileWrite:
    - prettier --write

Lastly, we add a second run-script to package.json that lets you run the sdk in watch mode:

    "sdk:watch": "nodemon --watch 'src/sdk/queries/**/**' --ext '*' -x 'yarn sdk'",

Note that you need nodemon installed in order for this to work.

import { NgModule } from '@angular/core';
import { ApolloModule, APOLLO_OPTIONS } from 'apollo-angular';
import { HttpLinkModule, HttpLink } from 'apollo-angular-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { WebSocketLink } from 'apollo-link-ws';
import { ApolloLink, split } from 'apollo-link';
import { getMainDefinition } from 'apollo-utilities';
import { environment } from '../environments/environment';
export function createApollo(httpLink: HttpLink) {
const token = false; // You probably get this from a cookie or localStorage
const headers = {
authorization: token ? `Bearer ${token}` : null,
};
const http = httpLink.create({
uri: environment.apiUrl,
});
const middlewareLink = new ApolloLink((operation, forward) => {
operation.setContext({
headers: token ? headers : null,
});
return forward(operation);
});
const httpAuth = middlewareLink.concat(http);
const ws = new WebSocketLink({
uri: environment.apiWsUrl,
options: {
reconnect: true,
timeout: 10000,
connectionParams: {
...headers,
},
},
});
// Using the ability to split links, you can send data to each link depending on the kind of operation
const link = split(
// Split based on operation type
({ query }) => {
const { kind, operation }: any = getMainDefinition(query);
// Run only Subscriptions over the WebSocketLink
return kind === 'OperationDefinition' && operation === 'subscription';
// Run both Subscriptions and Mutations over the WebSocketLink
// return kind === 'OperationDefinition' && (operation === 'subscription' || operation === 'mutation');
// Run all operations over the WebSocketLink
// return kind === 'OperationDefinition' && (operation === 'subscription' || operation === 'mutation' || operation === 'query');
},
ws,
httpAuth,
);
return {
link,
cache: new InMemoryCache(),
// Enable cache once know what you're doing
defaultOptions: {
watchQuery: {
fetchPolicy: 'no-cache',
errorPolicy: 'all',
},
query: {
fetchPolicy: 'no-cache',
errorPolicy: 'all',
},
},
};
}
@NgModule({
exports: [ApolloModule, HttpLinkModule],
providers: [
{
provide: APOLLO_OPTIONS,
useFactory: createApollo,
deps: [HttpLink],
},
],
})
export class AppGraphQLModule {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment