Skip to content

Commit

Permalink
Chore: docs updates (vercel#46)
Browse files Browse the repository at this point in the history
* fix styles; update prefetching

* add docs about performance; fixes vercel#34

* fixes vercel#45

* add cssnano; fix stylesheet order

* add dark mode support

* upgrade theme

* Apply suggestions from code review

Co-authored-by: Paco <[email protected]>

* remove unnecessary sentence

* upgrade nextra

* update theme

Co-authored-by: Paco <[email protected]>
  • Loading branch information
shuding and pacocoursey authored Nov 5, 2020
1 parent 6bb185c commit 00cbf16
Show file tree
Hide file tree
Showing 23 changed files with 1,080 additions and 105 deletions.
7 changes: 0 additions & 7 deletions components/callout.js

This file was deleted.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@
"intersection-observer": "^0.10.0",
"markdown-to-jsx": "^6.11.4",
"next": "^10.0.0",
"nextra": "^0.2.6",
"nextra-theme-docs": "^0.2.0",
"nextra": "^0.2.7",
"nextra-theme-docs": "^0.2.6",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-intersection-observer": "^8.26.2"
},
"devDependencies": {
"cssnano": "^4.1.10",
"postcss-preset-env": "^6.7.0",
"tailwindcss": "^1.4.6"
}
Expand Down
2 changes: 1 addition & 1 deletion pages/_app.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import 'nextra-theme-docs/style.css'
import '../styles.css'
import 'nextra-theme-docs/style.css'

export default function Nextra({ Component, pageProps }) {
return (
Expand Down
2 changes: 1 addition & 1 deletion pages/_document.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ class MyDocument extends Document {
return (
<Html lang="en">
<Head />
<SkipNavLink />
<body>
<SkipNavLink />
<Main />
<NextScript />
<script
Expand Down
1 change: 1 addition & 0 deletions pages/advanced/meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
110 changes: 110 additions & 0 deletions pages/advanced/performance.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
# Performance

SWR provides critical functionality in all kinds of web apps, so **performance** is a top priority.

SWR’s built-in **caching** and **[deduplication](/advanced/performance#deduplication)** skips unnecessary network requests, but
the performance of the `useSWR` hook itself still matters. In a complex app, there could be hundreds of `useSWR` calls in a single page render.

SWR ensures that your app has:
- _no unnecessary requests_
- _no unnecessary re-renders_
- _no unnecessary code imported_

without any code changes from you.

## Deduplication

It’s very common to reuse SWR hooks in your app. For example, an app that renders the current user’s avatar 5 times:

```jsx
function useUser () {
return useSWR('/api/user', fetcher)
}

function Avatar () {
const { data, error } = useUser()

if (error) return <Error />
if (!data) return <Spinner />

return <img src={data.avatar_url} />
}

function App () {
return <>
<Avatar />
<Avatar />
<Avatar />
<Avatar />
<Avatar />
</>
}
```

Each `<Avatar>` component has a `useSWR` hook inside. Since they have the same SWR key and are rendered at the almost same time, **only 1 network request will be made**.

You can reuse your data hooks (like `useUser` in the example above) everywhere, without worrying about performance or duplicated requests.

There is also a [`dedupingInterval` option](/docs/options) for overriding the default deduplication interval.

## Deep Comparison

SWR **deep compares** data changes by default. If the `data` value isn’t changed, a re-render will not be triggered.

You can also customize the comparison function via the [`compare` option](/docs/options) if you want to change the behavior.
For example, some API responses return a server timestamp that you might want to exclude from the data diff.

## Dependency Collection

`useSWR` returns 3 **stateful** values: `data`, `error` and `isValidating`, each one can be updated independently.
For example, if we print those values within a full data-fetching lifecycle, it will be something like this:

```jsx
function App () {
const { data, error, isValidating } = useSWR('/api', fetcher)
console.log(data, error, isValidating)
return null
}
```

In the worst case (the first request failed, then the retry was successful), you will see 5 lines of logs:

```js
// console.log(data, error, isValidating)
undefined undefined false // => hydration / initial render
undefined undefined true // => start fetching
undefined Error false // => end fetching, got an error
undefined Error true // => start retrying
Data undefined false // => end retrying, get the data
```

The state changes make sense. But that also means our component **rendered 5 times**.

If we change our component to only use `data`:

```jsx
function App () {
const { data } = useSWR('/api', fetcher)
console.log(data)
return null
}
```

The magic happens — there are only **2 re-renders** now:

```js
// console.log(data)
undefined // => hydration / initial render
Data // => end retrying, get the data
```

The exact same process has happened internally, there was an error from the first request, then we got the data from the retry.
However, **SWR only updates the states that are used by the component**, which is only `data` now.

If you are not always using all these 3 states, you are already benefitting from this feature.
At [Vercel](https://vercel.com), this optimization results in ~60% fewer re-renders.

## Tree Shaking

The SWR package is [tree-shakeable](https://webpack.js.org/guides/tree-shaking) and side-effect free.
That means if you are only importing the core `useSWR` API, unused APIs like `useSWRInfinite` won't be bundled in your application.
2 changes: 1 addition & 1 deletion pages/docs/data-fetching.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Callout from 'components/callout'
import Callout from 'nextra-theme-docs/callout'
import Link from 'next/link'

# Data Fetching
Expand Down
2 changes: 1 addition & 1 deletion pages/docs/error-handling.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Callout from 'components/callout'
import Callout from 'nextra-theme-docs/callout'
import Link from 'next/link'

# Error Handling
Expand Down
16 changes: 12 additions & 4 deletions pages/docs/mutation.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,22 @@ mutate('/api/user', updateUser(newUser)) // `updateUser` is a Promise of the req

## Mutate Based on Current Data

In many cases, you are receiving a single value back from your API and want to update a list of them.
Sometimes, you want to update a part of your data based on the current data.

With `mutate`, you can pass an async function which will receive the current cached value, if any, and let you return an updated document.

```jsx
mutate('/api/users', async users => {
const user = await fetcher('/api/users/1')
return [user, ...users.slice(1)]
mutate('/api/todos', async todos => {
// let's update the todo with ID `1` to be completed,
// this API returns the updated data
const updatedTodo = await fetch('/api/todos/1', {
method: 'PATCH'
body: JSON.stringify({ completed: true })
})

// filter the list, and return it with the updated item
const filteredTodos = todos.filter(todo => todo.id !== '1')
return [...filteredTodos, updatedTodo]
})
```

Expand Down
2 changes: 1 addition & 1 deletion pages/docs/options.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Callout from 'components/callout'
import Callout from 'nextra-theme-docs/callout'

# API Options

Expand Down
2 changes: 1 addition & 1 deletion pages/docs/pagination.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Callout from 'components/callout'
import Callout from 'nextra-theme-docs/callout'

# Pagination

Expand Down
14 changes: 10 additions & 4 deletions pages/docs/prefetching.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
# Prefetching Data

## Top-Level Page Data

There’re many ways to prefetch the data for SWR. For top level requests, [`rel="preload"`](https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content) is highly recommended:

```html
<link rel="preload" href="/api/data" as="fetch" crossorigin="anonymous">
```

This will prefetch the data before the JavaScript starts downloading. And your incoming fetch requests will reuse the result (including SWR, of course).
Just put it inside your HTML `<head>`. It’s easy, fast and native.

It will prefetch the data when the HTML loads, even before JavaScript starts to download. All your incoming fetch requests with the same URL will reuse the result (including SWR, of course).

## Programmatically Prefetch

Another choice is to prefetch the data conditionally. You can have a function to refetch and set the cache via [mutate](/docs/mutation):
Sometimes, you want to preload a resource conditionally. For example, preloading the data when the user is [hovering](https://github.com/GoogleChromeLabs/quicklink) [a](https://github.com/guess-js/guess) [link](https://instant.page). The most inituitive way is to have a function to refetch and set the cache via the global [mutate](/docs/mutation):

```js
import { mutate } from 'swr'

function prefetch () {
mutate('/api/data', fetch('/api/data').then(res => res.json()))
// the second parameter is a Promise
// SWR will use the result when it resolves
}
```

Then use it when you need to preload the **resources** (for example when [hovering](https://github.com/GoogleChromeLabs/quicklink) [a](https://github.com/guess-js/guess) [link](https://instant.page)).

Together with techniques like [page prefetching](https://nextjs.org/docs#prefetching-pages) in Next.js, you will be able to load both next page and data instantly.
2 changes: 1 addition & 1 deletion pages/docs/revalidation.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Video from 'components/video'
import Callout from 'components/callout'
import Callout from 'nextra-theme-docs/callout'
import Link from 'next/link'

# Automatic Revalidation
Expand Down
2 changes: 1 addition & 1 deletion pages/docs/suspense.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Callout from 'components/callout'
import Callout from 'nextra-theme-docs/callout'

# Suspense

Expand Down
2 changes: 1 addition & 1 deletion pages/docs/with-nextjs.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Callout from 'components/callout'
import Callout from 'nextra-theme-docs/callout'

# Usage with Next.js

Expand Down
2 changes: 1 addition & 1 deletion pages/getting-started.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Callout from '../components/callout'
import Callout from 'nextra-theme-docs/callout'
import Link from 'next/link'

# Getting Started
Expand Down
2 changes: 1 addition & 1 deletion pages/index.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Callout from 'components/callout'
import Callout from 'nextra-theme-docs/callout'
import Features from 'components/features'

# SWR
Expand Down
1 change: 1 addition & 0 deletions pages/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"index": "Introduction",
"getting-started": "Getting Started",
"docs": "Documentation",
"advanced": "Advanced",
"examples": "Examples",
"change-log": "Change Log",
"about": "About"
Expand Down
2 changes: 1 addition & 1 deletion postcss.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module.exports = {
plugins: ['tailwindcss', 'postcss-preset-env']
plugins: ['tailwindcss', 'postcss-preset-env', 'cssnano']
}
6 changes: 4 additions & 2 deletions styles.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@tailwind utilities;

.docs-search > span {
width: 100%;
}
Expand All @@ -19,6 +21,6 @@
@apply not-sr-only fixed ml-6 top-0 bg-white text-lg px-6 py-2 mt-2 outline-none shadow-outline z-50;
}

.callout p {
margin-top: 0;
code {
@apply text-sm;
}
2 changes: 1 addition & 1 deletion tailwind.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module.exports = {
purge: ['./components/**/*.js', './pages/**/*.md', './pages/**/*.mdx'],
purge: ['./components/**/*.js', './pages/**/*.md', './pages/**/*.mdx', './theme.config.js'],
theme: {
screens: {
sm: '640px',
Expand Down
2 changes: 1 addition & 1 deletion theme.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export default {
<meta name="apple-mobile-web-app-title" content="SWR" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsearch.js@2/dist/cdn/docsearch.min.css" media="print" onload="this.media='all'" />
</>,
footerText: <a href="https://vercel.com/?utm_source=swr" target="_blank" rel="noopener" className="inline-flex items-center no-underline text-black font-semibold">
footerText: <a href="https://vercel.com/?utm_source=swr" target="_blank" rel="noopener" className="inline-flex items-center no-underline text-current font-semibold">
<span className="mr-1">Powered by</span><span><Vercel/></span>
</a>
}
Loading

0 comments on commit 00cbf16

Please sign in to comment.