Skip to content

Commit

Permalink
(examples) - next.js (#1502)
Browse files Browse the repository at this point in the history
* add next example

* Update examples/with-next/README.md

Co-authored-by: Jess Telford <[email protected]>

* Update static.js

* convert to trygql.dev

* remove unused dep

* use gql helper

* Remove lockfile

Co-authored-by: Jess Telford <[email protected]>
  • Loading branch information
JoviDeCroock and jesstelford authored Apr 28, 2021
1 parent 25e6c5b commit c5e1422
Show file tree
Hide file tree
Showing 6 changed files with 223 additions and 0 deletions.
48 changes: 48 additions & 0 deletions examples/with-next/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Integrating with Next

## getInitialProps

This is the output you'll get when you're using `{ ssr: true }`, this way urql will try to automate
as much for you as it possibly can by using a [`prepass`](https://github.com/FormidableLabs/react-ssr-prepass)
this means that every `useQuery` used in your virtual-dom will be ran, the data will be collected on the server
and hydrated on the client.

> NOTE: to reduce performance complexities try to keep this to top-level renders as this can amount to waterfalls.
## getStaticProps

This requires some manual work, when we look at [`static.js`](./pages/static.js) we can see that we define our own
`getStaticProps` method, this because these methods are only `user-facing`. When doing a `yarn next build` we'll need to
ensure that the server we're targetting is running so we can successfully execute the static prerender.

## getServerSideProps

This requires some manual work, when we look at [`server.js`](./pages/server.js) we can see that we define our own
`getServerSideProps` method, this because these methods are only `user-facing`.

## Output

We can see that our `/` and `/server` routes are rendered on the server and `/static` is statically prerendered.

```
Page Size First Load JS
┌ λ / 4.98 kB 90 kB
├ /_app 0 B 85 kB
├ ○ /404 3.46 kB 88.5 kB
├ λ /api/graphql 0 B 85 kB
├ λ /server 878 B 85.9 kB
└ ● /static 895 B 85.9 kB
+ First Load JS shared by all 85 kB
├ chunks/d8c192fcf6e34535672c13f111ef41e3832b265d.d03071.js 17.4 kB
├ chunks/f6078781a05fe1bcb0902d23dbbb2662c8d200b3.6a2b27.js 13.3 kB
├ chunks/framework.4b1bec.js 41.8 kB
├ chunks/main.3d1d43.js 7.14 kB
├ chunks/pages/_app.92bde8.js 4.68 kB
└ chunks/webpack.50bee0.js 751 B
λ (Server) server-side renders at runtime (uses getInitialProps or getServerSideProps)
○ (Static) automatically rendered as static HTML (uses no initial props)
● (SSG) automatically generated as static HTML + JSON (uses getStaticProps)
(ISR) incremental static regeneration (uses revalidate in getStaticProps)
```
17 changes: 17 additions & 0 deletions examples/with-next/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "next-get-static-props",
"version": "1.0.0",
"private": true,
"dependencies": {
"graphql": "^15.5.0",
"next": "10.1.2",
"next-urql": "^3.0.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"urql": "^2.0.2"
},
"scripts": {
"start": "next",
"build": "next build"
}
}
10 changes: 10 additions & 0 deletions examples/with-next/pages/_app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { withUrqlClient } from "next-urql";

const App = ({ Component, pageProps }) => <Component {...pageProps} />;

export default withUrqlClient(
() => ({
url: "https://trygql.dev/graphql/basic-pokedex"
}),
{ ssr: false }
)(App);
40 changes: 40 additions & 0 deletions examples/with-next/pages/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { initUrqlClient, withUrqlClient } from "next-urql";
import {
ssrExchange,
dedupExchange,
cacheExchange,
fetchExchange,
useQuery,
gql
} from "urql";

const POKEMONS_QUERY = gql`
query {
pokemons(limit: 10) {
id
name
}
}
`;

function Index() {
const [res] = useQuery({ query: POKEMONS_QUERY });

return (
<div>
<h1>Static</h1>
{res.data.pokemons.map((pokemon) => (
<div key={pokemon.id}>
{pokemon.id} - {pokemon.name}
</div>
))}
</div>
);
}

export default withUrqlClient(
() => ({
url: "https://trygql.dev/graphql/basic-pokedex"
}),
{ ssr: true }
)(Index);
54 changes: 54 additions & 0 deletions examples/with-next/pages/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { initUrqlClient } from "next-urql";
import {
ssrExchange,
dedupExchange,
cacheExchange,
fetchExchange,
useQuery
gql
} from "urql";

const POKEMONS_QUERY = gql`
query {
pokemons(limit: 10) {
id
name
}
}
`;

function Server() {
const [res] = useQuery({ query: POKEMONS_QUERY });

return (
<div>
<h1>Server-side render</h1>
{res.data.pokemons.map((pokemon) => (
<div key={pokemon.id}>
{pokemon.id} - {pokemon.name}
</div>
))}
</div>
);
}

export async function getServerSideProps() {
const ssrCache = ssrExchange({ isClient: false });
const client = initUrqlClient({
url: "https://trygql.dev/graphql/basic-pokedex",
exchanges: [dedupExchange, cacheExchange, ssrCache, fetchExchange]
}, false);

// This query is used to populate the cache for the query
// used on this page.
await client.query(POKEMONS_QUERY).toPromise();

return {
props: {
// urqlState is a keyword here so withUrqlClient can pick it up.
urqlState: ssrCache.extractData()
},
};
}

export default Server;
54 changes: 54 additions & 0 deletions examples/with-next/pages/static.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { initUrqlClient } from "next-urql";
import {
ssrExchange,
dedupExchange,
cacheExchange,
fetchExchange,
useQuery,
gql
} from "urql";

const POKEMONS_QUERY = gql`
query {
pokemons(limit: 10) {
id
name
}
}
`;

function Static() {
const [res] = useQuery({ query: POKEMONS_QUERY });

return (
<div>
<h1>Static</h1>
{res.data.pokemons.map((pokemon) => (
<div key={pokemon.id}>
{pokemon.id} - {pokemon.name}
</div>
))}
</div>
);
}

export async function getStaticProps() {
const ssrCache = ssrExchange({ isClient: false });
const client = initUrqlClient({
url: "https://trygql.dev/graphql/basic-pokedex",
exchanges: [dedupExchange, cacheExchange, ssrCache, fetchExchange]
}, false);

// This query is used to populate the cache for the query
// used on this page.
await client.query(POKEMONS_QUERY).toPromise();

return {
props: {
// urqlState is a keyword here so withUrqlClient can pick it up.
urqlState: ssrCache.extractData()
},
};
}

export default Static;

0 comments on commit c5e1422

Please sign in to comment.