# React

# index

---
layout: collection
override:tags: []
date: 2018-11-05
pathName: react
---

# Accessibility auditing with react-axe and eslint-plugin-jsx-a11y


  If you would like to learn about the basic concepts behind accessibility in
  web pages, refer to the [What is accessibility](/what-is-accessibility) guide
  first.

[`react-axe`](https://github.com/dequelabs/react-axe) is a library that audits a
React application and logs any accessibility issues to the Chrome DevTools
console. It uses the open-source [axe](https://github.com/dequelabs/axe-core)
testing library to flag any issues and their severity.

[`eslint-plugin-jsx-a11y`](https://github.com/evcohen/eslint-plugin-jsx-a11y) is
an ESLint plugin that identifies and enforces a number of accessibility rules
directly in your JSX. Using this in combination with a tool that tests the final
rendered DOM, such as `react-axe`, can help you find and fix any accessibility
concerns on your site.

## Why is this useful?

It is crucial to build websites that provide every user, regardless of their
impairment or restriction, the capability to access its content. Using auditing
libraries such as `react-axe` and `eslint-plugin-jsx-a11y` during the
development of your React application will automatically expose any
accessibility issues as they pop up.

## Use eslint-plugin-jsx-a11y

React already supports writing accessible HTML elements within JSX syntax. For
example, you only need to use the `htmlFor` attribute instead of `for` to link a
label to a specific form element within a React component.

```html
<input id="promo" type="checkbox">
<label htmlFor="promo">Receive promotional offers?</label>
```

The
[React accessibility documentation](https://reactjs.org/docs/accessibility.html)
covers all the nuances of handling accessibility concerns within a React
component. To make it easier to spot these issues during development, Create
React App (CRA) includes the **`eslint-plugin-jsx-a11y`** plugin for ESLint by
default.

To enable pre-configured linting provided by CRA:

1. Install the appropriate [ESLint plugin](https://eslint.org/docs/user-guide/integrations#editors) for your code editor
2. Add a `.eslintrc.json` file to your project

```json
{
  "extends": "react-app"
}
```


  You can find more details about configuring your editor to support out-of-box
  linting in the
  [CRA documentation](https://facebook.github.io/create-react-app/docs/setting-up-your-editor).

Some common accessibility issues will now show up.

*Image accessibility warning in linter*

To check for even more accessibility rules, modify the file to automatically
include all the recommended rules by the plugin:

```json
{
  "extends": ["react-app", "plugin:jsx-a11y/recommended"]
}
```

If you would like an even stricter subset of rules, switch to strict mode:

```json
{
  "extends": ["react-app", "plugin:jsx-a11y/strict"]
}
```


*Label accessibility error in linter*

The project
[documentation](https://github.com/evcohen/eslint-plugin-jsx-a11y#difference-between-recommended-and-strict-mode)
provides information on the differences between recommended and strict mode.

## Use react-axe

`eslint-plugin-jsx-a11y` can help you easily pinpoint any accessibility issues
in your JSX, but it does not test any of the final HTML output. **`react-axe`**
is a library that does exactly this by providing a React wrapper around the
[`axe-core`](https://github.com/dequelabs/axe-core) testing tool by Deque Labs.

Install the library as a development dependency to begin:

```bash
npm install --save-dev react-axe
```

You now only need to initialize the module in `index.js`:

```js
if (process.env.NODE_ENV !== 'production') {
  import('react-axe').then(axe => {
    axe.default(React, ReactDOM, 1000);
    ReactDOM.render(<App />, document.getElementById('root'));
  });
} else {
  ReactDOM.render(<App />, document.getElementById('root'));
}
```

A
[dynamic import](https://v8.dev/features/dynamic-import)
is used here to only load the library when it is not in production mode before
rendering and booting up the root `App` component. This ensures that it is not
unnecessarily included in the final production bundle.

Now when you run the application during development, issues are surfaced
directly to the Chrome DevTools console.

*React Axe in Chrome DevTools*

A severity level is also assigned for each violation. These levels are:

* Minor
* Moderate
* Serious
* Critical

  If you would like to include accessibility testing in your unit testing
  workflow, take a look at the
  [Jest and axe integration example](https://github.com/dequelabs/axe-core/tree/develop/doc/examples/jest_react)
  to understand how.

## Conclusion

1. If you are building a site with React, include accessibility auditing into
   your workflow early to catch problems as you build your components.
2. Use `eslint-plugin-jsx-a11y` to add accessibility checks into your linting
   workflow. CRA already comes with it included, but switch to either the
   recommended or strict mode.
3. In addition to local development testing, include `react-axe` into your
   application to catch any issues on the final rendered DOM. Do not include it
   into your production bundle.


# Add a web app manifest with Create React App


  If you don't know how web app manifest files work, refer to the
  [Add a web app manifest](/add-manifest) guide first.

Create React App (CRA) includes a web app manifest by default. Modifying this
file will allow you to change how your application is displayed when installed
on the user's device.

<figure>
  

*A progressive web app icon on a mobile phone's home screen*

</figure>

## Why is this useful?

Web app manifest files provide the capability to change how an installed
application will look like on the user's desktop or mobile device. By modifying
properties in the JSON file, you can modify a number of details in your
application, including its:

* Name
* Description
* App icon
* Theme color

The [MDN documentation](https://developer.mozilla.org/docs/Web/Manifest)
covers all the properties that can be changed in detail.

## Modify the default manifest

In CRA, a default manifest file, `/public/manifest.json` is included automatically when a new app is created:

```json
{
  "short_name": "React App",
  "name": "Create React App Sample",
  "icons": [
    {
      "src": "favicon.ico",
      "sizes": "64x64 32x32 24x24 16x16",
      "type": "image/x-icon"
    },
    {
      "src": "logo192.png",
      "type": "image/png",
      "sizes": "192x192"
    },
    {
      "src": "logo512.png",
      "type": "image/png",
      "sizes": "512x512"
    }
  ],
  "start_url": ".",
  "display": "standalone",
  "theme_color": "#000000",
  "background_color": "#ffffff"
}
```

This allows anybody to install the application on their device and see some
default details of the application. The HTML file, `public/index.html`, also
includes a `<link>` element to load the manifest.

```html
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
```

Here is an example of an application built with CRA that has a modified manifest
file:

https://glitch.com/edit/#!/cra-web-app-manifest-defaut

To find out if all the properties are working correctly in this example:

-  In the **Application** panel, click the **Manifest** tab.

*DevTool's Manifest tab shows the properties from the app manifest file.*

## Conclusion

1. If you're building a site that you think does not need to be installed on a
   device, remove the manifest and the `<link>` element in the HTML file that
   points to it.
2. If you would like users to install the application on their device, modify
   the manifest file (or create one if you are not using CRA) with any
   properties that you like. The
   [MDN documentation](https://developer.mozilla.org/docs/Web/Manifest)
   explains all the required and optional attributes.


# Code splitting with React.lazy and Suspense


  If you don't yet understand the basic idea behind code splitting, refer to
  [Reduce JavaScript payloads with code splitting](/reduce-javascript-payloads-with-code-splitting)
  guide first.

The **`React.lazy`** method makes it easy to code-split a React application on a
component level using dynamic imports.

```jsx
import React, { lazy } from 'react';

const AvatarComponent = lazy(() => import('./AvatarComponent'));

const DetailsComponent = () => (
  <div>
    <AvatarComponent />
  </div>
)
```

## Why is this useful?

A large React application will usually consist of many components, utility
methods, and third-party libraries. If an effort isn't made to try to load
different parts of an application only when they're needed, a single, large
bundle of JavaScript will be shipped to your users as soon as they load the
first page. This can affect page performance significantly.

The `React.lazy` function provides a built-in way to separate components in an
application into separate chunks of JavaScript with very little legwork. You can
then take care of loading states when you couple it with the `Suspense`
component.

## Suspense

The problem with shipping a large JavaScript payload to users is the length of
time it would take for the page to finish loading, especially on weaker devices
and network connections. This is why code splitting and lazy loading is
extremely useful.

However, there will always be a slight delay that users have to experience when
a code-split component is being fetched over the network, so it's important to
display a useful loading state. Using `React.lazy` with the **`Suspense`**
component helps solve this problem.

```jsx
import React, { lazy, Suspense } from 'react';

const AvatarComponent = lazy(() => import('./AvatarComponent'));

const renderLoader = () => <p>Loading</p>;

const DetailsComponent = () => (
  <Suspense fallback={renderLoader()}>
    <AvatarComponent />
  </Suspense>
)
```

`Suspense` accepts a `fallback` component which allows you to display any React
component as a loading state. The following example shows how this works.
The avatar is only rendered when the button is clicked, where a request is
then made to retrieve the code necessary for the suspended `AvatarComponent`.
In the meantime, the fallback loading component is shown.

https://glitch.com/edit/#!/react-lazy-suspense

In here, the code that makes up `AvatarComponent` is small which is
why the loading spinner only shows for a short amount of time. Larger
components can take much longer to load, especially on
weak network connections.

To better demonstrate how this works:

-  Click the **Throttling** dropdown, which is set to **No throttling** by default. Select **Fast 3G**.
-  Click the **Click Me** button in the app.

The loading indicator will show for longer now. Notice how all the code that
makes up the `AvatarComponent` is fetched as a separate chunk.

<figure>
  

*DevTools network panel showing one chunk.js file being downloaded*

</figure>

 React does not currently support Suspense when components are being server-side
 rendered. If you are rendering on the server, consider using another library
 such as
 [`loadable-components`](https://www.smooth-code.com/open-source/loadable-components/docs/server-side-rendering/)
 which is recommended in the React docs.

## Suspending multiple components

Another feature of `Suspense` is that it allows you to suspend multiple
components from loading, **even if they are all lazy loaded**.

For example:

```jsx
import React, { lazy, Suspense } from 'react';

const AvatarComponent = lazy(() => import('./AvatarComponent'));
const InfoComponent = lazy(() => import('./InfoComponent'));
const MoreInfoComponent = lazy(() => import('./MoreInfoComponent'));

const renderLoader = () => <p>Loading</p>;

const DetailsComponent = () => (
  <Suspense fallback={renderLoader()}>
    <AvatarComponent />
    <InfoComponent />
    <MoreInfoComponent />
  </Suspense>
)
```

This is an extremely useful way to delay rendering of multiple components while
only showing a single loading state. Once all the components have finished
fetching, the user gets to see them all displayed at the same time.

You can see this with the following embed:

https://glitch.com/edit/#!/react-lazy-suspense-multiple

  Loading indicator showing a little too quickly?
  Try simulating a throttled connection in DevTools again.

Without this, it's easy to run into the problem of _staggered loading_, or
different parts of a UI loading one after the other with each having their own
loading indicator. This can make the user experience feel more jarring.

 Although using Suspense to split components is already possible and makes it
 easy to trim down bundle sizes, the React team is continuing to work on
 more features that would extend this even further. The
 [React 16.x roadmap](https://reactjs.org/blog/2018/11/27/react-16-roadmap.html)
 explains this in more detail.

## Handle loading failures

`Suspense` allows you to display a temporary loading state while network
requests are made under the hood. But what if those network requests fail for
some reason? You might be offline, or perhaps your web app is attempting to
lazy-load a [versioned URL](/http-cache/#long-lived-caching-for-versioned-urls)
that is out of date, and no longer available following a server redeployment.

React has a standard pattern for gracefully handling these types of loading
failures: using an error boundary. As described [in the documentation](https://reactjs.org/docs/error-boundaries.html),
any React component can serve as an error boundary if it implements either (or
both) of the lifecycle methods `static getDerivedStateFromError()` or
`componentDidCatch()`.

To detect and handle lazy loading failures, you can wrap your `Suspense`
component with a parent components that serves as an error boundary. Inside the
error boundary's `render()` method, you can render the children as-is if there's
no error, or render a custom error message if something goes wrong:

```js
import React, { lazy, Suspense } from 'react';

const AvatarComponent = lazy(() => import('./AvatarComponent'));
const InfoComponent = lazy(() => import('./InfoComponent'));
const MoreInfoComponent = lazy(() => import('./MoreInfoComponent'));

const renderLoader = () => <p>Loading</p>;

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = {hasError: false};
  }

  static getDerivedStateFromError(error) {
    return {hasError: true};
  }

  render() {
    if (this.state.hasError) {
      return <p>Loading failed! Please reload.</p>;
    }

    return this.props.children;
  }
}

const DetailsComponent = () => (
  <ErrorBoundary>
    <Suspense fallback={renderLoader()}>
      <AvatarComponent />
      <InfoComponent />
      <MoreInfoComponent />
    </Suspense>
  </ErrorBoundary>
)
```

## Conclusion

If you are unsure where to begin applying code splitting to your React
application, follow these steps:

1. Begin at the route level. Routes are the simplest way to identify points of
   your application that can be split. The
   [React docs](https://reactjs.org/docs/code-splitting.html#route-based-code-splitting)
   show how `Suspense` can be used along with
   [`react-router`](https://github.com/ReactTraining/react-router).
2. Identify any large components on a page on your site that only render on
   certain user interactions (like clicking a button). Splitting these
   components will minimize your JavaScript payloads.
3. Consider splitting anything else that is offscreen and not critical for the
   user.


# Code splitting with dynamic imports in Next.js

This post explains different types of [code
splitting](/reduce-javascript-payloads-with-code-splitting/) and how to use
dynamic imports to speed up your Next.js apps.

## Route-based and component-based code splitting

By default, Next.js splits your JavaScript into separate chunks for each route.
When users load your application, Next.js only sends the code needed for the
initial route. When users navigate around the application, they fetch the chunks
associated with the other routes. Route-based code splitting minimizes the
amount of script that needs to be parsed and compiled at once, which results in
faster page load times.

While route-based code splitting is a good default, you can further optimize the
loading process with code splitting on the component level. If you have large
components in your app, it's a great idea to split them into separate chunks.
That way, any large components that are not critical or only render on certain
user interactions (like clicking a button) can be lazy-loaded.

Next.js supports [dynamic `import()`](https://v8.dev/features/dynamic-import),
which allows you to import JavaScript modules (including React components)
dynamically and load each import as a separate chunk. This gives you
component-level code splitting and enables you to control resource loading so
that users only download the code they need for the part of the site that
they're viewing. In Next.js, these components are [server-side rendered
(SSR)](/rendering-on-the-web/)
by default.

## Dynamic imports in action

This post includes several versions of a sample app that consists of a simple
page with one button. When you click the button, you get to see a cute puppy. As
you move through each version of the app, you'll see how dynamic imports are
different from [static
imports](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/import)
and how to work with them.

In the first version of the app, the puppy lives in `components/Puppy.js`. To
display the puppy on the page, the app imports the `Puppy` component in
`index.js` with a static import statement:

```js
import Puppy from "../components/Puppy";
```


https://glitch.com/edit/#!/static-import

To see how Next.js bundles the app, inspect the network trace in DevTools:

When you load the page, all the necessary code, including the `Puppy.js`
component, is bundled in `index.js`:

<figure>

*DevTools Network tab showing showing six JavaScript files: index.js, app.js, webpack.js, main.js, 0.js and the dll (dynamic-link library) file.*

</figure>

When you press the **Click me** button, only the request for the puppy JPEG is
added to the **Network** tab:

<figure>

*DevTools Network tab after the button click, showing the same six JavaScript files and one image.*

</figure>

The downside of this approach is that even if users don't click the button to
see the puppy, they have to load the `Puppy` component because it's included in
`index.js`. In this little example that's not a big deal, but in real-world
applications it's often a huge improvement to load large components only when
necessary.

Now check out a second version of the app, in which the static import is
replaced with a dynamic import. Next.js includes `next/dynamic`, which makes it
possible to use dynamic imports for any components in Next:

```js/1,5/0
import Puppy from "../components/Puppy";
import dynamic from "next/dynamic";

// ...

const Puppy = dynamic(import("../components/Puppy"));
```


https://glitch.com/edit/#!/dynamic-import-nextjs

Follow the steps from the first example to inspect the network trace.

When you first load the app, only `index.js` is downloaded. This time it's
0.5&nbsp;KB smaller (it went down from 37.9&nbsp;KB to 37.4&nbsp;KB) because it
doesn't include the code for the `Puppy` component:

<figure>

*DevTools Network showing the same six JavaScript files, except index.js is now 0.5 KB smaller.*

</figure>

The `Puppy` component is now in a separate chunk, `1.js`, which is loaded only
when you press the button:

<figure>

*DevTools Network tab after the button click, showing the additional 1.js file and the image added to the bottom of the file list.*

</figure>

 By default, Next.js names these dynamic chunks _number_.js, where
_number_ starts from 1. 

In real-world applications, components are often [much
larger](https://bundlephobia.com/result?p=moment@2.24.0), and lazy loading them
can trim your initial JavaScript payload by hundreds of kilobytes.

## Dynamic imports with custom loading indicator

When you lazy-load resources, it's good practice to provide a loading indicator
in case there are any delays. In Next.js, you can do that by providing an
additional argument to the `dynamic()` function:

```js
const Puppy = dynamic(() => import("../components/Puppy"), {
  loading: () => <p>Loading...</p>
});
```


https://glitch.com/edit/#!/dynamic-import-loading

To see the loading indictor in action, simulate slow network connection in
DevTools:

5. In the **Throttling** drop-down list, select **Fast 3G**.

6. Press the **Click me** button.

Now when you click the button it takes a while to load the component and the app
displays the "Loading…" message in the meantime.

<figure>
  

*A dark screen with the text \*

</figure>

## Dynamic imports without SSR

If you need to render a component only on the client side (for example, a chat
widget) you can do that by setting the `ssr` option to `false`:

```js
const Puppy = dynamic(() => import("../components/Puppy"), {
  ssr: false,
});
```


https://glitch.com/edit/#!/dynamic-import-no-ssr

## Conclusion

With support for dynamic imports, Next.js gives you component-level code
splitting, which can minimize your JavaScript payloads and improve application
load time. All components are server-side rendered by default and you can
disable this option whenever necessary.


# Prefetching in create-react-app with Quicklink


This codelab uses [Chrome DevTools](https://www.google.com/chrome/). Download Chrome if you don't already have it.

This codelab shows you how to implement the [Quicklink](/quicklink) library in a React SPA demo to demonstrate how prefetching speeds up subsequent navigations.

## Measure

Before adding optimizations, it's always a good idea to first analyze the current state of the application.

The website is a simple demo built with [create-react-app](https://reactjs.org/docs/create-a-new-react-app.html).

Complete the following instructions in the new tab that just opened:

1. In the [Throttling drop-down list](https://developer.chrome.com/docs/devtools/network/reference/#throttling), select **Fast 3G** to simulate a slow connection type.

1. Type `chunk` into the [Filter textbox](https://developer.chrome.com/docs/devtools/network/reference/#filter-by-property) to hide any resources that do not include `chunk` in their name.

*Network panel showing the home page chunks.*

The site uses [route-based code splitting](/reduce-javascript-payloads-with-code-splitting/), thanks to which only the necessary code is requested at the beginning.

1. [Clear the network requests in DevTools](https://developer.chrome.com/docs/devtools/network/reference/#clear).
1. Within the app, click the **Blog** link to navigate to that page.

The JS and CSS chunks for the new route are loaded to render the page.

*Network panel showing the blog page chunks.*

Next, you'll implement Quicklink in this site, so that these chunks can be prefetched in the home page, making the navigation faster.

This allows you to combine the best of both techniques:

- Route-based code splitting tells the browser to only load the necessary chunks at a higher priority at page load time.
- Prefetching tells the browser to load the chunks for in-viewport links at the lowest priority, during the browser's idle time.

## Configure `webpack-route-manifest`

The first step is to install and configure [webpack-route-manifest](https://github.com/lukeed/webpack-route-manifest), a webpack plugin that lets you generate a manifest file associating routes with their corresponding chunks.

Usually, you would need to install the library, but we've already done it for you. Here's the command that you would need to run:

```bash
npm install webpack-route-manifest --save-dev
```
`config-overrides.js` is a file placed in your project root directory where you can override existing behaviour of the webpack configuration, without having to [eject the project](https://github.com/facebook/create-react-app/blob/master/packages/cra-template/template/README.md#npm-run-eject).

Open `config-overrides.js` for edit and add the `webpack-route-manifest` dependency at the beginning of the file:

```javascript/1/
const path = require('path');
const RouteManifest = require('webpack-route-manifest');
```

Next, configure the `webpack-route-manifest` plugin by adding the following
code to the bottom of `config-overrides.js`:

```javascript
module.exports = function override(config) {
  config.resolve = {
    ...config.resolve,
    alias: {
      '@assets': `${path.resolve(__dirname, 'src/assets')}`,
      '@pages': `${path.resolve(__dirname, 'src/pages')}`,
      '@components': `${path.resolve(__dirname, 'src/components')}`,
    },
  };

  config.plugins.push(
    new RouteManifest({
      minify: true,
      filename: 'rmanifest.json',
      routes(str) {
        let out = str.replace('@pages', '').toLowerCase();
        if (out === '/article') return '/blog/:title';
        if (out === '/home') return '/';
        return out;
      },
    }),
  );

  return config;
};
```

The new code does the following:

- `config.resolve` declares variables with the internal routes to pages, assets and components.
- `config.plugins.push()` creates a `RouteManifest` object and passes it the configuration so that the `rmanifest.json` file can be generated based on the site's routes and chunks.

The `manifest.json` file will be generated and made available at `https://site_url/rmanifest.json`.

## Configure quicklink

At this point you would need to install the Quicklink library in your project. For simplicity, we already added it to the project. Here's the command that you would need to run:

```bash
npm install --save quicklink
```

Open `src/components/App/index.js` for edit.

First, import the Quicklink higher order component (HOC):

```javascript/6/
import React, { lazy, Suspense } from 'react';
import { Route } from 'react-router-dom';

import Footer from '@components/Footer';
import Hero from '@components/Hero';
import style from './index.module.css';
import { withQuicklink } from 'quicklink/dist/react/hoc.js';

const Home = lazy(() => import(/* webpackChunkName: "home" */ '@pages/Home'));
const About = lazy(() => import(/* webpackChunkName: "about" */ '@pages/About'));
const Article = lazy(() => import(/* webpackChunkName: "article" */ '@pages/Article'));
const Blog = lazy(() => import(/* webpackChunkName: "blog" */ '@pages/Blog'));
```

Next, create an `options` object after the `Blog` variable declaration, to use as an argument when calling `quicklink`:

```javascript/0-2/
const options = {
	origins: []
};
```
Finally, wrap each route with the `withQuicklink()` higher order component, passing it an `options` parameter and the target component for that route:

```javascript/5-11/
const App = () => (
  <div className={style.app}>
    <Hero />
    <main className={style.wrapper}>
      <Suspense fallback={<div>Loading...</div>}>
        <Route path="/" exact component={withQuicklink(Home, options)} />
        <Route path="/blog" exact component={withQuicklink(Blog, options)} />
        <Route
          path="/blog/:title"
          component={withQuicklink(Article, options)}
        />
        <Route path="/about" exact component={withQuicklink(About, options)} />
      </Suspense>
    </main>
    <Footer />
  </div>
);
```
The previous code instructs to prefetch chunks for the routes wrapped with `withQuicklink()`, when the link comes into the view.

If Glitch throws an error at this point about the lack of a dependency,
try opening the Glitch Terminal (**Tools** > **Terminal**), running
`refresh` in the Terminal, then running `npm run build`.

## Measure again

Repeat the first 6 steps from [Measure](#measure). Don't navigate to the blog page yet.

When the home page loads the chunks for that route are loaded. After that, Quicklink prefetches the route's chunks for the in-viewport links:

*Network panel showing the home page prefetching chunks.*

These chunks are requested at the lowest priority and without blocking the page.

Next:

1. Clear the Network log again.
1. Disable the **Disable cache** checkbox.
1. Click the **Blog** link to navigate to that page.

*Network panel showing the blog page with chunks picked up from cache.*

The **Size** column indicates that these chunks were retrieved from the "prefetch cache", instead of the network. Loading these chunks without a Quicklink took approximately **580ms**. Using the library it now takes **2ms**, which represents a **99% reduction**!


# Get started: optimize your React app

[React](https://reactjs.org/) is an open-source library that makes building UIs
easier. This learning path will cover different APIs and tools within the
ecosystem that you should consider using to improve the performance and
usability of your application.

This guide will show you how to get up and running with a React application.
Every other guide in this section will cover topics to optimize the speed or
accessibility of a React app.

## Why is this useful?

There's a lot of content that explains how to build fast and reliable
applications, but not many that show how to build fast and reliable **React**
applications. These guides cover all this from the perspective of a React
app where only libraries, APIs, and features specific to
the React ecosystem are mentioned.

## What will you learn?

The tutorials in this learning path do *not* focus on:

* How to use React
* How React works under the hood

Although both of these concepts will be touched on when needed, all the guides
and codelabs in this section will instead focus on how to build fast and
accessible React sites. For this reason, [a basic knowledge of React is
required](https://reactjs.org/docs/getting-started.html).

## Create React App

[Create React App](https://facebook.github.io/create-react-app/) (CRA) is the
easiest way to get started building React applications. It provides a default
setup with a number of core features baked in, including a build system
containing a module bundler (webpack) and a transpiler (Babel).

On a command-line shell, you only need to run the following to create a new
application:

```bash
npx create-react-app app-name
```


`npx` is a package runner that is installed automatically with `npm` 5.2.0 or
later. It simplifies quite a few processes involved with managing
packages—including running CLI commands like `create-react-app`—without
having to install them globally on your machine.

Take a look at
[Introducing npx: an npm package runner](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b) if you would like to learn more.

Once the command finishes executing, you can navigate to and run the application
with the following commands:

```bash
cd new-app
npm start
```

The following embed shows the directory structure and the actual web page of a newly
bootstrapped CRA application.

https://glitch.com/edit/#!/new-create-react-app

  Although CRA makes it simple to get started building a React application,
  there are many different ways to begin building sites with React. The
  ["Popular Alternatives"](https://github.com/facebook/create-react-app#popular-alternatives)
  in the README covers different use-cases and options.

There are multiple configuration files and build scripts that CRA uses to set up
a webpack and Babel build process that includes a base
[Jest](https://jestjs.io/) setup for testing. To make things simpler for the
user, these files are hidden and cannot be accessed until you eject from CRA. It
is always best to avoid ejecting whenever possible, since this means taking on all
of these configuration files as your own source code, which can become difficult
to manage.

The directory structure of a new CRA application only contains the files that
you would actually need to modify in order to work on your application. The
[CRA documentation](https://facebook.github.io/create-react-app/docs/folder-structure)
explains this in detail.

## What's next?

Now that you know how to get started building a Create React App, learn how
to improve your app's performance and accessibility with all the guides in
this learning path:

* [Code splitting with React.lazy and Suspense](/code-splitting-suspense)
* [Virtualize large lists with react-window](/virtualize-long-lists-react-window)
* [Precaching in Create React App with Workbox](/precache-with-workbox-react)
* [Pre-render routes with react-snap](/prerender-with-react-snap)
* [Add a web app manifest with Create React App](/add-manifest-react)
* [Accessibility auditing with react-axe and eslint-plugin-jsx-a11y](/accessibility-auditing-react)


# How AMP can guarantee fastness in your Next.js app

[AMP](https://amp.dev) is a web component framework that guarantees
fast page loads. [Next.js][intro] has built-in support for AMP.

## What will you learn?

This guide first briefly describes [how AMP guarantees fast page loads](#overview), then
explains [the different ways you can support AMP in a Next.js app](#strategies),
then helps you [decide which approach is best for you](#guidance).

The intended audience for this guide is a web developer who has decided to use Next.js but is
unsure of whether to support AMP.

  This guide was not written for web developers who have decided to use AMP but are unsure of what
  framework to use. We will note briefly however that Next.js could be a good choice because it
  supports [AMP server-side rendering](https://amp.dev/documentation/guides-and-tutorials/optimize-and-measure/server-side-rendering/)
  and makes it easy to serve AMP content without introducing a lot of complexity into your codebase.

## How AMP guarantees fast page loads {: #overview }

AMP has two main strategies for guaranteeing fastness:

* **AMP HTML**: A restricted form of HTML that makes certain optimizations mandatory and prohibits
  architectural patterns that lead to slowness. See [How AMP works][overview] for a high-level
  overview of the optimizations and restrictions.
* **AMP Cache**: A content cache used by some search engines, such as Google and Bing, that uses
  [prerendering] to speed up page loads. See [Why AMP Caches exist][why] to learn more about the
  benefits and tradeoffs of the caches and [How does my AMP page get cached?][how] to understand
  how your AMP pages get into the caches.

## How you can use AMP in Next.js {: #strategies }

There are two ways to use AMP in Next.js:

* The **Hybrid AMP** approach lets you create an accompanying AMP version of any
  Next.js page.
* The **AMP-only** approach lets you make AMP the only option for a page.

Although Next.js is usually thought of as a React framework, it's important to understand that
when you use Next.js to serve AMP pages, you can no longer run React components client-side because
React components are not valid AMP components. In other words, Next.js is no longer a React
framework but rather a server-side templating engine for generating AMP pages.

  Check out [How to use AMP in Next.js](/how-to-use-amp-in-nextjs) to try out the two
  approaches yourself.

## How to decide whether to use the Hybrid AMP or AMP-only approach {: #guidance }

If you're serious about load performance, an AMP-only page could be a good way to make sure
that your page gets fast and stays fast. But here's the catch: in order to guarantee fastness,
AMP prohibits certain architectural patterns and HTML elements that often lead to slow pages.
For example, AMP doesn't allow custom synchronous JavaScript because
[render-blocking resources][blockers] are a common cause of slow page loads.

In order to understand whether an AMP-only approach is right for you, you need to figure out
whether all of your frontend code can be represented in AMP HTML:

* Read [How AMP works][overview] to understand AMP's high-level
  architectural restrictions and mandatory optimizations.
* Read [HTML Tags][tags] to see what HTML tags AMP allows and prohibits,
  browse the [AMP component catalogue](https://amp.dev/documentation/components/) to see the
  custom components that the AMP community has built to solve common use cases, and check
  out [amp-script] to learn how to use custom JavaScript to implement features that AMP
  doesn't currently support.

Even if an AMP-only approach won't work for your page, it might still be a good idea to
use AMP whenever possible, because of the guaranteed fastness of AMP HTML and the AMP Caches.
The Hybrid AMP approach in Next.js provides a way to conditionally serve AMP pages. However,
it also creates a higher maintenance cost because it requires you to maintain
two versions of each page.

## Conclusion

AMP guarantees that your site gets fast and stays fast by enforcing patterns that lead to
fastness and prohibiting patterns that lead to slowness. AMP HTML and AMP Caches are the two
main ways that AMP guarantees fastness. But before adopting AMP you should make sure that it
can support all of your site's requirements.

[intro]: /performance-as-a-default-with-nextjs
[collection]: /react#nextjs
[prerendering]: https://developers.googleblog.com/2019/08/the-speed-benefit-of-amp-prerendering.html
[tags]: https://amp.dev/documentation/guides-and-tutorials/learn/spec/amphtml/#html-tags
[blockers]: https://developer.chrome.com/docs/lighthouse/performance/render-blocking-resources/
[why]: https://blog.amp.dev/2017/01/13/why-amp-caches-exist/
[how]: https://amp.dev/documentation/guides-and-tutorials/learn/amp-caches-and-cors/how_amp_pages_are_cached/#how-does-my-amp-page-get-cached?
[amp-script]: https://amp.dev/documentation/components/amp-script/
[overview]: https://amp.dev/about/how-amp-works/


# How to use AMP in Next.js

This codelab lets you try out the two ways that you can use AMP in a Next.js app.
Check out [How AMP can guarantee fastness in your Next.js app][guidance] to learn why you
might want to add AMP support to your Next.js app.

### How to create Hybrid AMP pages {: #hybrid }

  The [AMP-only approach](#amponly) is the recommended path for using AMP with Next.js. The
  Hybrid AMP approach described in this section has a higher maintenance cost than the AMP-only
  approach because it requires you to maintain two versions of each page. You should only use the
  Hybrid approach if you're certain that the AMP-only approach won't work.

The **Hybrid AMP** approach creates an accompanying AMP version of any Next.js page. In the past
the Hybrid approach was frequently used when there was an experience on the main version of your
page that AMP couldn't support. The main version had the full experience while the AMP page had
a slightly degraded experience. With the introduction of [amp-script] there's less of a need
for the Hybrid approach, but we'll cover it here just in case you still need it.

There are multiple ways to configure how Next.js renders and serves pages. Using a `config`
object allows you to modify these on a per-page basis. In order to serve a specific page as
an AMP page, you need to export the `amp` property in the object:

```jsx/2
import React from 'react'

export const config = { amp: 'hybrid' };

const Home = () => (
  <p>This is the home page</p>
);

export default Home;
```


1. Add `?amp=1` to the end of the URL. The page looks the same, but if you look in the
   Console you'll see that the AMP version of the page is being rendered.

<figure>
  

*The live page and a message in the Chrome DevTools Console stating that the page is powered by AMP.*

</figure>

Since the page only has a single `<p>` tag, there's no visible difference between the
main page and its AMP version.

#### How to conditionally serve AMP components

AMP pages need to have their own set of valid components in place of many HTML elements. It's
important to make sure that the AMP components are conditionally served only for the AMP page.
Next.js provides a [hook] called `useAmp` to allow you to conditionally serve different elements
depending on which version of the page was requested.

1. Edit `pages/index.js` so that it renders a different paragraph element to the page depending on whether
   the main version or the AMP version was requested:

   ```jsx/1,5-11
   import React from 'react';
   import { useAmp } from 'next/amp';

   export const config = { amp: 'hybrid' };

   const Home = () => (
     useAmp() ? (
       <p>This is the <strong>AMP</strong> version of the home page</p>
     ) : (
       <p>This is the main version of the home page</p>
     )
   );

   export default Home;
   ```

1. Load the main version of the page:

   <figure>
     

*A screenshot of the main version of the page.*

   </figure>

1. Add `?amp=1` to the end of the URL again to load the AMP version of the page:

   <figure>
     

*A screenshot of the AMP version of the page that is displaying different text than the main version.*

   </figure>

1. Try rendering AMP's replacement of the image tag, `amp-img`:

   {# TODO(kaycebasques): Line highlighting isn't working with this sample. #}

   ```jsx
   import React from 'react';
   import { useAmp } from 'next/amp';

   export const config = { amp: 'hybrid' };

   const imgSrc = 'https://placekitten.com/1000/1000';

   const Image = () => (
     useAmp() ? (
       <amp-img alt="A cute kitten"
         src={imgSrc}
         width="1000"
         height="1000"
         layout="responsive">
       </amp-img>
     ) : (
       <img alt="A cute kitten"
         src={imgSrc}
         width="1000"
         height="1000">
       </img>
     )
   );

   const Home = () => (
     <div>
       <Image />
     </div>
   );

   export default Home;
   ```

   `layout="responsive"` automatically renders a fully responsive image with an aspect ratio
   specified by width and height. Check out [Layout & media queries][layout] to learn more about
   the supported layouts of AMP elements, and [amp-img] to learn more about that element's
   optimizations.

1. View the main version of the page again.

   <figure>
     

*A screenshot showing that the image in the main version of the page overflows the viewport.*

   </figure>

1. View the AMP version of the page again.

   <figure>
     

*A screenshot showing that the image in the AMP version of the page has been automatically resized to fit the viewport.*

   </figure>

### How to create AMP-only pages {: #amponly }

Next.js also supports AMP-only pages. With this approach, a single AMP page is served and rendered
to users and search engines at all times.

1. To render an AMP-only page, change the value of the `amp` property in the config object to `true`.

   ```jsx/2
   import React from 'react'

   export const config = { amp: true };

   const Home = () => (
     <p>This is an AMP-only page</p>
   );

   export default Home;
   ```

[guidance]: /how-amp-can-guarantee-fastness-in-your-nextjs-app
[layout]: https://amp.dev/documentation/guides-and-tutorials/develop/style_and_layout/control_layout/
[collection]: /react#nextjs
[hook]: https://reactjs.org/docs/hooks-overview.html
[layout]: https://amp.dev/documentation/guides-and-tutorials/develop/style_and_layout/control_layout/
[amp-img]: https://amp.dev/documentation/examples/components/amp-img/
[amp-script]: https://amp.dev/documentation/components/amp-script/


# Performance as a default with Next.js

[Next.js](https://nextjs.org/) is an opinionated [React](https://reactjs.org/)
framework with a number of performance optimizations baked in. The main idea
behind the framework is to ensure applications start and remain as performant
as possible by having these capabilities included by default.

This introduction will briefly cover many features provided by the framework
at a high level. The other guides in this collection will explore the features
in more detail.

  Chrome is collaborating with Next.js to improve the framework for any developer looking to
  build a fast, server-rendered React application. A number of newer optimizations were recently
  added such as [module/nomodule support](https://github.com/zeit/next.js/issues/7563) and an
  [improved granular chunking strategy](https://github.com/zeit/next.js/issues/7631).

## What will you learn?

Although Next.js provides a number of performance optimizations by default, these guides
aim to explain them in more detail and show you how you can use them to build a fast and
performant experience.

  This collection assumes that you have a basic knowledge of React. If not, check out
  [React's Getting Started page](https://reactjs.org/docs/getting-started.html).

There are many optimizations that can be added to React sites in general that would also
work for applications built with Next.js. These will not be covered since the focus is
on what Next.js specifically provides. To learn more about general React
optimizations, check out our [React collection][collection].

## How is Next.js different from React?

React is a library that makes it easier to build user interfaces using a component-based
approach. Although powerful, React is specifically a UI library. Many developers include
additional tooling such as a module bundler ([webpack](https://webpack.js.org/) for example)
and a transpiler ([Babel](https://babeljs.io/) for example) to have a complete build toolchain.

In the [React collection][collection], we took the approach of using [Create React App](https://create-react-app.dev/)
(CRA) to spin up React apps quickly. CRA takes the hassle out of setting up a React application
by providing a complete build toolchain with a single command.

Although there are a few default optimizations baked into CRA, the tool aims to provide a
simple and straightforward setup. The choice is given to developers to decide whether
to [eject](https://create-react-app.dev/docs/available-scripts#npm-run-eject) and
modify the configurations themselves.

Next.js, which can also be used to create a new React application, takes a different approach.
It immediately provides a number of common optimizations that many developers would like to have
but find difficult to set up, such as:

* Server-side rendering
* Automatic code-splitting
* Route prefetching
* File-system routing
* CSS-in-JS styling ([`styled-jsx`](https://github.com/zeit/styled-jsx))

## Setting up

To create a new Next.js application, run the following command:

```bash
npx create-next-app new-app
```


  [npx](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b)
  is a package runner that is installed automatically with npm 5.2.0 or later. It simplifies
  quite a few processes involved with managing packages including running CLI commands
  (like `create-next-app`) without having to install them globally on your machine.

Then navigate to the directory and start the development server:

```bash
cd new-app
npm run dev
```


  You can also add Next.js to an existing React application.
  Check out [Manual Setup](https://nextjs.org/docs#manual-setup) to learn how.

The following embed shows the directory structure of a new Next.js app.

https://glitch.com/edit/#!/new-next-app

Notice that a `pages/` directory is created with a single file: `index.jsx`. Next.js follows
a file-system routing approach, where every page within this directory is served as a separate
route. Creating a new file in this directory, such as `about.js`, will automatically create a
new route (`/about`).

Components can also be created and used like any other React application. A `components/`
directory has already been created with a single component, `nav.js`, which is already
imported in `index.js`. By default, every import used in Next.js is only fetched when that
page is loaded, providing the benefits of **automated code-splitting**.

Moreover, every initial page load in Next.js is **server-side rendered**. If you open
the Network panel in DevTools, you can see the initial request for the document returns
a fully server-rendered page.

<figure>
  

*The Preview tab of the Network panel shows that Next.js returns visually complete HTML when a page is requested.*

  <figcaption>
    The Preview tab of the Network panel shows that Next.js returns visually complete
    HTML when a page is requested.
  </figcaption>
</figure>

  Check out [Server Rendering](/rendering-on-the-web/#server-rendering)
  to learn how server-side rendering often results in a better experience for users.

These are only a few of the many features provided by Next.js automatically. Many
are customizable and can be modified for different use cases.

## What's next?

Pun intended 😛

Every other guide in this collection will explore a specific Next.js feature in detail:

* [Route prefetching](/route-prefetching-in-nextjs/) to speed up page navigations
* [Serving hybrid and AMP-only pages][amp] for faster loading from search engines
* [Code-splitting components with dynamic imports](/code-splitting-with-dynamic-imports-in-nextjs/)
  to reduce JavaScript footprints

[collection]: /react
[cra]: https://create-react-app.dev/
[ssr]: /rendering-on-the-web/#server-rendering
[amp]: /how-amp-can-guarantee-fastness-in-your-nextjs-app


# Precaching in Create React App with Workbox


  If you don't yet understand the basic idea behind service workers and
  precaching, read the [Precaching with Workbox](/precache-with-workbox) guide
  first.

[`Workbox`](https://developer.chrome.com/docs/workbox/) is built into
Create React App (CRA) with a default configuration that precaches all the
static assets in your application with every build.

<figure>
  

*Requests/responses with service worker*

</figure>

## Why is this useful?

Service workers enable you to store important resources in its cache
(_precaching_) so that when a user loads the web page for a second time, the
browser can retrieve them from the service worker instead of making requests to
the network. This results in faster page loads on repeat visits as well as in the
ability to surface content when the user is offline.

## Workbox in CRA

**Workbox** is a collection of tools that allow you create and maintain service
workers. In CRA, the
[`workbox-webpack-plugin`](https://developer.chrome.com/docs/workbox/modules/workbox-webpack-plugin/)
is already included into the production build and only needs to be enabled in
the `src/index.js` file in order to register a new service worker with every
build:

```js/8/7
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(<App />, document.getElementById('root'));

serviceWorker.unregister();
serviceWorker.register();
```

Here is an example of a React app built with CRA that has a service worker enabled through this file:

https://glitch.com/edit/#!/react-sw-example

To see which assets are being cached:

You'll notice that instead of showing the payload size, the `Size` column shows
a `(from ServiceWorker)` message to indicate that these resources were retrieved
from the service worker.

*Network requests with a service worker*

Since the service worker caches all static assets, try to use the application
while offline:

1.  In the **Network** tab in DevTools, enable the **Offline** checkbox to
   simulate an offline experience.

The application works in exactly the same way, even without a network
connection!

## Modifying caching strategies

The default precaching strategy used by Workbox in CRA is **cache-first**, where
all static assets are fetched from the service worker cache and if that fails
(if the resource is not cached for example), the network request is made. This
is how content can still be served to users even when they are in a complete
offline state.

Although Workbox provides support to define different strategies and approaches
to caching static and dynamic resources, the default configuration in CRA cannot
be modified or overwritten unless you eject entirely. However, there is an
[open proposal](https://github.com/facebook/create-react-app/issues/5359)
to explore adding support for an external `workbox.config.js` file. This
would allow developers to override the default settings by just creating a
single `workbox.config.js` file.

For more details on all the caching strategies that a service worker can use,
take a look at the
[Offline Cookbook](/offline-cookbook/).

## Handling a cache-first strategy

Relying on the service worker cache first and then falling back to the network
is an excellent way to build sites that load faster on subsequent visits and
work offline to some extent. However, there are a few things that need to
be taken into consideration:

+  How can caching behaviors by a service worker be tested?
+  Should there be a message for users to let them know they are looking at
   cached content?

[The CRA
documentation](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app#offline-first-considerations)
explains these points, and more, in detail.

## Conclusion

Use a service worker to precache important resources in your application to
provide a faster experience for your users as well as offline support.

1. If you are using CRA, enable the pre-configured service worker in
   `src/index.js`.
2. If you are not using CRA to build a React application, include one of the
   many libraries Workbox provides, such as `workbox-webpack-plugin`, into your
   build process.
3. Keep an eye out for when CRA will support a `workbox.config.js` override file
   in this
   [GitHub issue](https://github.com/facebook/create-react-app/issues/5359).


# Pre-render routes with react-snap

[`react-snap`](https://github.com/stereobooster/react-snap) is a third-party
library that pre-renders pages on your site into static HTML files. This can
improve
[First Paint](/user-centric-performance-metrics/#important-metrics-to-measure)
times in your application.

Here's a comparison of the same application with and without pre-rendering
loaded on a simulated 3G connection and mobile device:

<figure>
  

*A side by side loading comparison. The version using pre-rendering loads 4.2 seconds faster.*

</figure>

  `react-snap` is not the only library that can pre-render static HTML content
  for your React application.
  [`react-snapshot`](https://github.com/geelen/react-snapshot)
  is another alternative.

## Why is this useful?

The main performance problem with large single-page applications is that the
user needs to wait for the JavaScript bundle(s) that make up the site to finish
downloading before they can see any real content. The larger the bundles, the
longer the user will have to wait.

To solve this, many developers take the approach of rendering the application on
the server instead of only booting it up on the browser. With each
page/route transition, the complete HTML is generated on the server and sent to
the browser, which reduces First Paint times but comes at the cost of a slower
Time to First Byte.

**Pre-rendering** is a separate technique that is less complex than server
rendering, but also provides a way to improve First Paint times in your
application. A headless browser, or a browser without a user interface, is used
to generate static HTML files of every route during _build time_. These files
can then be shipped along with the JavaScript bundles that are needed for the
application.

## react-snap

`react-snap` uses [Puppeteer](https://github.com/GoogleChrome/puppeteer) to
create pre-rendered HTML files of different routes in your application. To
begin, install it as a development dependency:

```bash
npm install --save-dev react-snap
```

Then add a `postbuild` script in your `package.json`:

```json
"scripts": {
  //...
  "postbuild": "react-snap"
}
```

This would automatically run the `react-snap` command every time a new build of
the applications made (`npm build`).

  `npm` supports _pre_ and _post_ commands for main and arbitrary scripts which
  will always run directly before or after the original script respectively. You
  can learn more in the
  [npm documentation](https://docs.npmjs.com/misc/scripts).

The last thing you will need to do is change how the application is booted.
Change the `src/index.js` file to the following:

```js/6,8-12/5
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));
const rootElement = document.getElementById("root");

if (rootElement.hasChildNodes()) {
  ReactDOM.hydrate(<App />, rootElement);
} else {
  ReactDOM.render(<App />, rootElement);
}
```

Instead of only using `ReactDOM.render` to render the root React element
directly into the DOM, this checks to see if any child nodes are already present
to determine whether HTML contents were pre-rendered (or rendered on the
server). If that's the case, `ReactDOM.hydrate` is used instead to attach event
listeners to the already created HTML instead of creating it anew.

Building the application will now generate static HTML files as payloads for
each route that is crawled. You can take a look at what the HTML payload looks
like by clicking the URL of the HTML request and then clicking the **Previews**
tab within Chrome DevTools.

*A before and after comparison. The after shot shows content has rendered.*

  `react-snap` can be used for other frameworks than React! This includes Vue
  and Preact. More instructions about this can be found in the
  [`react-snap` README](https://github.com/stereobooster/react-snap).

## Flash of unstyled content

Although static HTML is now rendered almost immediately, it still remains
unstyled by default which may cause the issue of showing a "flash of unstyled
content" (FOUC). This can be especially noticeable if you are using a CSS-in-JS
library to generate selectors since the JavaScript bundle will have to finish
executing before any styles can be applied.

To help prevent this, the **critical** CSS, or the minimum amount of CSS that is
needed for the initial page to render, can be inlined directly to the `<head>`
of the HTML document. `react-snap` uses another third-party library under the
hood, [`minimalcss`](https://github.com/peterbe/minimalcss), to extract any
critical CSS for different routes. You can enable this by specifying the
following in your `package.json` file:

```json
"reactSnap": {
  "inlineCss": true
}
```

Taking a look at the response preview in Chrome DevTools will now show the styled page with critical CSS inlined.

*A before and after comparison. The after shot shows content has rendered and is styled because of inlined critical CSS.*

  The `inlineCSS` option is still experimental. It is worth double-checking to
  make sure styles are being applied correctly for your routes.

### Conclusion

If you are not server-side rendering routes in your application, use
`react-snap` to pre-render static HTML to your users.

1. Install it as a development dependency and begin with just the default
   settings.
2. Use the experimental `inlineCss` option to inline critical CSS if it works
   for your site.
3. If you are using code splitting on a component level within any routes, be
   careful not to pre-render a loading state to your users. The
   [`react-snap` README](https://github.com/stereobooster/react-snap#async-components)
   covers this in more detail.


# Speed up navigations in React with Quicklink

[Prefetching](/link-prefetch/) is a technique to speed up navigations by downloading the resources for the next page, ahead of time. [Quicklink](https://github.com/GoogleChromeLabs/quicklink) is a library that allows you to implement this technique at scale, by automatically prefetching links as they come into the view.

In multi-page apps the library prefetches documents (e.g. `/article.html`), for in-viewport links, so that when the user clicks on these links they can be picked up from the [HTTP cache](/http-cache/).

[Single-page apps](https://en.wikipedia.org/wiki/Single-page_application) commonly use a technique called [route-based code splitting](/reduce-javascript-payloads-with-code-splitting/). This allows the site to load the code for a given route only when the user navigates to it. These files (JS, CSS) are commonly referred to as "chunks".

With that said, in these sites, instead of prefetching documents the biggest performance gains come from prefetching these chunks before the page needs them.

Achieving this presents some challenges:

- It's not trivial to determine which chunks (e.g. `article.chunk.js`) are associated with a given route (e.g. `/article`) before landing on it.
- The final URL names of these chunks can't be predicted, as modern module bundlers typically use long-term hashing for versioning (e.g. `article.chunk.46e51.js`).

This guide explains how Quicklink solves these challenges and allows you to achieve prefetching at scale in React single page apps.

At the moment this solution is only compatible with [react-router](https://www.npmjs.com/package/react-router).

  Check out the [Prefetching in create-react-app with Quicklink](/codelab-quicklink/)
  codelab for a guided, hands-on demonstration of Quicklink.

## Determine chunks associated with each route

One of the core components of `quicklink` is [webpack-route-manifest](https://github.com/lukeed/webpack-route-manifest), a [webpack](https://webpack.js.org/) plugin that lets you generate a JSON dictionary of routes and chunks.
This allows the library to know which files are going to be needed by each route of the application and prefetch them as the routes come into the view.

After [integrating the plugin](https://github.com/lukeed/webpack-route-manifest#install) with the project, it will produce a JSON manifest file associating each route with its corresponding chunks:

```javascript
{
  '/about': [
    {
      type: 'style',
      href: '/static/css/about.f6fd7d80.chunk.css',
    },
    {
      type: 'script',
      href: '/static/js/about.1cdfef3b.chunk.js',
    },
  ],
  '/blog': [
    {
      type: 'style',
      href: '/static/css/blog.85e80e75.chunk.css',
    },
    {
      type: 'script',
      href: '/static/js/blog.35421503.chunk.js',
    },
  ],
}
```

This manifest file can be requested in two ways:

- By URL, e.g. `https://site_url/rmanifest.json`.
- Through the window object, at `window.__rmanifest`.

## Prefetch chunks for in-viewport routes

Once the manifest file is available, the next step is to install Quicklink by running `npm install quicklink`.

Then, the [higher order component (HOC)](https://reactjs.org/docs/higher-order-components.html) `withQuicklink()` can be used to indicate that a given route should be prefetched when the link comes into the view.

The following code belongs to an `App` component of a React app that renders a top menu with four links:

```jsx
const App = () => (
  <div className={style.app}>
    <Hero />
    <main className={style.wrapper}>
      <Suspense fallback={<div>Loading…</div>}>
        <Route path="/" exact component={Home} />
        <Route path="/blog" exact component={Blog} />
        <Route path="/blog/:title" component={Article} />
        <Route path="/about" exact component={About} />
      </Suspense>
    </main>
    <Footer />
  </div>
);
```

To tell Quicklink that these routes should be prefetched as they come into the view:

1. Import the `quicklink` HOC at the beginning of the component.
1. Wrap each route with the `withQuicklink()` HOC, passing the page component and options parameter to it.

```html
const options = {
  origins: [],
};
const App = () => (
  <div className={style.app}>
    <Hero />
    <main className={style.wrapper}>
      <Suspense fallback={<div>Loading…</div>}>
        <Route path="/" exact component={withQuicklink(Home, options)} />
        <Route path="/blog" exact component={withQuicklink(Blog, options)} />
        <Route
          path="/blog/:title"
          component={withQuicklink(Article, options)}
        />
        <Route path="/about" exact component={withQuicklink(About, options)} />
      </Suspense>
    </main>
    <Footer />
  </div>
);
```

The `withQuicklink()` HOC uses the path of the route as a key to obtain its associated chunks from `rmanifest.json`.
Under the hood, as links come into the view, the library injects a `<link rel="prefetch">` tag in the page for each chunk so they can be prefetched.
Prefetched resources will be requested at the lowest priority by the browser and kept in the [HTTP Cache](/http-cache/) for 5 minutes, after which point, the `cache-control` rules of the resource apply.
As a result of this, when a user clicks on a link and moves to a given route, the chunks will be retrieved from the cache, greatly improving the time it takes to render that route.

## Conclusion

Prefetching can greatly improve load times for future navigations. In React single-page apps, this can be achieved by loading the chunks associated with each route, before the user lands in them.
Quicklink's solution for React SPA uses `webpack-route-manifest` to create a map of routes and chunks, in order to determine which files to prefetch, when a link comes into the view.
Implementing this technique throughout your site can greatly improve navigations to the point of making them appear instant.


# Route prefetching in Next.js

In this post you'll learn how routing in Next.js works, how it's optimized for speed, and how to customize it to best fit your needs.

## The `<Link>` component

In [Next.js](https://nextjs.org/), you don't need to set up routing manually.
Next.js uses file-system-based routing, which lets you just create files and folders
inside the `./pages/` directory:

<figure>

*Screenshot of the pages directory containting three files: index.js, margherita.js, and pineapple-pizza.js.*

</figure>

To link to different pages, use the
[`<Link>`](https://nextjs.org/docs/api-reference/next/link) component, similarly to how you'd
use the good old `<a>` element:

```js
<Link href="/margherita">
  <a>Margherita</a>
</Link>
```

When you use the `<Link>` component for navigation, Next.js does a little bit
more for you. Normally, a page is downloaded when you follow a link to it, but
Next.js automatically prefetches the JavaScript needed to render the page.

When you load a page with a few links, odds are that by the time you follow
a link, the component behind it has already been fetched. This improves
application responsiveness by making navigations to new pages quicker.

In the example app below, the `index.js` page links to `margherita.js` with a
`<Link>`:

https://glitch.com/edit/#!/nextjs-prefetching

Use Chrome DevTools to verify that `margherita.js` is prefetched:

When you load `index.js`, the **Network** tab shows that `margherita.js` is
downloaded too:

*DevTools Network tab with margherita.js highlighted.*

## How automatic prefetching works

Next.js prefetches only links that appear in the viewport and uses the [Intersection
Observer API](https://developer.mozilla.org/docs/Web/API/Intersection_Observer_API)
to detect them. It also disables prefetching when the network connection is slow
or when users have
[`Save-Data`](https://developer.mozilla.org/docs/Web/HTTP/Headers/Save-Data)
turned on. Based on these checks, Next.js dynamically injects [`<link
rel="preload">`](/preload-critical-assets/) tags to download components for
subsequent navigations.

Next.js only *fetches* the JavaScript; it doesn't execute it. That way, it's not
downloading any additional content that the prefetched page might request until you visit
the link.

 Glitch examples are running in production mode because prefetching depends on the browsing conditions and it's enabled only in optimized production builds. To switch to development mode,
check the `README.md` in Glitch examples. 

 Because `<link rel="preload">` requests resources with high
priority, the browser expects them to be used right away, which triggers
Console warnings. [Fetch Priority](/fetch-priority/) will
is available in Chrome, which will allow Next.js to indicate lower
priority for resources that are not needed immediately with `<link rel="preload"
fetchpriority="low">`. 

## Avoid unnecessary prefetching

To avoid downloading unnecessary content, you can disable prefetching for rarely
visited pages by setting the `prefetch` property on `<Link>` to `false`:

```js
<Link href="/pineapple-pizza" prefetch={false}>
  <a>Pineapple pizza</a>
</Link>
```

In this second example app, the `index.js` page has a `<Link>` to
`pineapple-pizza.js` with `prefetch` set to `false`:

https://glitch.com/edit/#!/nextjs-noprefetch

To inspect the network activity, follow the steps from the first example. When
you load `index.js`, the DevTools **Network** tab shows that `margherita.js` is
downloaded, but `pineapple-pizza.js` is not:

*DevTools Network tab with margherita.js highlighted.*

## Prefetching with custom routing

The `<Link>` component is suitable for most use cases, but you can also build
your own component to do routing. Next.js makes this easy for you with the
router API available in [`next/router`](https://nextjs.org/docs/api-reference/next/router#userouter).
If you want to do something (for example, submit a form) before navigating to a new
route, you can define that in your custom routing code.

When you use custom components for routing, you can add prefetching to them too.
To implement prefetching in your routing code, use the `prefetch` method from
`useRouter`.

Take a look at `components/MyLink.js` in this example app:

https://glitch.com/edit/#!/custom-routing-nextjs

Prefetching is done inside the
[`useEffect`](https://reactjs.org/docs/hooks-effect.html) hook. If the
`prefetch` property on a `<MyLink>` is set to `true`, the route specified in the
`href` property gets prefetched when that `<MyLink>` is rendered:

```js
useEffect(() => {
    if (prefetch) router.prefetch(href)
});
```

When you click the link, the routing is done in `handleClick`. A message gets
logged to the console, and the `push` method navigates to the new route
specified in `href`:

```js
const handleClick = e => {
    e.preventDefault();
    console.log("Having fun with Next.js.");
    router.push(href);
};

```

In this example app, the `index.js` page has a `<MyLink>` to `margherita.js` and
`pineapple-pizza.js`. The `prefetch` property is set to `true` on `/margherita`
and to `false` on `/pineapple-pizza`.

```js
<MyLink href="/margherita" title="Margherita" prefetch={true} />
<MyLink href="/pineapple-pizza"  title="Pineapple pizza" prefetch={false} />
```

When you load `index.js`, the **Network** tab shows that `margherita.js` is
downloaded and `pineapple-pizza.js` is not:

*DevTools Network tab with margherita.js highlighted.*

When you click on either link, the **Console** logs "Having fun with Next.js."
and navigates to the new route:

*DevTools Console displaying the message 'Having fun with Next.js.'*

## Conclusion

When you use `<Link>`, Next.js automatically prefetches the JavaScript needed to
render the linked page, which makes navigating to new pages faster. If you are
using custom routing, you can use the Next.js router API to implement
prefetching yourself. Avoid downloading content unnecessarily by disabling
prefetching for rarely visited pages.


# Virtualize large lists with react-window

[`react-window`](https://react-window.now.sh/#/examples/list/fixed-size) is a
library that allows large lists to be rendered efficiently.

Here's an example of a list that contains 1000 rows being rendered with
`react-window`. Try scrolling as fast you can.

https://glitch.com/edit/#!/react-window-fixed

## Why is this useful?

There may be times where you need to display a large table or list that contains
many rows. Loading every single item on such a list can affect performance
significantly.

**List virtualization**, or "windowing", is the concept of only rendering what
is visible to the user. The number of elements that are rendered at first is a
very small subset of the entire list and the "window" of visible content _moves_
when the user continues to scroll. This improves both the rendering and
scrolling performance of the list.

<figure>
  

*Window of content in a virtualized list*

  <figcaption>
    Moving "window" of content in a virtualized list
  </figcaption>
</figure>

DOM nodes that exit the "window" are recycled, or immediately replaced with
newer elements as the user scrolls down the list. This keeps the number of all
rendered elements specific to the size of the window.

## react-window

`react-window` is a small, third-party library that makes it easier to
create virtualized lists in your application. It provides a number of base APIs
that can be used for different types of lists and tables.

### When to use fixed size lists

Use the `FixedSizeList` component if you have a long, one-dimensional list
of equally sized items.

```jsx
import React from 'react';
import { FixedSizeList } from 'react-window';

const items = [...] // some list of items

const Row = ({ index, style }) => (
  <div style={style}>
     {/* define the row component using items[index] */}
  </div>
);

const ListComponent = () => (
  <FixedSizeList
    height={500}
    width={500}
    itemSize={120}
    itemCount={items.length}
  >
    {Row}
  </FixedSizeList>
);

export default ListComponent;
```

* The `FixedSizeList` component accepts a `height`, `width` and `itemSize` prop
  to control the size of the items within the list.
* A function that renders the rows is passed as a child to `FixedSizeList`.
  Details about the particular item can be accessed with the `index` argument
  (`items[index]`).
* A `style` parameter is also passed in to the row rendering method that
  **must** be attached to the row element. List items are absolutely positioned
  with their height and width values assigned inline, and the `style` parameter
  is responsible for this.

Do not assign `height` and `width` properties to the list or the list item with
an external CSS file. They would be ignored due to the fact that these style
attributes are applied inline.

The Glitch example shown earlier in this article shows an example of a
`FixedSizeList` component.

### When to use variable sized lists

Use the `VariableSizeList` component to render a list of items that have
different sizes. This component works in the same way as a fixed size list, but
instead expects a function for the `itemSize` prop instead of a specific value.

```jsx
import React from 'react';
import { VariableSizeList } from 'react-window';

const items = [...] // some list of items

const Row = ({ index, style }) => (
  <div style={style}>
     {/* define the row component using items[index] */}
  </div>
);

const getItemSize = index => {
  // return a size for items[index]
}

const ListComponent = () => (
  <VariableSizeList
    height={500}
    width={500}
    itemCount={items.length}
    itemSize={getItemSize}
  >
    {Row}
  </VariableSizeList>
);

export default ListComponent;
```

The following embed shows an example of this component.

https://glitch.com/edit/#!/react-window-variable

The item size function passed to the `itemSize` prop randomizes the row heights
in this example. In a real application however, there should be actual logic
defining the sizes of each item. Ideally, these sizes should be calculated based
on data or obtained from an API.

Both `FixedSizeList` and `VariableSizeList` components support horizontal lists
by using a `layout="horizontal"` prop. Take a look at the
[documentation](https://react-window.now.sh/#/examples/list/fixed-size) to see
an example.

### Grids

`react-window` also provides support for virtualizing multi-dimensional lists,
or grids. In this context, the "window" of visible content changes as the user
scrolls horizontally **and** vertically.

<figure>
  

*Moving window of content in a virtualized grid is two-dimensional*

  <figcaption>
    Moving "window" of content in a virtualized grid is two-dimensional
  </figcaption>
</figure>

Similarly, both `FixedSizeGrid` and `VariableSizeGrid` components can be used
depending on whether the size of specific list items can vary.

* For `FixedSizeGrid`, the API is about the same but with the fact that heights,
  widths and item counts need to be represented for both columns and rows.
* For `VariableSizeGrid`, both the column widths and row heights can be changed
  by passing in functions instead of values to their respective props.

Take a look at the
[documentation](https://react-window.now.sh/#/examples/grid/fixed-size) to see
examples of virtualized grids.

  Aside from providing the base components to create efficient lists and grids,
  `react-window` also provides other capabilities such as scrolling to a
  specific item or providing an indicator when the user is scrolling. The
  [documentation](https://react-window.now.sh/#/examples/list/scrolling-indicators)
  provides examples for this.

## Lazy loading on scroll

Many websites improve performance by waiting to load and render items in a long
list until the user has scrolled down. This technique, commonly referred to as
"infinite loading", adds new DOM nodes into the list as the user scrolls past a
certain threshold close to the end. Although this is better than loading all
items on a list at once, it still ends up populating the DOM with thousands of
row entries if the user has scrolled past that many. This can lead to an
excessively large DOM size, which starts to impact performance by making style
calculations and DOM mutations slower.

The following diagram might help summarize this:

<figure>
  

*Difference in scrolling between a regular and virtualized list*

  <figcaption>
    Difference in scrolling between a regular and virtualized list
  </figcaption>
</figure>

The best approach to solve this problem is continue to use a library like
`react-window` to maintain a small "window" of elements on a page, but to also
lazy load newer entries as the user scrolls down. A separate package,
`react-window-infinite-loader`, makes this possible with `react-window`.

Consider the following piece of code which shows an example of state that is
managed in a parent `App` component.

```jsx
import React, { Component } from 'react';

import ListComponent from './ListComponent';

class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      items: [], // instantiate initial list here
      moreItemsLoading: false,
      hasNextPage: true
    };

    this.loadMore = this.loadMore.bind(this);
  }

  loadMore() {
   // method to fetch newer entries for the list
  }

  render() {
    const { items, moreItemsLoading, hasNextPage } = this.state;

    return (
      <ListComponent
        items={items}
        moreItemsLoading={moreItemsLoading}
        loadMore={this.loadMore}
        hasNextPage={hasNextPage}
      />
    );
  }
}

export default App;
```

A `loadMore` method is passed into a child `ListComponent` that contains the
infinite loader list. This is important because the infinite loader needs to
fire a callback to load more items once the user has scrolled past a certain
point.

Here's how the `ListComponent` that renders the list can look like:

```jsx
import React from 'react';
import { FixedSizeList } from 'react-window';
import InfiniteLoader from "react-window-infinite-loader";

const ListComponent = ({ items, moreItemsLoading, loadMore, hasNextPage }) => {
  const Row = ({ index, style }) => (
     {/* define the row component using items[index] */}
  );

  const itemCount = hasNextPage ? items.length + 1 : items.length;

  return (
    <InfiniteLoader
      isItemLoaded={index => index < items.length}
      itemCount={itemCount}
      loadMoreItems={loadMore}
    >
      {({ onItemsRendered, ref }) => (
        <FixedSizeList
          height={500}
          width={500}
          itemCount={itemCount}
          itemSize={120}
          onItemsRendered={onItemsRendered}
          ref={ref}
        >
          {Row}
        </FixedSizeList>
      )}
  </InfiniteLoader>
  )
};

export default ListComponent;
```

In here, the `FixedSizeList` component is wrapped within the `InfiniteLoader`.
The props assigned to the loader are:

* `isItemLoaded`: Method that checks whether a certain item has loaded
* `itemCount`: Number of items on the list (or expected)
* `loadMoreItems`: Callback that returns a promise that resolves to additional
  data for the list

A
[render prop](https://reactjs.org/docs/render-props.html#using-props-other-than-render)
is used to return a function that the list component uses in order to render.
Both `onItemsRendered` and `ref` attributes are attributes that need to be
passed in.

The following is an example of how infinite loading can work with a virtualized
list.

https://glitch.com/edit/#!/react-window-infinite

Scrolling down the list might feel the same, but a request is now made to
retrieve 10 users from a [random user API](https://randomuser.me/) every time you
scroll close to the end of the list. This is all done while only rendering a
single "window" of results at at a time.

By checking the `index` of a certain item, a different loading state can be
shown for an item depending on whether a request has been made for newer entries
and the item is still loading.

For example:

```js
const Row = ({ index, style }) => {
  const itemLoading = index === items.length;

  if (itemLoading) {
      // return loading state
  } else {
      // return item
  }
};
```

## Overscanning

Since items in a virtualized list only change when the user scrolls, blank
space can briefly flash as newer entries are about to be displayed. You can
try quickly scrolling any of the previous examples in this guide to notice
this.

To improve the user experience of virtualized lists, `react-window` allows
you to overscan items with the `overscanCount` property. This allows you to
define how many items outside of the visible "window" to render at all times.

```jsx
<FixedSizeList
  //...
  overscanCount={4}
>
  {...}
</FixedSizeList>
```

`overscanCount` works for both the `FixedSizeList` and `VariableSizeList`
components and has a default value of 1. Depending on how large a list is
as well as the size of each item, overscanning more than just one entry can
help prevent a noticeable flash of empty space when the user scrolls. However,
overscanning too many entries can affect performance negatively. The whole
point of using a virtualized list is to minimize the number of entries to what
the user can see at any given moment, so try to keep the number of overscanned
items as low as possible.

For `FixedSizeGrid` and `VariableSizeGrid`, use the `overscanColumnsCount` and
`overscanRowsCount` properties to control the number of columns and rows to
overscan respectively.

## Conclusion

If you are unsure where to begin virtualizing lists and tables in your
application, follow these steps:

1. Measure rendering and scrolling performance. This
   [article](https://addyosmani.com/blog/react-window/) shows how the [FPS
   meter](https://developer.chrome.com/docs/devtools/evaluate-performance/#analyze_frames_per_second)
   in Chrome DevTools can be used to explore how efficiently items are rendered
   on a list.
2. Include `react-window` for any long lists or grids that are affecting
   performance.
3. If there are certain features not supported in `react-window`, consider using
   [`react-virtualized`](https://github.com/bvaughn/react-virtualized) if you
   cannot add this functionality yourself.
4. Wrap your virtualized list with `react-window-infinite-loader` if you need to
   lazy load items as the user scrolls.
5. Use the `overscanCount` property for your lists and the
   `overscanColumnsCount` and `overscanRowsCount` properties for your grids
   to prevent a flash of empty content. Do not overscan too many entries as
   this will affect performance negatively.