Skip to content

Commit

Permalink
Documentation about prefetching and dehydratedState (#465)
Browse files Browse the repository at this point in the history
  • Loading branch information
MrLeebo authored May 10, 2021
1 parent 072cb16 commit 7209765
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 15 deletions.
21 changes: 16 additions & 5 deletions app/pages/docs/get-server-side-props.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ title: getServerSideProps API
sidebar_label: getServerSideProps API
---

If you export an `async` function called `getServerSideProps` from a page,
Blitz will pre-render this page on each request using the data returned by
`getServerSideProps`.
If you export an `async` function called `getServerSideProps` from a
[page](./pages), Blitz will pre-render this page on each request using the
data returned by `getServerSideProps`.

```js
export async function getServerSideProps(context) {
Expand Down Expand Up @@ -189,9 +189,20 @@ what Blitz eliminates from the client-side bundle.

#### Only allowed in a page

`getServerSideProps` can only be exported from a **page**. You can’t
export it from non-page files.
`getServerSideProps` can only be exported from a [page](./pages). You
can’t export it from non-page files.

Also, you must use `export async function getServerSideProps() {}` — it
will **not** work if you add `getServerSideProps` as a property of the
page component.

#### First Render UX

Even though a page with `getServerSideProps` will be pre-rendered on the
server, it may fallback to the page's loading state if your page contains
queries that request data missing from the initial page props. This can
create a flickering effect where the contents of the page rapidly changes
when the query data gets loaded into the app.

[Click here](./pages#first-render-ux) to discover ways you can improve the
first render User Experience (UX) of your pages.
21 changes: 16 additions & 5 deletions app/pages/docs/get-static-props.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ runtime. And at build time, there is no user http request to handle.

</Card>

If you export an `async` function called `getStaticProps` from a page,
Blitz will pre-render this page at build time using the props returned by
`getStaticProps`.
If you export an `async` function called `getStaticProps` from a
[page](./pages), Blitz will pre-render this page at build time using the
props returned by `getStaticProps`.

```jsx
export async function getStaticProps(context) {
Expand Down Expand Up @@ -376,8 +376,8 @@ the exported JSON is used.

#### Only allowed in a page

`getStaticProps` can only be exported from a **page**. You can’t export it
from non-page files.
`getStaticProps` can only be exported from a [page](./pages). You can’t
export it from non-page files.

One of the reasons for this restriction is that React needs to have all
the required data before the page is rendered.
Expand All @@ -391,6 +391,17 @@ component.
In development (`blitz dev`), `getStaticProps` will be called on every
request.

#### First Render UX

Even though a page with `getStaticProps` will be pre-rendered on the
server, it may fallback to the page's loading state if your page contains
queries that request data missing from the initial page props. This can
create a flickering effect where the contents of the page rapidly changes
when the query data gets loaded into the app.

[Click here](./pages#first-render-ux) to discover ways you can improve the
first render User Experience (UX) of your pages.

#### Preview Mode

In some cases, you might want to temporarily bypass Static Generation and
Expand Down
77 changes: 72 additions & 5 deletions app/pages/docs/pages.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,26 @@ file called `app/pages/posts/[id].js`, then it will be accessible at
By default, Blitz pre-renders the static HTML for every page unless you
explicitly opt-in to server-side rendering.

For pages with dynamic data, the page's loading state will be
pre-rendered.

#### First Render UX
For pages with dynamic data, the page's loading fallback state will be
rendered unless you [prefetch](./query-usage#prefetching) the data to
populate the cache.

In some cases, the static optimization can cause an undesirable UX where
the first render shows one thing but the second render shows another. For
example this happens when using `useSession()`.

Next, we'll introduce some ways to improve the way Blitz pre-renders your
pages.

### First Render UX {#first-render-ux}

To provide a better User Experience (UX), Blitz tries to automatically
pre-render the HTML for your pages, but if your page contains dynamic data
fetched with [useQuery](./use-query) hooks, Blitz will fallback to the
page's loading state and you will not see much benefit from the automatic
pre-rendering, because the application will need to immediately make
another request to fetch the data it needs to satisfy the query.

In this case you can set `Page.suppressFirstRenderFlicker = true`, and
Blitz will hide the first render's content. This will result in a tiny
delay of first paint but will greatly improve the perceived UX.
Expand All @@ -64,6 +75,62 @@ Page.suppressFirstRenderFlicker = true
export default Page
```

You can also consider prefetching all of the necessary queries that your
page needs to complete its first render. You can use either the
`getStaticProps` or `getServerSideProps` page functions, depending on what
you need.

If you create an instance of QueryClient and populate it with query data,
then you can pass it as `dehydratedState` to your page props. Blitz will
automatically use the state to build the query cache later when the page
tries to render.

```tsx
import {
useQuery,
getQueryKey,
invokeWithMiddleware,
dehydrate,
QueryClient,
BlitzPage,
GetServerSidePropsContext
} from 'blitz'
const Page: BlitzPage = () => {
// highlight-start
const [organization] = useQuery(getCurrentOrganization, null)
// highlight-end

return <div>You have selected: {organization.name}</div>
}

export async function getServerSideProps(ctx: GetServerSidePropsContext) {
const queryClient = new QueryClient()

// highlight-start
const queryKey = getQueryKey(getCurrentOrganization, null)
await queryClient.prefetchQuery(queryKey, () =>
invokeWithMiddleware(getCurrentOrganization, null, ctx),
)
// highlight-end

return {
props: {
dehydratedState: dehydrate(queryClient),
},
}
}
```

In this way, the pre-rendered version of your page HTML will not have to
make a request as soon as it loads to fetch any data and will avoid any
screen flickering. This is very useful for Search Engine Optimization and
the Link Previews used by Social Media sites like Facebook and Twitter.

You can also use prefetching to pre-populate queries that a user might
need shortly after the page loads--such a common searches or filter
criteria--by setting a [staleTime](./use-query#options) on the query being
prefetched.

### Static Page Generation for Unauthenticated Pages {#static-page-generation-for-unauthenticated-pages}

For pages accessible by anyone without authentication, we recommend using
Expand Down Expand Up @@ -91,5 +158,5 @@ To use Server-side Rendering for a page, you need to `export` an `async`
function called `getServerSideProps`. This function will be called by the
server on every request.

See the [`getServerSideProps` documentation](./get-server-side-props) for
See the `getServerSideProps` [documentation](./get-server-side-props) for
more details.

0 comments on commit 7209765

Please sign in to comment.