Skip to content

Commit

Permalink
[Examples] Move with-typescript-graphql to SSG (#13854)
Browse files Browse the repository at this point in the history
Related to #11014
  • Loading branch information
lfades committed Jun 10, 2020
1 parent 9dc9028 commit 4327182
Show file tree
Hide file tree
Showing 12 changed files with 152 additions and 253 deletions.
2 changes: 1 addition & 1 deletion examples/with-stitches/css/index.js
Expand Up @@ -17,7 +17,7 @@ const context = React.createContext(null)

/*
With Typescript:
const Provider: React.FC<{ css: TCss<typeof config> }> = ({ css, children }) => {
const Provider = ({ css, children }: { css: TCss<typeof config>, children?: React.ReactNode }) => {
return <context.Provider value={css}>{children}</context.Provider>
}
*/
Expand Down
35 changes: 33 additions & 2 deletions examples/with-typescript-graphql/.gitignore
@@ -1,4 +1,35 @@
.next
node_modules
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local

# Graphql
*.graphql.d.ts
*.graphqls.d.ts
18 changes: 7 additions & 11 deletions examples/with-typescript-graphql/README.md
Expand Up @@ -2,18 +2,21 @@

One of the strengths of GraphQL is [enforcing data types on runtime](https://graphql.github.io/graphql-spec/June2018/#sec-Value-Completion). Further, TypeScript and [GraphQL Code Generator](https://graphql-code-generator.com/) (graphql-codegen) make it safer by typing data statically, so you can write truly type-protected code with rich IDE assists.

This template extends [Apollo Server and Client Example](https://github.com/vercel/next.js/tree/canary/examples/api-routes-apollo-server-and-client#readme) by rewriting in TypeScript and integrating [graphql-let](https://github.com/piglovesyou/graphql-let#readme), which runs [TypeScript React Apollo](https://graphql-code-generator.com/docs/plugins/typescript-react-apollo) in [graphql-codegen](https://github.com/dotansimha/graphql-code-generator#readme) under the hood. It enhances the typed GraphQL use as below.
This template extends [Apollo Server and Client Example](https://github.com/vercel/next.js/tree/canary/examples/api-routes-apollo-server-and-client#readme) by rewriting in TypeScript and integrating [graphql-let](https://github.com/piglovesyou/graphql-let#readme), which runs [TypeScript React Apollo](https://graphql-code-generator.com/docs/plugins/typescript-react-apollo) in [graphql-codegen](https://github.com/dotansimha/graphql-code-generator#readme) under the hood. It enhances the typed GraphQL use as below:

```typescript jsx
```tsx
import { useNewsQuery } from './news.graphql'

const News: React.FC = () => {
const News = () => {
// Typed already️⚡️
const { data: { news } } = useNewsQuery()
if (news) <div>{news.map(...)}</div>

return <div>{news.map(...)}</div>
}
```

By default `**/*.graphqls` is recognized as GraphQL schema and `**/*.graphql` as GraphQL documents. If you prefer the other extensions, make sure the settings of the webpack loader in `next.config.js` and `.graphql-let.yml` are consistent.

## Deploy your own

Deploy the example using [Vercel](https://vercel.com):
Expand Down Expand Up @@ -52,10 +55,3 @@ yarn dev
```

Deploy it to the cloud with [Vercel](https://vercel.com/import?filter=next.js&utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)).

## Notes

By default `**/*.graphqls` is recognized as GraphQL schema and `**/*.graphql` as GraphQL documents. If you prefer the other extensions, make sure the settings of the webpack loader in `next.config.js` and `.graphql-let.yml` are consistent.

Note: Do not be alarmed that you see two renders being executed. Apollo recursively traverses the React render tree looking for Apollo query components. When it has done that, it fetches all these queries and then passes the result to a cache. This cache is then used to render the data on the server side (another React render).
https://www.apollographql.com/docs/react/api/react-ssr/#getdatafromtree
59 changes: 59 additions & 0 deletions examples/with-typescript-graphql/lib/apollo.ts
@@ -0,0 +1,59 @@
import { IncomingMessage, ServerResponse } from 'http'
import { useMemo } from 'react'
import { ApolloClient } from 'apollo-client'
import { InMemoryCache, NormalizedCacheObject } from 'apollo-cache-inmemory'

let apolloClient: ApolloClient<NormalizedCacheObject> | undefined

export type ResolverContext = {
req?: IncomingMessage
res?: ServerResponse
}

function createIsomorphLink(context: ResolverContext = {}) {
if (typeof window === 'undefined') {
const { SchemaLink } = require('apollo-link-schema')
const { schema } = require('./schema')
return new SchemaLink({ schema, context })
} else {
const { HttpLink } = require('apollo-link-http')
return new HttpLink({
uri: '/api/graphql',
credentials: 'same-origin',
})
}
}

function createApolloClient(context?: ResolverContext) {
return new ApolloClient({
ssrMode: typeof window === 'undefined',
link: createIsomorphLink(context),
cache: new InMemoryCache(),
})
}

export function initializeApollo(
initialState: any = null,
// Pages with Next.js data fetching methods, like `getStaticProps`, can send
// a custom context which will be used by `SchemaLink` to server render pages
context?: ResolverContext
) {
const _apolloClient = apolloClient ?? createApolloClient(context)

// If your page has Next.js data fetching methods that use Apollo Client, the initial state
// get hydrated here
if (initialState) {
_apolloClient.cache.restore(initialState)
}
// For SSG and SSR always create a new Apollo Client
if (typeof window === 'undefined') return _apolloClient
// Create the Apollo Client once in the client
if (!apolloClient) apolloClient = _apolloClient

return _apolloClient
}

export function useApollo(initialState: any) {
const store = useMemo(() => initializeApollo(initialState), [initialState])
return store
}
2 changes: 1 addition & 1 deletion examples/with-typescript-graphql/lib/resolvers.ts
@@ -1,5 +1,5 @@
import { QueryResolvers } from './type-defs.graphqls'
import { ResolverContext } from './with-apollo'
import { ResolverContext } from './apollo'

const Query: Required<QueryResolvers<ResolverContext>> = {
viewer(_parent, _args, _context, _info) {
Expand Down
4 changes: 1 addition & 3 deletions examples/with-typescript-graphql/lib/schema.ts
Expand Up @@ -2,9 +2,7 @@ import { makeExecutableSchema } from 'graphql-tools'
import typeDefs from './type-defs.graphqls'
import resolvers from './resolvers'

const schema = makeExecutableSchema({
export const schema = makeExecutableSchema({
typeDefs,
resolvers,
})

export default schema
203 changes: 0 additions & 203 deletions examples/with-typescript-graphql/lib/with-apollo.tsx

This file was deleted.

0 comments on commit 4327182

Please sign in to comment.