1 | [![Next.js](https://assets.zeit.co/image/upload/v1538361091/repositories/next-js/next-js.png)](https://nextjs.org)
|
2 |
|
3 | <p align="center">
|
4 | <a aria-label="ZEIT logo" href="https://github.com/zeit">
|
5 | <img src="https://img.shields.io/badge/MADE%20BY%20ZEIT-000000.svg?style=for-the-badge&logo=ZEIT&labelColor=000000&logoWidth=20">
|
6 | </a>
|
7 | <a aria-label="NPM version" href="https://www.npmjs.com/package/next">
|
8 | <img alt="" src="https://img.shields.io/npm/v/next.svg?style=for-the-badge&labelColor=000000">
|
9 | </a>
|
10 | <a aria-label="License" href="https://github.com/zeit/next.js/blob/canary/license.md">
|
11 | <img alt="" src="https://img.shields.io/npm/l/next.svg?style=for-the-badge&labelColor=000000">
|
12 | </a>
|
13 | <a aria-label="join us in spectrum" href="https://spectrum.chat/next-js">
|
14 | <img alt="" src="https://img.shields.io/badge/Join%20the%20community-blueviolet.svg?style=for-the-badge&logo=Next.js&labelColor=000000&logoWidth=20">
|
15 | </a>
|
16 | </p>
|
17 |
|
18 | <p align="center">
|
19 | <strong>
|
20 | Visit <a aria-label="next.js learn" href="https://nextjs.org/learn">https://nextjs.org/learn</a> to get started with Next.js.
|
21 | </strong>
|
22 | </p>
|
23 |
|
24 | ---
|
25 |
|
26 | **The below readme is the documentation for the `canary` (prerelease) branch. To view the documentation for the latest stable Next.js version visit [nextjs.org/docs](https://nextjs.org/docs).**
|
27 |
|
28 | ---
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 | - [How to use](#how-to-use)
|
35 | - [Setup](#setup)
|
36 | - [Quick Start](#quick-start)
|
37 | - [Manual Setup](#manual-setup)
|
38 | - [Automatic code splitting](#automatic-code-splitting)
|
39 | - [CSS](#css)
|
40 | - [Built-in CSS support](#built-in-css-support)
|
41 | - [CSS-in-JS](#css-in-js)
|
42 | - [Importing CSS / Sass / Less / Stylus files](#importing-css--sass--less--stylus-files)
|
43 | - [Static file serving (e.g.: images)](#static-file-serving-eg-images)
|
44 | - [Dynamic Routing](#dynamic-routing)
|
45 | - [Populating `<head>`](#populating-head)
|
46 | - [Fetching data and component lifecycle](#fetching-data-and-component-lifecycle)
|
47 | - [Routing](#routing)
|
48 | - [With `<Link>`](#with-link)
|
49 | - [With URL object](#with-url-object)
|
50 | - [Replace instead of push url](#replace-instead-of-push-url)
|
51 | - [Using a component that supports `onClick`](#using-a-component-that-supports-onclick)
|
52 | - [Forcing the Link to expose `href` to its child](#forcing-the-link-to-expose-href-to-its-child)
|
53 | - [Disabling the scroll changes to top on page](#disabling-the-scroll-changes-to-top-on-page)
|
54 | - [Imperatively](#imperatively)
|
55 | - [Intercepting `popstate`](#intercepting-popstate)
|
56 | - [With URL object](#with-url-object-1)
|
57 | - [Router Events](#router-events)
|
58 | - [Shallow Routing](#shallow-routing)
|
59 | - [useRouter](#userouter)
|
60 | - [Using a Higher Order Component](#using-a-higher-order-component)
|
61 | - [Prefetching Pages](#prefetching-pages)
|
62 | - [With `<Link>`](#with-link-1)
|
63 | - [Imperatively](#imperatively-1)
|
64 | - [API Routes](#api-routes)
|
65 | - [Dynamic routes support](#dynamic-routes-support)
|
66 | - [API Middlewares](#api-middlewares)
|
67 | - [Helper Functions](#helper-functions)
|
68 | - [Custom server and routing](#custom-server-and-routing)
|
69 | - [Disabling file-system routing](#disabling-file-system-routing)
|
70 | - [Dynamic assetPrefix](#dynamic-assetprefix)
|
71 | - [Changing x-powered-by](#changing-x-powered-by)
|
72 | - [Dynamic Import](#dynamic-import)
|
73 | - [Basic Usage (Also does SSR)](#basic-usage-also-does-ssr)
|
74 | - [With named exports](#with-named-exports)
|
75 | - [With Custom Loading Component](#with-custom-loading-component)
|
76 | - [With No SSR](#with-no-ssr)
|
77 | - [Custom `<App>`](#custom-app)
|
78 | - [Custom `<Document>`](#custom-document)
|
79 | - [Customizing `renderPage`](#customizing-renderpage)
|
80 | - [Custom error handling](#custom-error-handling)
|
81 | - [Reusing the built-in error page](#reusing-the-built-in-error-page)
|
82 | - [Custom configuration](#custom-configuration)
|
83 | - [Setting a custom build directory](#setting-a-custom-build-directory)
|
84 | - [Disabling etag generation](#disabling-etag-generation)
|
85 | - [Configuring the onDemandEntries](#configuring-the-ondemandentries)
|
86 | - [Configuring extensions looked for when resolving pages in `pages`](#configuring-extensions-looked-for-when-resolving-pages-in-pages)
|
87 | - [Configuring the build ID](#configuring-the-build-id)
|
88 | - [Configuring next process script](#configuring-next-process-script)
|
89 | - [Customizing webpack config](#customizing-webpack-config)
|
90 | - [Customizing babel config](#customizing-babel-config)
|
91 | - [Exposing configuration to the server / client side](#exposing-configuration-to-the-server--client-side)
|
92 | - [Build-time configuration](#build-time-configuration)
|
93 | - [Runtime configuration](#runtime-configuration)
|
94 | - [Starting the server on alternative hostname](#starting-the-server-on-alternative-hostname)
|
95 | - [CDN support with Asset Prefix](#cdn-support-with-asset-prefix)
|
96 | - [Automatic Static Optimization](#automatic-static-optimization)
|
97 | - [Automatic Static Optimization Indicator](#automatic-static-optimization-indicator)
|
98 | - [Production deployment](#production-deployment)
|
99 | - [Compression](#compression)
|
100 | - [Serverless deployment](#serverless-deployment)
|
101 | - [One Level Lower](#one-level-lower)
|
102 | - [Summary](#summary)
|
103 | - [Browser support](#browser-support)
|
104 | - [TypeScript](#typescript)
|
105 | - [Exported types](#exported-types)
|
106 | - [AMP Support](#amp-support)
|
107 | - [Enabling AMP Support](#enabling-amp-support)
|
108 | - [AMP First Page](#amp-first-page)
|
109 | - [Hybrid AMP Page](#hybrid-amp-page)
|
110 | - [AMP Page Modes](#amp-page-modes)
|
111 | - [AMP Behavior with `next export`](#amp-behavior-with-next-export)
|
112 | - [Adding AMP Components](#adding-amp-components)
|
113 | - [AMP Validation](#amp-validation)
|
114 | - [TypeScript Support](#typescript-support)
|
115 | - [Static HTML export](#static-html-export)
|
116 | - [Usage](#usage)
|
117 | - [Limitation](#limitation)
|
118 | - [Multi Zones](#multi-zones)
|
119 | - [How to define a zone](#how-to-define-a-zone)
|
120 | - [How to merge them](#how-to-merge-them)
|
121 | - [FAQ](#faq)
|
122 | - [Contributing](#contributing)
|
123 | - [Authors](#authors)
|
124 |
|
125 |
|
126 |
|
127 | ## How to use
|
128 |
|
129 | ### Setup
|
130 |
|
131 | #### Quick Start
|
132 |
|
133 | ```bash
|
134 | npx create-next-app
|
135 | ```
|
136 |
|
137 | _([npx](https://medium.com/@maybekatz/introducing-npx-an-npm-package-runner-55f7d4bd282b) comes with npm 5.2+ and higher, see [instructions for older npm versions](https://gist.github.com/timer/833d9946fa8a05ba855729d05a38ac23))_
|
138 |
|
139 | #### Manual Setup
|
140 |
|
141 | Install it in your project:
|
142 |
|
143 | ```bash
|
144 | npm install --save next react react-dom
|
145 | ```
|
146 |
|
147 | and add a script to your package.json like this:
|
148 |
|
149 | ```json
|
150 | {
|
151 | "scripts": {
|
152 | "dev": "next",
|
153 | "build": "next build",
|
154 | "start": "next start"
|
155 | }
|
156 | }
|
157 | ```
|
158 |
|
159 | After that, the file-system is the main API. Every `.js` file becomes a route that gets automatically processed and rendered.
|
160 |
|
161 | Populate `./pages/index.js` inside your project:
|
162 |
|
163 | ```jsx
|
164 | function Home() {
|
165 | return <div>Welcome to Next.js!</div>
|
166 | }
|
167 |
|
168 | export default Home
|
169 | ```
|
170 |
|
171 | and then just run `npm run dev` and go to `http://localhost:3000`. To use another port, you can run `npm run dev -- -p <your port here>`.
|
172 |
|
173 | So far, we get:
|
174 |
|
175 | - Automatic transpilation and bundling (with webpack and babel)
|
176 | - Hot code reloading
|
177 | - Server rendering and indexing of `./pages/`
|
178 | - Static file serving. `./public/` is mapped to `/` (given you [create a `./public/` directory](#static-file-serving-eg-images) inside your project)
|
179 |
|
180 | ### Automatic code splitting
|
181 |
|
182 | Every `import` you declare gets bundled and served with each page. That means pages never load unnecessary code!
|
183 |
|
184 | ```jsx
|
185 | import cowsay from 'cowsay-browser'
|
186 |
|
187 | function CowsayHi() {
|
188 | return <pre>{cowsay.say({ text: 'hi there!' })}</pre>
|
189 | }
|
190 |
|
191 | export default CowsayHi
|
192 | ```
|
193 |
|
194 | ### CSS
|
195 |
|
196 | #### Built-in CSS support
|
197 |
|
198 | <details>
|
199 | <summary><b>Examples</b></summary>
|
200 | <ul>
|
201 | <li><a href="/examples/basic-css">Basic css</a></li>
|
202 | </ul>
|
203 | </details>
|
204 |
|
205 | We bundle [styled-jsx](https://github.com/zeit/styled-jsx) to provide support for isolated scoped CSS. The aim is to support "shadow CSS" similar to Web Components, which unfortunately [do not support server-rendering and are JS-only](https://github.com/w3c/webcomponents/issues/71).
|
206 |
|
207 | ```jsx
|
208 | function HelloWorld() {
|
209 | return (
|
210 | <div>
|
211 | Hello world
|
212 | <p>scoped!</p>
|
213 | <style jsx>{`
|
214 | p {
|
215 | color: blue;
|
216 | }
|
217 | div {
|
218 | background: red;
|
219 | }
|
220 | @media (max-width: 600px) {
|
221 | div {
|
222 | background: blue;
|
223 | }
|
224 | }
|
225 | `}</style>
|
226 | <style global jsx>{`
|
227 | body {
|
228 | background: black;
|
229 | }
|
230 | `}</style>
|
231 | </div>
|
232 | )
|
233 | }
|
234 |
|
235 | export default HelloWorld
|
236 | ```
|
237 |
|
238 | Please see the [styled-jsx documentation](https://www.npmjs.com/package/styled-jsx) for more examples.
|
239 |
|
240 | #### CSS-in-JS
|
241 |
|
242 | <details>
|
243 | <summary>
|
244 | <b>Examples</b>
|
245 | </summary>
|
246 | <ul>
|
247 | <li><a href="/examples/with-styled-components">Styled components</a></li>
|
248 | <li><a href="/examples/with-styletron">Styletron</a></li>
|
249 | <li><a href="/examples/with-glamor">Glamor</a></li>
|
250 | <li><a href="/examples/with-cxs">Cxs</a></li>
|
251 | <li><a href="/examples/with-aphrodite">Aphrodite</a></li>
|
252 | <li><a href="/examples/with-fela">Fela</a></li>
|
253 | </ul>
|
254 | </details>
|
255 |
|
256 | It's possible to use any existing CSS-in-JS solution. The simplest one is inline styles:
|
257 |
|
258 | ```jsx
|
259 | function HiThere() {
|
260 | return <p style={{ color: 'red' }}>hi there</p>
|
261 | }
|
262 |
|
263 | export default HiThere
|
264 | ```
|
265 |
|
266 | To use more sophisticated CSS-in-JS solutions, you typically have to implement style flushing for server-side rendering. We enable this by allowing you to define your own [custom `<Document>`](#custom-document) component that wraps each page.
|
267 |
|
268 | #### Importing CSS / Sass / Less / Stylus files
|
269 |
|
270 | To support importing `.css`, `.scss`, `.less` or `.styl` files you can use these modules, which configure sensible defaults for server rendered applications.
|
271 |
|
272 | - [@zeit/next-css](https://github.com/zeit/next-plugins/tree/master/packages/next-css)
|
273 | - [@zeit/next-sass](https://github.com/zeit/next-plugins/tree/master/packages/next-sass)
|
274 | - [@zeit/next-less](https://github.com/zeit/next-plugins/tree/master/packages/next-less)
|
275 | - [@zeit/next-stylus](https://github.com/zeit/next-plugins/tree/master/packages/next-stylus)
|
276 |
|
277 | ### Static file serving (e.g.: images)
|
278 |
|
279 | Create a folder called `public` in your project root directory. From your code you can then reference those files starting from the baseURL `/`
|
280 |
|
281 | ```jsx
|
282 | function MyImage() {
|
283 | return <img src="/my-image.png" alt="my image" />
|
284 | }
|
285 |
|
286 | export default MyImage
|
287 | ```
|
288 |
|
289 | _Note: Don't name the `public` directory anything else. The name can't be changed and is the only directory that Next.js uses for serving static assets._
|
290 |
|
291 | ### Dynamic Routing
|
292 |
|
293 | <details>
|
294 | <summary><b>Examples</b></summary>
|
295 | <ul>
|
296 | <li><a href="/examples/dynamic-routing">Dynamic routing</a></li>
|
297 | </ul>
|
298 | </details>
|
299 |
|
300 | Defining routes by using predefined paths is not always enough for complex applications, in Next.js you can add brackets to a page (`[param]`) to create a dynamic route (a.k.a. url slugs, pretty urls, et al).
|
301 |
|
302 | Consider the following page `pages/post/[pid].js`:
|
303 |
|
304 | ```jsx
|
305 | import { useRouter } from 'next/router'
|
306 |
|
307 | const Post = () => {
|
308 | const router = useRouter()
|
309 | const { pid } = router.query
|
310 |
|
311 | return <p>Post: {pid}</p>
|
312 | }
|
313 |
|
314 | export default Post
|
315 | ```
|
316 |
|
317 | Any route like `/post/1`, `/post/abc`, etc will be matched by `pages/post/[pid].js`.
|
318 | The matched path parameter will be sent as a query parameter to the page.
|
319 |
|
320 | For example, the route `/post/abc` will have the following `query` object: `{ pid: 'abc' }`.
|
321 | Similarly, the route `/post/abc?foo=bar` will have the `query` object: `{ foo: 'bar', pid: 'abc' }`.
|
322 |
|
323 | > Note: Multiple dynamic route segments work the same way.
|
324 | >
|
325 | > For example, `pages/post/[pid]/[comment].js` would match `/post/1/a-comment`.
|
326 | > Its `query` object would be: `{ pid: '1', comment: 'a-comment' }`.
|
327 |
|
328 | A `<Link>` for `/post/abc` looks like so:
|
329 |
|
330 | ```jsx
|
331 | <Link href="/post/[pid]" as="/post/abc">
|
332 | <a>First Post</a>
|
333 | </Link>
|
334 | ```
|
335 |
|
336 | - `href`: the path inside `pages` directory.
|
337 | - `as`: the path that will be rendered in the browser URL bar.
|
338 |
|
339 | As `href` is a filesystem path, it shouldn't change at runtime, instead, you will probably need to change `as`
|
340 | dynamically according to your needs. Here's an example to create a list of links:
|
341 |
|
342 | ```jsx
|
343 | const pids = ['id1', 'id2', 'id3']
|
344 | {
|
345 | pids.map(pid => (
|
346 | <Link href="/post/[pid]" as={`/post/${pid}`}>
|
347 | <a>Post {pid}</a>
|
348 | </Link>
|
349 | ))
|
350 | }
|
351 | ```
|
352 |
|
353 | > You can [read more about `<Link>` here](#with-link).
|
354 |
|
355 | However, if a query and route param name are the same, route parameters will override the matching query params.
|
356 | For example, `/post/abc?pid=bcd` will have the `query` object: `{ pid: 'abc' }`.
|
357 |
|
358 | > **Note**: Predefined routes take precedence over dynamic routes.
|
359 | > For example, if you have `pages/post/[pid].js` and `pages/post/create.js`, the route `/post/create` will be matched by `pages/post/create.js` instead of the dynamic route (`[pid]`).
|
360 |
|
361 | > **Note**: Pages that are statically optimized by [automatic static optimization](#automatic-static-optimization) will be hydrated without their route parameters provided (`query` will be empty, i.e. `{}`).
|
362 | > After hydration, Next.js will trigger an update to your application to provide the route parameters in the `query` object.
|
363 | > If your application cannot tolerate this behavior, you can opt-out of static optimization by capturing the query parameter in `getInitialProps`.
|
364 |
|
365 | > **Note**: If deploying to [ZEIT Now](https://zeit.co/now) dynamic routes will work out-of-the-box.
|
366 | > You do not need to configure custom routes in a `now.json` file.
|
367 | >
|
368 | > If you are new to ZEIT Now, you can learn how to deploy a Next.js app to it in the [_Deploying a Next.js App_ Learn section](https://nextjs.org/learn/basics/deploying-a-nextjs-app).
|
369 |
|
370 | ### Populating `<head>`
|
371 |
|
372 | <details>
|
373 | <summary><b>Examples</b></summary>
|
374 | <ul>
|
375 | <li><a href="/examples/head-elements">Head elements</a></li>
|
376 | <li><a href="/examples/layout-component">Layout component</a></li>
|
377 | </ul>
|
378 | </details>
|
379 |
|
380 | We expose a built-in component for appending elements to the `<head>` of the page.
|
381 |
|
382 | ```jsx
|
383 | import Head from 'next/head'
|
384 |
|
385 | function IndexPage() {
|
386 | return (
|
387 | <div>
|
388 | <Head>
|
389 | <title>My page title</title>
|
390 | <meta name="viewport" content="initial-scale=1.0, width=device-width" />
|
391 | </Head>
|
392 | <p>Hello world!</p>
|
393 | </div>
|
394 | )
|
395 | }
|
396 |
|
397 | export default IndexPage
|
398 | ```
|
399 |
|
400 | To avoid duplicate tags in your `<head>` you can use the `key` property, which will make sure the tag is only rendered once:
|
401 |
|
402 | ```jsx
|
403 | import Head from 'next/head'
|
404 |
|
405 | function IndexPage() {
|
406 | return (
|
407 | <div>
|
408 | <Head>
|
409 | <title>My page title</title>
|
410 | <meta
|
411 | name="viewport"
|
412 | content="initial-scale=1.0, width=device-width"
|
413 | key="viewport"
|
414 | />
|
415 | </Head>
|
416 | <Head>
|
417 | <meta
|
418 | name="viewport"
|
419 | content="initial-scale=1.2, width=device-width"
|
420 | key="viewport"
|
421 | />
|
422 | </Head>
|
423 | <p>Hello world!</p>
|
424 | </div>
|
425 | )
|
426 | }
|
427 |
|
428 | export default IndexPage
|
429 | ```
|
430 |
|
431 | In this case only the second `<meta name="viewport" />` is rendered.
|
432 |
|
433 | _Note: The contents of `<head>` get cleared upon unmounting the component, so make sure each page completely defines what it needs in `<head>`, without making assumptions about what other pages added._
|
434 |
|
435 | _Note: `<title>` and `<meta>` elements need to be contained as **direct** children of the `<Head>` element, or wrapped into maximum one level of `<React.Fragment>`, otherwise the metatags won't be correctly picked up on clientside navigation._
|
436 |
|
437 | ### Fetching data and component lifecycle
|
438 |
|
439 | <details>
|
440 | <summary><b>Examples</b></summary>
|
441 | <ul>
|
442 | <li><a href="/examples/data-fetch">Data fetch</a></li>
|
443 | </ul>
|
444 | </details>
|
445 |
|
446 | When you need state, lifecycle hooks or **initial data population** you can export a function component that uses [Hooks](https://reactjs.org/docs/hooks-intro.html) or a [class component](https://reactjs.org/docs/react-component.html).
|
447 |
|
448 | Using a function component:
|
449 |
|
450 | ```jsx
|
451 | import fetch from 'isomorphic-unfetch'
|
452 |
|
453 | function Page({ stars }) {
|
454 | return <div>Next stars: {stars}</div>
|
455 | }
|
456 |
|
457 | Page.getInitialProps = async ({ req }) => {
|
458 | const res = await fetch('https://api.github.com/repos/zeit/next.js')
|
459 | const json = await res.json()
|
460 | return { stars: json.stargazers_count }
|
461 | }
|
462 |
|
463 | export default Page
|
464 | ```
|
465 |
|
466 | Using a class component:
|
467 |
|
468 | ```jsx
|
469 | import React from 'react'
|
470 |
|
471 | class HelloUA extends React.Component {
|
472 | static async getInitialProps({ req }) {
|
473 | const userAgent = req ? req.headers['user-agent'] : navigator.userAgent
|
474 | return { userAgent }
|
475 | }
|
476 |
|
477 | render() {
|
478 | return <div>Hello World {this.props.userAgent}</div>
|
479 | }
|
480 | }
|
481 |
|
482 | export default HelloUA
|
483 | ```
|
484 |
|
485 | Notice that to load data when the page loads, we use `getInitialProps` which is an [`async`](https://zeit.co/blog/async-and-await) static method. It can asynchronously fetch anything that resolves to a JavaScript plain `Object`, which populates `props`.
|
486 |
|
487 | Data returned from `getInitialProps` is serialized when server rendering, similar to a `JSON.stringify`. Make sure the returned object from `getInitialProps` is a plain `Object` and not using `Date`, `Map` or `Set`.
|
488 |
|
489 | For the initial page load, `getInitialProps` will execute on the server only. `getInitialProps` will only be executed on the client when navigating to a different route via the `Link` component or using the routing APIs.
|
490 |
|
491 | <br/>
|
492 |
|
493 | > - `getInitialProps` can **not** be used in children components. Only in `pages`.
|
494 | > - If you are using some server only modules inside `getInitialProps`, make sure to [import them properly](https://arunoda.me/blog/ssr-and-server-only-modules), otherwise, it'll slow down your app.
|
495 |
|
496 | <br/>
|
497 |
|
498 | `getInitialProps` receives a context object with the following properties:
|
499 |
|
500 | - `pathname` - path section of URL
|
501 | - `query` - query string section of URL parsed as an object
|
502 | - `asPath` - `String` of the actual path (including the query) shows in the browser
|
503 | - `req` - HTTP request object (server only)
|
504 | - `res` - HTTP response object (server only)
|
505 | - `err` - Error object if any error is encountered during the rendering
|
506 |
|
507 | ### Routing
|
508 |
|
509 | Next.js does not ship a routes manifest with every possible route in the application, so the current page is not aware of any other pages on the client side. All subsequent routes get lazy-loaded, for scalability sake.
|
510 |
|
511 | #### With `<Link>`
|
512 |
|
513 | <details>
|
514 | <summary><b>Examples</b></summary>
|
515 | <ul>
|
516 | <li><a href="/examples/hello-world">Hello World</a></li>
|
517 | </ul>
|
518 | </details>
|
519 |
|
520 | Client-side transitions between routes can be enabled via a `<Link>` component.
|
521 |
|
522 | > This component is not required for navigations to static pages that require a hard refresh, like when using [AMP](#amp-support).
|
523 |
|
524 | **Basic Example**
|
525 |
|
526 | Consider these two pages:
|
527 |
|
528 | ```jsx
|
529 | // pages/index.js
|
530 | import Link from 'next/link'
|
531 |
|
532 | function Home() {
|
533 | return (
|
534 | <>
|
535 | <ul>
|
536 | <li>Home</li>
|
537 | <li>
|
538 | <Link href="/about">
|
539 | <a>About Us</a>
|
540 | </Link>
|
541 | </li>
|
542 | </ul>
|
543 |
|
544 | <h1>This is our homepage.</h1>
|
545 | </>
|
546 | )
|
547 | }
|
548 |
|
549 | export default Home
|
550 | ```
|
551 |
|
552 | ```jsx
|
553 | // pages/about.js
|
554 | import Link from 'next/link'
|
555 |
|
556 | function About() {
|
557 | return (
|
558 | <>
|
559 | <ul>
|
560 | <li>
|
561 | <Link href="/">
|
562 | <a>Home</a>
|
563 | </Link>
|
564 | </li>
|
565 | <li>About Us</li>
|
566 | </ul>
|
567 |
|
568 | <h1>About</h1>
|
569 | <p>We are a cool company.</p>
|
570 | </>
|
571 | )
|
572 | }
|
573 |
|
574 | export default About
|
575 | ```
|
576 |
|
577 | Note: if passing a functional component as a child of `<Link>` you will need to wrap it in [`React.forwardRef`](https://reactjs.org/docs/react-api.html#reactforwardref)
|
578 |
|
579 | **Example with `React.forwardRef`**
|
580 |
|
581 | ```jsx
|
582 | import React from 'react'
|
583 | import Link from 'next/link'
|
584 |
|
585 | // `onClick`, `href`, and `ref` need to be passed to the DOM element
|
586 | // for proper handling
|
587 | const MyButton = React.forwardRef(({ onClick, href }, ref) => (
|
588 | <a href={href} onClick={onClick} ref={ref}>
|
589 | Click Me
|
590 | </a>
|
591 | ))
|
592 |
|
593 | export default () => (
|
594 | <>
|
595 | <Link href="/another">
|
596 | <MyButton />
|
597 | </Link>
|
598 | </>
|
599 | )
|
600 | ```
|
601 |
|
602 | **Custom routes (using props from URL)**
|
603 |
|
604 | If you find that your use case is not covered by [Dynamic Routing](#dynamic-routing) then you can create a custom server and manually add dynamic routes.
|
605 |
|
606 | Example:
|
607 |
|
608 | 1. Consider you have the URL `/post/:slug`.
|
609 |
|
610 | 2. You created `pages/post.js`:
|
611 |
|
612 | ```jsx
|
613 | import { useRouter } from 'next/router'
|
614 |
|
615 | const Post = () => {
|
616 | const router = useRouter()
|
617 | const { slug } = router.query
|
618 |
|
619 | return <p>My Blog Post: {slug}</p>
|
620 | }
|
621 |
|
622 | export default Post
|
623 | ```
|
624 |
|
625 | 3. You add the route to `express` (or any other server) on `server.js` file (this is only for SSR). This will route the url `/post/:slug` to `pages/post.js` and provide `slug` as part of the `query` object to the page.
|
626 |
|
627 | ```jsx
|
628 | server.get('/post/:slug', (req, res) => {
|
629 | return app.render(req, res, '/post', { slug: req.params.slug })
|
630 | })
|
631 | ```
|
632 |
|
633 | 4. For client side routing, use `next/link`:
|
634 |
|
635 | ```jsx
|
636 | <Link href="/post?slug=something" as="/post/something">
|
637 | ```
|
638 |
|
639 | - `href`: the path inside `pages` directory
|
640 | - `as`: the path used by your server routes
|
641 |
|
642 | Client-side routing behaves exactly like the browser:
|
643 |
|
644 | 1. The component is fetched.
|
645 | 2. If it defines `getInitialProps`, data is fetched. If an error occurs, `_error.js` is rendered.
|
646 | 3. After 1 and 2 complete, `pushState` is performed and the new component is rendered.
|
647 |
|
648 | To inject the `pathname`, `query` or `asPath` in your component, you can use the [useRouter](#userouter) hook, or [withRouter](#using-a-higher-order-component) for class components.
|
649 |
|
650 | ##### With URL object
|
651 |
|
652 | <details>
|
653 | <summary><b>Examples</b></summary>
|
654 | <ul>
|
655 | <li><a href="/examples/with-url-object-routing">With URL Object Routing</a></li>
|
656 | </ul>
|
657 | </details>
|
658 |
|
659 | The component `<Link>` can also receive a URL object and it will automatically format it to create the URL string.
|
660 |
|
661 | ```jsx
|
662 | // pages/index.js
|
663 | import Link from 'next/link'
|
664 |
|
665 | function Home() {
|
666 | return (
|
667 | <div>
|
668 | Click{' '}
|
669 | <Link href={{ pathname: '/about', query: { name: 'Zeit' } }}>
|
670 | <a>here</a>
|
671 | </Link>{' '}
|
672 | to read more
|
673 | </div>
|
674 | )
|
675 | }
|
676 |
|
677 | export default Home
|
678 | ```
|
679 |
|
680 | That will generate the URL string `/about?name=Zeit`, you can use every property as defined in the [Node.js URL module documentation](https://nodejs.org/api/url.html#url_url_strings_and_url_objects).
|
681 |
|
682 | ##### Replace instead of push url
|
683 |
|
684 | The default behaviour for the `<Link>` component is to `push` a new url into the stack. You can use the `replace` prop to prevent adding a new entry.
|
685 |
|
686 | ```jsx
|
687 | // pages/index.js
|
688 | import Link from 'next/link'
|
689 |
|
690 | function Home() {
|
691 | return (
|
692 | <div>
|
693 | Click{' '}
|
694 | <Link href="/about" replace>
|
695 | <a>here</a>
|
696 | </Link>{' '}
|
697 | to read more
|
698 | </div>
|
699 | )
|
700 | }
|
701 |
|
702 | export default Home
|
703 | ```
|
704 |
|
705 | ##### Using a component that supports `onClick`
|
706 |
|
707 | `<Link>` supports any component that supports the `onClick` event. In case you don't provide an `<a>` tag, it will only add the `onClick` event handler and won't pass the `href` property.
|
708 |
|
709 | ```jsx
|
710 | // pages/index.js
|
711 | import Link from 'next/link'
|
712 |
|
713 | function Home() {
|
714 | return (
|
715 | <div>
|
716 | Click{' '}
|
717 | <Link href="/about">
|
718 | <img src="/static/image.png" alt="image" />
|
719 | </Link>
|
720 | </div>
|
721 | )
|
722 | }
|
723 |
|
724 | export default Home
|
725 | ```
|
726 |
|
727 | ##### Forcing the Link to expose `href` to its child
|
728 |
|
729 | If child is an `<a>` tag and doesn't have a href attribute we specify it so that the repetition is not needed by the user. However, sometimes, you’ll want to pass an `<a>` tag inside of a wrapper and the `Link` won’t recognize it as a _hyperlink_, and, consequently, won’t transfer its `href` to the child. In cases like that, you should define a boolean `passHref` property to the `Link`, forcing it to expose its `href` property to the child.
|
730 |
|
731 | **Please note**: using a tag other than `a` and failing to pass `passHref` may result in links that appear to navigate correctly, but, when being crawled by search engines, will not be recognized as links (owing to the lack of `href` attribute). This may result in negative effects on your sites SEO.
|
732 |
|
733 | ```jsx
|
734 | import Link from 'next/link'
|
735 | import Unexpected_A from 'third-library'
|
736 |
|
737 | function NavLink({ href, name }) {
|
738 | return (
|
739 | <Link href={href} passHref>
|
740 | <Unexpected_A>{name}</Unexpected_A>
|
741 | </Link>
|
742 | )
|
743 | }
|
744 |
|
745 | export default NavLink
|
746 | ```
|
747 |
|
748 | ##### Disabling the scroll changes to top on page
|
749 |
|
750 | The default behaviour of `<Link>` is to scroll to the top of the page. When there is a hash defined it will scroll to the specific id, just like a normal `<a>` tag. To prevent scrolling to the top / hash `scroll={false}` can be added to `<Link>`:
|
751 |
|
752 | ```jsx
|
753 | <Link scroll={false} href="/?counter=10"><a>Disables scrolling</a></Link>
|
754 | <Link href="/?counter=10"><a>Changes with scrolling to top</a></Link>
|
755 | ```
|
756 |
|
757 | #### Imperatively
|
758 |
|
759 | <details>
|
760 | <summary><b>Examples</b></summary>
|
761 | <ul>
|
762 | <li><a href="/examples/using-router">Basic routing</a></li>
|
763 | <li><a href="/examples/with-loading">With a page loading indicator</a></li>
|
764 | </ul>
|
765 | </details>
|
766 |
|
767 | You can also do client-side page transitions using `next/router`:
|
768 |
|
769 | ```jsx
|
770 | import Router from 'next/router'
|
771 |
|
772 | function ReadMore() {
|
773 | return (
|
774 | <div>
|
775 | Click <span onClick={() => Router.push('/about')}>here</span> to read more
|
776 | </div>
|
777 | )
|
778 | }
|
779 |
|
780 | export default ReadMore
|
781 | ```
|
782 |
|
783 | #### Intercepting `popstate`
|
784 |
|
785 | In some cases (for example, if using a [custom router](#custom-server-and-routing)), you may wish
|
786 | to listen to [`popstate`](https://developer.mozilla.org/en-US/docs/Web/Events/popstate) and react before the router acts on it.
|
787 | For example, you could use this to manipulate the request, or force an SSR refresh.
|
788 |
|
789 | ```jsx
|
790 | import Router from 'next/router'
|
791 |
|
792 | Router.beforePopState(({ url, as, options }) => {
|
793 | // I only want to allow these two routes!
|
794 | if (as !== '/' && as !== '/other') {
|
795 | // Have SSR render bad routes as a 404.
|
796 | window.location.href = as
|
797 | return false
|
798 | }
|
799 |
|
800 | return true
|
801 | })
|
802 | ```
|
803 |
|
804 | If the function you pass into `beforePopState` returns `false`, `Router` will not handle `popstate`;
|
805 | you'll be responsible for handling it, in that case.
|
806 | See [Disabling File-System Routing](#disabling-file-system-routing).
|
807 |
|
808 | Above `Router` object comes with the following API:
|
809 |
|
810 | - `route` - `String` of the current route
|
811 | - `pathname` - `String` of the current path excluding the query string
|
812 | - `query` - `Object` with the parsed query string. Defaults to `{}`.
|
813 | - `asPath` - `String` of the actual path (including the query) shows in the browser
|
814 | - `push(url, as=url)` - performs a `pushState` call with the given url
|
815 | - `replace(url, as=url)` - performs a `replaceState` call with the given url
|
816 | - `beforePopState(cb=function)` - intercept popstate before router processes the event
|
817 |
|
818 | The second `as` parameter for `push` and `replace` is an optional _decoration_ of the URL. Useful if you configured custom routes on the server.
|
819 |
|
820 | ##### With URL object
|
821 |
|
822 | You can use a URL object the same way you use it in a `<Link>` component to `push` and `replace` a URL.
|
823 |
|
824 | ```jsx
|
825 | import Router from 'next/router'
|
826 |
|
827 | const handler = () => {
|
828 | Router.push({
|
829 | pathname: '/about',
|
830 | query: { name: 'Zeit' },
|
831 | })
|
832 | }
|
833 |
|
834 | function ReadMore() {
|
835 | return (
|
836 | <div>
|
837 | Click <span onClick={handler}>here</span> to read more
|
838 | </div>
|
839 | )
|
840 | }
|
841 |
|
842 | export default ReadMore
|
843 | ```
|
844 |
|
845 | This uses the same exact parameters as [in the `<Link>` component](#with-url-object). The first parameter maps to `href` while the second parameter maps to `as` in the `<Link>` component as documented [here](#with-url-object).
|
846 |
|
847 | ##### Router Events
|
848 |
|
849 | You can also listen to different events happening inside the Router.
|
850 | Here's a list of supported events:
|
851 |
|
852 | - `routeChangeStart(url)` - Fires when a route starts to change
|
853 | - `routeChangeComplete(url)` - Fires when a route changed completely
|
854 | - `routeChangeError(err, url)` - Fires when there's an error when changing routes, or a route load is cancelled
|
855 | - `beforeHistoryChange(url)` - Fires just before changing the browser's history
|
856 | - `hashChangeStart(url)` - Fires when the hash will change but not the page
|
857 | - `hashChangeComplete(url)` - Fires when the hash has changed but not the page
|
858 |
|
859 | > Here `url` is the URL shown in the browser. If you call `Router.push(url, as)` (or similar), then the value of `url` will be `as`.
|
860 |
|
861 | Here's how to properly listen to the router event `routeChangeStart`:
|
862 |
|
863 | ```js
|
864 | const handleRouteChange = url => {
|
865 | console.log('App is changing to: ', url)
|
866 | }
|
867 |
|
868 | Router.events.on('routeChangeStart', handleRouteChange)
|
869 | ```
|
870 |
|
871 | If you no longer want to listen to that event, you can unsubscribe with the `off` method:
|
872 |
|
873 | ```js
|
874 | Router.events.off('routeChangeStart', handleRouteChange)
|
875 | ```
|
876 |
|
877 | If a route load is cancelled (for example by clicking two links rapidly in succession), `routeChangeError` will fire. The passed `err` will contain a `cancelled` property set to `true`.
|
878 |
|
879 | ```js
|
880 | Router.events.on('routeChangeError', (err, url) => {
|
881 | if (err.cancelled) {
|
882 | console.log(`Route to ${url} was cancelled!`)
|
883 | }
|
884 | })
|
885 | ```
|
886 |
|
887 | > **Note**: Using router events in `getInitialProps` is discouraged as it may result in unexpected behavior.<br/>
|
888 | > Router events should be registered when a component mounts (`useEffect` or `componentDidMount`/`componentWillUnmount`) or imperatively when an event happens.
|
889 | >
|
890 | > ```js
|
891 | > useEffect(() => {
|
892 | > const handleRouteChange = url => {
|
893 | > console.log('App is changing to: ', url)
|
894 | > }
|
895 | >
|
896 | > Router.events.on('routeChangeStart', handleRouteChange)
|
897 | > return () => {
|
898 | > Router.events.off('routeChangeStart', handleRouteChange)
|
899 | > }
|
900 | > }, [])
|
901 | > ```
|
902 |
|
903 | ##### Shallow Routing
|
904 |
|
905 | <details>
|
906 | <summary><b>Examples</b></summary>
|
907 | <ul>
|
908 | <li><a href="/examples/with-shallow-routing">Shallow Routing</a></li>
|
909 | </ul>
|
910 | </details>
|
911 |
|
912 | Shallow routing allows you to change the URL without running `getInitialProps`. You'll receive the updated `pathname` and the `query` via the `router` prop (injected by using [`useRouter`](#userouter) or [`withRouter`](#using-a-higher-order-component)), without losing state.
|
913 |
|
914 | You can do this by invoking either `Router.push` or `Router.replace` with the `shallow: true` option. Here's an example:
|
915 |
|
916 | ```js
|
917 | // Current URL is "/"
|
918 | const href = '/?counter=10'
|
919 | const as = href
|
920 | Router.push(href, as, { shallow: true })
|
921 | ```
|
922 |
|
923 | Now, the URL is updated to `/?counter=10`. You can see the updated URL with `this.props.router.query` inside the `Component` (make sure you are using [`withRouter`](#using-a-higher-order-component) around your `Component` to inject the `router` prop).
|
924 |
|
925 | You can watch for URL changes via [`componentDidUpdate`](https://reactjs.org/docs/react-component.html#componentdidupdate) hook as shown below:
|
926 |
|
927 | ```js
|
928 | componentDidUpdate(prevProps) {
|
929 | const { pathname, query } = this.props.router
|
930 | // verify props have changed to avoid an infinite loop
|
931 | if (query.id !== prevProps.router.query.id) {
|
932 | // fetch data based on the new query
|
933 | }
|
934 | }
|
935 | ```
|
936 |
|
937 | > NOTES:
|
938 | >
|
939 | > Shallow routing works **only** for same page URL changes. For an example, let's assume we have another page called `about`, and you run this:
|
940 | >
|
941 | > ```js
|
942 | > Router.push('/?counter=10', '/about?counter=10', { shallow: true })
|
943 | > ```
|
944 | >
|
945 | > Since that's a new page, it'll unload the current page, load the new one and call `getInitialProps` even though we asked to do shallow routing.
|
946 |
|
947 | #### useRouter
|
948 |
|
949 | <details>
|
950 | <summary><b>Examples</b></summary>
|
951 | <ul>
|
952 | <li><a href="/examples/dynamic-routing">Dynamic routing</a></li>
|
953 | </ul>
|
954 | </details>
|
955 |
|
956 | If you want to access the `router` object inside any functional component in your app, you can use the `useRouter` hook, here's how to use it:
|
957 |
|
958 | ```jsx
|
959 | import { useRouter } from 'next/router'
|
960 |
|
961 | export default function ActiveLink({ children, href }) {
|
962 | const router = useRouter()
|
963 | const style = {
|
964 | marginRight: 10,
|
965 | color: router.pathname === href ? 'red' : 'black',
|
966 | }
|
967 |
|
968 | const handleClick = e => {
|
969 | e.preventDefault()
|
970 | router.push(href)
|
971 | }
|
972 |
|
973 | return (
|
974 | <a href={href} onClick={handleClick} style={style}>
|
975 | {children}
|
976 | </a>
|
977 | )
|
978 | }
|
979 | ```
|
980 |
|
981 | > **Note**: `useRouter` is a React hook, meaning it cannot be used with classes.
|
982 | > You can either use [`withRouter`](#using-a-higher-order-component) (a higher order component) or wrap your class in a functional component.
|
983 |
|
984 | The above `router` object comes with an API similar to [`next/router`](#imperatively).
|
985 |
|
986 | #### Using a Higher Order Component
|
987 |
|
988 | <details>
|
989 | <summary><b>Examples</b></summary>
|
990 | <ul>
|
991 | <li><a href="/examples/using-with-router">Using the `withRouter` utility</a></li>
|
992 | </ul>
|
993 | </details>
|
994 |
|
995 | If [useRouter](#userouter) is not the best fit for you, `withRouter` can also add the same `router` object to any component, here's how to use it:
|
996 |
|
997 | ```jsx
|
998 | import { withRouter } from 'next/router'
|
999 |
|
1000 | function Page({ router }) {
|
1001 | return <p>{router.pathname}</p>
|
1002 | }
|
1003 |
|
1004 | export default withRouter(Page)
|
1005 | ```
|
1006 |
|
1007 | ### Prefetching Pages
|
1008 |
|
1009 | ⚠️ This is a production only feature ⚠️
|
1010 |
|
1011 | <details>
|
1012 | <summary><b>Examples</b></summary>
|
1013 | <ul>
|
1014 | <li><a href="/examples/with-prefetching">Prefetching</a></li>
|
1015 | </ul>
|
1016 | </details>
|
1017 |
|
1018 | Next.js has an API which allows you to prefetch pages.
|
1019 |
|
1020 | Since Next.js server-renders your pages, this allows all the future interaction paths of your app to be instant. Effectively Next.js gives you the great initial download performance of a _website_, with the ahead-of-time download capabilities of an _app_. [Read more](https://zeit.co/blog/next#anticipation-is-the-key-to-performance).
|
1021 |
|
1022 | > With prefetching Next.js only downloads JS code. When the page is getting rendered, you may need to wait for the data.
|
1023 |
|
1024 | > Automatic prefetching is disabled if your device is connected with 2G network or [Save-Data](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Save-Data) header is `on`.
|
1025 |
|
1026 | > `<link rel="preload">` is used for prefetching. Sometimes browsers will show a warning if the resource is not used within 3 seconds, these warnings can be ignored as per https://github.com/zeit/next.js/issues/6517#issuecomment-469063892.
|
1027 |
|
1028 | #### With `<Link>`
|
1029 |
|
1030 | `<Link>` will automatically prefetch pages in the background as they appear in the view. If certain pages are rarely visited you can manually set `prefetch` to `false`, here's how:
|
1031 |
|
1032 | ```jsx
|
1033 | <Link href="/about" prefetch={false}>
|
1034 | <a>About</a>
|
1035 | </Link>
|
1036 | ```
|
1037 |
|
1038 | #### Imperatively
|
1039 |
|
1040 | Most prefetching needs are addressed by `<Link />`, but we also expose an imperative API for advanced usage:
|
1041 |
|
1042 | ```jsx
|
1043 | import { useRouter } from 'next/router'
|
1044 |
|
1045 | export default function MyLink() {
|
1046 | const router = useRouter()
|
1047 |
|
1048 | return (
|
1049 | <>
|
1050 | <a onClick={() => setTimeout(() => router.push('/dynamic'), 100)}>
|
1051 | A route transition will happen after 100ms
|
1052 | </a>
|
1053 | {// and we can prefetch it!
|
1054 | router.prefetch('/dynamic')}
|
1055 | </>
|
1056 | )
|
1057 | }
|
1058 | ```
|
1059 |
|
1060 | `router` methods should be only used inside the client side of your app though. In order to prevent any error regarding this subject use the imperatively `prefetch` method in the `useEffect()` hook:
|
1061 |
|
1062 | ```jsx
|
1063 | import { useRouter } from 'next/router'
|
1064 |
|
1065 | export default function MyLink() {
|
1066 | const router = useRouter()
|
1067 |
|
1068 | useEffect(() => {
|
1069 | router.prefetch('/dynamic')
|
1070 | })
|
1071 |
|
1072 | return (
|
1073 | <a onClick={() => setTimeout(() => router.push('/dynamic'), 100)}>
|
1074 | A route transition will happen after 100ms
|
1075 | </a>
|
1076 | )
|
1077 | }
|
1078 | ```
|
1079 |
|
1080 | You can also add it to the `componentDidMount()` lifecycle method when using `React.Component`:
|
1081 |
|
1082 | ```jsx
|
1083 | import React from 'react'
|
1084 | import { withRouter } from 'next/router'
|
1085 |
|
1086 | class MyLink extends React.Component {
|
1087 | componentDidMount() {
|
1088 | const { router } = this.props
|
1089 | router.prefetch('/dynamic')
|
1090 | }
|
1091 |
|
1092 | render() {
|
1093 | const { router } = this.props
|
1094 |
|
1095 | return (
|
1096 | <a onClick={() => setTimeout(() => router.push('/dynamic'), 100)}>
|
1097 | A route transition will happen after 100ms
|
1098 | </a>
|
1099 | )
|
1100 | }
|
1101 | }
|
1102 |
|
1103 | export default withRouter(MyLink)
|
1104 | ```
|
1105 |
|
1106 | ### API Routes
|
1107 |
|
1108 | <details>
|
1109 | <summary><b>Examples</b></summary>
|
1110 | <ul>
|
1111 | <li><a href="/examples/api-routes">Basic API routes</a></li>
|
1112 | <li><a href="/examples/api-routes-micro">API routes with micro</a></li>
|
1113 | <li><a href="/examples/api-routes-middleware">API routes with middleware</a></li>
|
1114 | <li><a href="/examples/api-routes-graphql">API routes with GraphQL server</a></li>
|
1115 | <li><a href="/examples/api-routes-rest">API routes with REST</a></li>
|
1116 | </ul>
|
1117 | </details>
|
1118 |
|
1119 | API routes provides a straightforward solution to build your **API** with Next.js.
|
1120 | Start by creating the `api/` folder inside the `./pages/` folder.
|
1121 |
|
1122 | Every file inside `./pages/api` is mapped to `/api/*`.
|
1123 | For example, `./pages/api/posts.js` is mapped to the route `/api/posts`.
|
1124 |
|
1125 | Here's an example API route file:
|
1126 |
|
1127 | ```js
|
1128 | export default (req, res) => {
|
1129 | res.setHeader('Content-Type', 'application/json')
|
1130 | res.statusCode = 200
|
1131 | res.end(JSON.stringify({ name: 'Nextjs' }))
|
1132 | }
|
1133 | ```
|
1134 |
|
1135 | - `req` refers to [NextApiRequest](https://github.com/zeit/next.js/blob/v9.0.0/packages/next-server/lib/utils.ts#L143-L158) which extends [http.IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage)
|
1136 |
|
1137 | - `res` refers to [NextApiResponse](https://github.com/zeit/next.js/blob/v9.0.0/packages/next-server/lib/utils.ts#L168-L178) which extends [http.ServerResponse](https://nodejs.org/api/http.html#http_class_http_serverresponse)
|
1138 |
|
1139 | For [API routes](#api-routes) there are built-in types `NextApiRequest` and `NextApiResponse`, which extend the `Node.js` request and response objects.
|
1140 |
|
1141 | ```ts
|
1142 | import { NextApiRequest, NextApiResponse } from 'next'
|
1143 |
|
1144 | export default (req: NextApiRequest, res: NextApiResponse) => {
|
1145 | res.status(200).json({ title: 'Next.js' })
|
1146 | }
|
1147 | ```
|
1148 |
|
1149 | To handle different HTTP methods for API calls you can access `req.method` in your resolver function:
|
1150 |
|
1151 | ```js
|
1152 | export default (req, res) => {
|
1153 | if (req.method === 'POST') {
|
1154 | // Process your POST request
|
1155 | } else {
|
1156 | // Handle the rest of your HTTP methods
|
1157 | }
|
1158 | }
|
1159 | ```
|
1160 |
|
1161 | > **Note**: API Routes [do not specify CORS headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS), so they'll be **same-origin only** by default.
|
1162 | > You can customize this behavior by wrapping your export with CORS middleware.
|
1163 | > We provide an [example of this below](#api-middlewares).
|
1164 |
|
1165 | API Routes do not increase your client-side bundle size. They are server-side only bundles.
|
1166 |
|
1167 | #### Dynamic routes support
|
1168 |
|
1169 | API pages support [dynamic routing](#dynamic-routing), so you can use all benefits mentioned already above.
|
1170 |
|
1171 | Consider the following page `./pages/api/post/[pid].js`, here is how you get parameters inside the resolver method:
|
1172 |
|
1173 | ```js
|
1174 | export default (req, res) => {
|
1175 | const {
|
1176 | query: { pid },
|
1177 | } = req
|
1178 |
|
1179 | res.end(`Post: ${pid}`)
|
1180 | }
|
1181 | ```
|
1182 |
|
1183 | #### API Middlewares
|
1184 |
|
1185 | API routes provides built in middlewares which parse the incoming `req`.
|
1186 | Those middlewares are:
|
1187 |
|
1188 | - `req.cookies` - an object containing the cookies sent by the request. Defaults to `{}`
|
1189 | - `req.query` - an object containing the [query string](https://en.wikipedia.org/wiki/Query_string). Defaults to `{}`
|
1190 | - `req.body` - an object containing the body parsed by `content-type`, or `null` if no body is sent
|
1191 |
|
1192 | Body parsing is enabled by default with a size limit of `1mb` for the parsed body.
|
1193 | You can opt-out of automatic body parsing if you need to consume it as a `Stream`:
|
1194 |
|
1195 | ```js
|
1196 | // ./pages/api/my-endpoint.js
|
1197 | export default (req, res) => {
|
1198 | // ...
|
1199 | }
|
1200 |
|
1201 | export const config = {
|
1202 | api: {
|
1203 | bodyParser: false,
|
1204 | },
|
1205 | }
|
1206 | ```
|
1207 |
|
1208 | You can adjust size of parsed body by adding `sizeLimit` key to `bodyParser`, supported values are by [bytes](https://github.com/visionmedia/bytes.js) library.
|
1209 |
|
1210 | ```js
|
1211 | // ./pages/api/my-endpoint.js
|
1212 | export default (req, res) => {
|
1213 | // ...
|
1214 | }
|
1215 |
|
1216 | export const config = {
|
1217 | api: {
|
1218 | bodyParser: {
|
1219 | sizeLimit: '1mb',
|
1220 | },
|
1221 | },
|
1222 | }
|
1223 | ```
|
1224 |
|
1225 | As an added bonus, you can also use any [Micro](https://github.com/zeit/micro) compatible [middleware](https://github.com/amio/awesome-micro)!
|
1226 |
|
1227 | For example, [configuring CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) for your API endpoint can be done leveraging `micro-cors`.
|
1228 |
|
1229 | First, install `micro-cors`:
|
1230 |
|
1231 | ```bash
|
1232 | npm i micro-cors
|
1233 | # or
|
1234 | yarn add micro-cors
|
1235 | ```
|
1236 |
|
1237 | Then, import `micro-cors` and [configure it](https://github.com/possibilities/micro-cors#readme). Finally, wrap your exported function in the middleware:
|
1238 |
|
1239 | ```js
|
1240 | import Cors from 'micro-cors'
|
1241 |
|
1242 | const cors = Cors({
|
1243 | allowMethods: ['GET', 'HEAD'],
|
1244 | })
|
1245 |
|
1246 | function Endpoint(req, res) {
|
1247 | res.json({ message: 'Hello Everyone!' })
|
1248 | }
|
1249 |
|
1250 | export default cors(Endpoint)
|
1251 | ```
|
1252 |
|
1253 | #### Helper Functions
|
1254 |
|
1255 | We're providing a set of Express.js-like methods to improve the developer experience and increase the speed of creating new API endpoints:
|
1256 |
|
1257 | ```js
|
1258 | export default (req, res) => {
|
1259 | res.status(200).json({ name: 'Next.js' })
|
1260 | }
|
1261 | ```
|
1262 |
|
1263 | - `res.status(code)` - a function to set the status code. `code` must be a valid [HTTP status code](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes)
|
1264 | - `res.json(json)` - Sends a `JSON` response. `json` must be a valid `JSON` object
|
1265 | - `res.send(body)` - Sends the HTTP response. `body` can be a `string`, an `object` or a `Buffer`
|
1266 |
|
1267 | ### Custom server and routing
|
1268 |
|
1269 | <details>
|
1270 | <summary><b>Examples</b></summary>
|
1271 | <ul>
|
1272 | <li><a href="/examples/custom-server">Basic custom server</a></li>
|
1273 | <li><a href="/examples/custom-server-express">Express integration</a></li>
|
1274 | <li><a href="/examples/custom-server-hapi">Hapi integration</a></li>
|
1275 | <li><a href="/examples/custom-server-koa">Koa integration</a></li>
|
1276 | <li><a href="/examples/parameterized-routing">Parameterized routing</a></li>
|
1277 | <li><a href="/examples/ssr-caching">SSR caching</a></li>
|
1278 | </ul>
|
1279 | </details>
|
1280 |
|
1281 | Typically you start your next server with `next start`. It's possible, however, to start a server 100% programmatically in order to customize routes, use route patterns, etc.
|
1282 |
|
1283 | When using a custom server with a server file, for example called `server.js`, make sure you update the scripts key in `package.json` to:
|
1284 |
|
1285 | ```json
|
1286 | {
|
1287 | "scripts": {
|
1288 | "dev": "node server.js",
|
1289 | "build": "next build",
|
1290 | "start": "NODE_ENV=production node server.js"
|
1291 | }
|
1292 | }
|
1293 | ```
|
1294 |
|
1295 | This example makes `/a` resolve to `./pages/b`, and `/b` resolve to `./pages/a`:
|
1296 |
|
1297 | ```js
|
1298 | // This file doesn't go through babel or webpack transformation.
|
1299 | // Make sure the syntax and sources this file requires are compatible with the current node version you are running
|
1300 | // See https://github.com/zeit/next.js/issues/1245 for discussions on Universal Webpack or universal Babel
|
1301 | const { createServer } = require('http')
|
1302 | const { parse } = require('url')
|
1303 | const next = require('next')
|
1304 |
|
1305 | const dev = process.env.NODE_ENV !== 'production'
|
1306 | const app = next({ dev })
|
1307 | const handle = app.getRequestHandler()
|
1308 |
|
1309 | app.prepare().then(() => {
|
1310 | createServer((req, res) => {
|
1311 | // Be sure to pass `true` as the second argument to `url.parse`.
|
1312 | // This tells it to parse the query portion of the URL.
|
1313 | const parsedUrl = parse(req.url, true)
|
1314 | const { pathname, query } = parsedUrl
|
1315 |
|
1316 | if (pathname === '/a') {
|
1317 | app.render(req, res, '/b', query)
|
1318 | } else if (pathname === '/b') {
|
1319 | app.render(req, res, '/a', query)
|
1320 | } else {
|
1321 | handle(req, res, parsedUrl)
|
1322 | }
|
1323 | }).listen(3000, err => {
|
1324 | if (err) throw err
|
1325 | console.log('> Ready on http://localhost:3000')
|
1326 | })
|
1327 | })
|
1328 | ```
|
1329 |
|
1330 | The `next` API is as follows:
|
1331 |
|
1332 | - `next(opts: object)`
|
1333 |
|
1334 | Supported options:
|
1335 |
|
1336 | - `dev` (`bool`) whether to launch Next.js in dev mode - default `false`
|
1337 | - `dir` (`string`) where the Next project is located - default `'.'`
|
1338 | - `quiet` (`bool`) Hide error messages containing server information - default `false`
|
1339 | - `conf` (`object`) the same object you would use in `next.config.js` - default `{}`
|
1340 |
|
1341 | Then, change your `start` script to `NODE_ENV=production node server.js`.
|
1342 |
|
1343 | #### Disabling file-system routing
|
1344 |
|
1345 | By default, `Next` will serve each file in `/pages` under a pathname matching the filename (eg, `/pages/some-file.js` is served at `site.com/some-file`.
|
1346 |
|
1347 | If your project uses custom routing, this behavior may result in the same content being served from multiple paths, which can present problems with SEO and UX.
|
1348 |
|
1349 | To disable this behavior & prevent routing based on files in `/pages`, simply set the following option in your `next.config.js`:
|
1350 |
|
1351 | ```js
|
1352 | // next.config.js
|
1353 | module.exports = {
|
1354 | useFileSystemPublicRoutes: false,
|
1355 | }
|
1356 | ```
|
1357 |
|
1358 | Note that `useFileSystemPublicRoutes` simply disables filename routes from SSR; client-side routing may still access those paths. If using this option, you should guard against navigation to routes you do not want programmatically.
|
1359 |
|
1360 | You may also wish to configure the client-side Router to disallow client-side redirects to filename routes; please refer to [Intercepting `popstate`](#intercepting-popstate).
|
1361 |
|
1362 | #### Dynamic assetPrefix
|
1363 |
|
1364 | Sometimes we need to set the `assetPrefix` dynamically. This is useful when changing the `assetPrefix` based on incoming requests.
|
1365 | For that, we can use `app.setAssetPrefix`.
|
1366 |
|
1367 | Here's an example usage of it:
|
1368 |
|
1369 | ```js
|
1370 | const next = require('next')
|
1371 | const http = require('http')
|
1372 |
|
1373 | const dev = process.env.NODE_ENV !== 'production'
|
1374 | const app = next({ dev })
|
1375 | const handleNextRequests = app.getRequestHandler()
|
1376 |
|
1377 | app.prepare().then(() => {
|
1378 | const server = new http.Server((req, res) => {
|
1379 | // Add assetPrefix support based on the hostname
|
1380 | if (req.headers.host === 'my-app.com') {
|
1381 | app.setAssetPrefix('http://cdn.com/myapp')
|
1382 | } else {
|
1383 | app.setAssetPrefix('')
|
1384 | }
|
1385 |
|
1386 | handleNextRequests(req, res)
|
1387 | })
|
1388 |
|
1389 | server.listen(port, err => {
|
1390 | if (err) {
|
1391 | throw err
|
1392 | }
|
1393 |
|
1394 | console.log(`> Ready on http://localhost:${port}`)
|
1395 | })
|
1396 | })
|
1397 | ```
|
1398 |
|
1399 | #### Changing x-powered-by
|
1400 |
|
1401 | By default Next.js will add `x-powered-by` to the request headers. There's an optional way to opt-out of this:
|
1402 |
|
1403 | ```js
|
1404 | // next.config.js
|
1405 | module.exports = {
|
1406 | poweredByHeader: false,
|
1407 | }
|
1408 | ```
|
1409 |
|
1410 | ### Dynamic Import
|
1411 |
|
1412 | <details>
|
1413 | <summary><b>Examples</b></summary>
|
1414 | <ul>
|
1415 | <li><a href="/examples/with-dynamic-import">With Dynamic Import</a></li>
|
1416 | </ul>
|
1417 | </details>
|
1418 |
|
1419 | Next.js supports ES2020 [dynamic `import()`](https://github.com/tc39/proposal-dynamic-import) for JavaScript.
|
1420 | With that, you could import JavaScript modules (inc. React Components) dynamically and work with them.
|
1421 |
|
1422 | You can think dynamic imports as another way to split your code into manageable chunks.
|
1423 | Since Next.js supports dynamic imports with SSR, you could do amazing things with it.
|
1424 |
|
1425 | Here are a few ways to use dynamic imports.
|
1426 |
|
1427 | #### Basic Usage (Also does SSR)
|
1428 |
|
1429 | ```jsx
|
1430 | import dynamic from 'next/dynamic'
|
1431 |
|
1432 | const DynamicComponent = dynamic(() => import('../components/hello'))
|
1433 |
|
1434 | function Home() {
|
1435 | return (
|
1436 | <div>
|
1437 | <Header />
|
1438 | <DynamicComponent />
|
1439 | <p>HOME PAGE is here!</p>
|
1440 | </div>
|
1441 | )
|
1442 | }
|
1443 |
|
1444 | export default Home
|
1445 | ```
|
1446 |
|
1447 | #### With named exports
|
1448 |
|
1449 | ```jsx
|
1450 | // components/hello.js
|
1451 | export function Hello() {
|
1452 | return <p>Hello!</p>
|
1453 | }
|
1454 | ```
|
1455 |
|
1456 | ```jsx
|
1457 | import dynamic from 'next/dynamic'
|
1458 |
|
1459 | const DynamicComponent = dynamic(() =>
|
1460 | import('../components/hello').then(mod => mod.Hello)
|
1461 | )
|
1462 |
|
1463 | function Home() {
|
1464 | return (
|
1465 | <div>
|
1466 | <Header />
|
1467 | <DynamicComponent />
|
1468 | <p>HOME PAGE is here!</p>
|
1469 | </div>
|
1470 | )
|
1471 | }
|
1472 |
|
1473 | export default Home
|
1474 | ```
|
1475 |
|
1476 | #### With Custom Loading Component
|
1477 |
|
1478 | ```jsx
|
1479 | import dynamic from 'next/dynamic'
|
1480 |
|
1481 | const DynamicComponentWithCustomLoading = dynamic(
|
1482 | () => import('../components/hello2'),
|
1483 | { loading: () => <p>...</p> }
|
1484 | )
|
1485 |
|
1486 | function Home() {
|
1487 | return (
|
1488 | <div>
|
1489 | <Header />
|
1490 | <DynamicComponentWithCustomLoading />
|
1491 | <p>HOME PAGE is here!</p>
|
1492 | </div>
|
1493 | )
|
1494 | }
|
1495 |
|
1496 | export default Home
|
1497 | ```
|
1498 |
|
1499 | #### With No SSR
|
1500 |
|
1501 | ```jsx
|
1502 | import dynamic from 'next/dynamic'
|
1503 |
|
1504 | const DynamicComponentWithNoSSR = dynamic(
|
1505 | () => import('../components/hello3'),
|
1506 | { ssr: false }
|
1507 | )
|
1508 |
|
1509 | function Home() {
|
1510 | return (
|
1511 | <div>
|
1512 | <Header />
|
1513 | <DynamicComponentWithNoSSR />
|
1514 | <p>HOME PAGE is here!</p>
|
1515 | </div>
|
1516 | )
|
1517 | }
|
1518 |
|
1519 | export default Home
|
1520 | ```
|
1521 |
|
1522 | ### Custom `<App>`
|
1523 |
|
1524 | <details>
|
1525 | <summary><b>Examples</b></summary>
|
1526 | <ul>
|
1527 | <li><a href="/examples/with-app-layout">Using `_app.js` for layout</a></li>
|
1528 | <li><a href="/examples/with-componentdidcatch">Using `_app.js` to override `componentDidCatch`</a></li>
|
1529 | </ul>
|
1530 | </details>
|
1531 |
|
1532 | Next.js uses the `App` component to initialize pages. You can override it and control the page initialization. Which allows you to do amazing things like:
|
1533 |
|
1534 | - Persisting layout between page changes
|
1535 | - Keeping state when navigating pages
|
1536 | - Custom error handling using `componentDidCatch`
|
1537 | - Inject additional data into pages (for example by processing GraphQL queries)
|
1538 |
|
1539 | To override, create the `./pages/_app.js` file and override the App class as shown below:
|
1540 |
|
1541 | ```js
|
1542 | import React from 'react'
|
1543 | import App from 'next/app'
|
1544 |
|
1545 | class MyApp extends App {
|
1546 | // Only uncomment this method if you have blocking data requirements for
|
1547 | // every single page in your application. This disables the ability to
|
1548 | // perform automatic static optimization, causing every page in your app to
|
1549 | // be server-side rendered.
|
1550 | //
|
1551 | // static async getInitialProps(appContext) {
|
1552 | // // calls page's `getInitialProps` and fills `appProps.pageProps`
|
1553 | // const appProps = await App.getInitialProps(appContext);
|
1554 | //
|
1555 | // return { ...appProps }
|
1556 | // }
|
1557 |
|
1558 | render() {
|
1559 | const { Component, pageProps } = this.props
|
1560 | return <Component {...pageProps} />
|
1561 | }
|
1562 | }
|
1563 |
|
1564 | export default MyApp
|
1565 | ```
|
1566 |
|
1567 | > **Note:** Adding a custom `getInitialProps` in App will affect [Automatic Static Optimization](#automatic-static-optimization)
|
1568 |
|
1569 | ### Custom `<Document>`
|
1570 |
|
1571 | <details>
|
1572 | <summary><b>Examples</b></summary>
|
1573 | <ul>
|
1574 | <li><a href="/examples/with-styled-components">Styled components custom document</a></li>
|
1575 | </ul>
|
1576 | </details>
|
1577 |
|
1578 | A custom `<Document>` is commonly used to augment your application's `<html>` and `<body>` tags.
|
1579 | This is necessary because Next.js pages skip the definition of the surrounding document's markup.
|
1580 |
|
1581 | This allows you to support Server-Side Rendering for CSS-in-JS libraries like
|
1582 | [styled-components](/examples/with-styled-components) or [emotion](/examples/with-emotion).
|
1583 | Note, [styled-jsx](https://github.com/zeit/styled-jsx) is included in Next.js by default.
|
1584 |
|
1585 | A custom `<Document>` can also include `getInitialProps` for expressing asynchronous server-rendering data requirements.
|
1586 |
|
1587 | > **Note**: `<Document>`'s `getInitialProps` function is not called during client-side transitions,
|
1588 | > nor when a page is [automatically statically optimized](#automatic-static-optimization).
|
1589 |
|
1590 | > **Note**: Make sure to check if `ctx.req` / `ctx.res` are defined in `getInitialProps`.
|
1591 | > These variables will be `undefined` when a page is being statically exported for `next export` or [automatic static optimization](#automatic-static-optimization).
|
1592 |
|
1593 | To use a custom `<Document>`, you must create a file at `./pages/_document.js` and extend the `Document` class:
|
1594 |
|
1595 | ```jsx
|
1596 | // _document is only rendered on the server side and not on the client side
|
1597 | // Event handlers like onClick can't be added to this file
|
1598 |
|
1599 | // ./pages/_document.js
|
1600 | import Document, { Html, Head, Main, NextScript } from 'next/document'
|
1601 |
|
1602 | class MyDocument extends Document {
|
1603 | static async getInitialProps(ctx) {
|
1604 | const initialProps = await Document.getInitialProps(ctx)
|
1605 | return { ...initialProps }
|
1606 | }
|
1607 |
|
1608 | render() {
|
1609 | return (
|
1610 | <Html>
|
1611 | <Head />
|
1612 | <body>
|
1613 | <Main />
|
1614 | <NextScript />
|
1615 | </body>
|
1616 | </Html>
|
1617 | )
|
1618 | }
|
1619 | }
|
1620 |
|
1621 | export default MyDocument
|
1622 | ```
|
1623 |
|
1624 | All of `<Html>`, `<Head />`, `<Main />` and `<NextScript />` are required for page to be properly rendered.
|
1625 |
|
1626 | **Note: React-components outside of `<Main />` will not be initialised by the browser. Do _not_ add application logic here. If you need shared components in all your pages (like a menu or a toolbar), take a look at the [`<App>`](#custom-app) component instead.**
|
1627 |
|
1628 | The `ctx` object is equivalent to the one received in all [`getInitialProps`](#fetching-data-and-component-lifecycle) hooks, with one addition:
|
1629 |
|
1630 | - `renderPage` (`Function`) a callback that executes the actual React rendering logic (synchronously). It's useful to decorate this function in order to support server-rendering wrappers like Aphrodite's [`renderStatic`](https://github.com/Khan/aphrodite#server-side-rendering).
|
1631 |
|
1632 | #### Customizing `renderPage`
|
1633 |
|
1634 | 🚧 It should be noted that the only reason you should be customizing `renderPage` is for usage with css-in-js libraries
|
1635 | that need to wrap the application to properly work with server-rendering. 🚧
|
1636 |
|
1637 | - It takes as argument an options object for further customization:
|
1638 |
|
1639 | ```js
|
1640 | import Document from 'next/document'
|
1641 |
|
1642 | class MyDocument extends Document {
|
1643 | static async getInitialProps(ctx) {
|
1644 | const originalRenderPage = ctx.renderPage
|
1645 |
|
1646 | ctx.renderPage = () =>
|
1647 | originalRenderPage({
|
1648 | // useful for wrapping the whole react tree
|
1649 | enhanceApp: App => App,
|
1650 | // useful for wrapping in a per-page basis
|
1651 | enhanceComponent: Component => Component,
|
1652 | })
|
1653 |
|
1654 | // Run the parent `getInitialProps` using `ctx` that now includes our custom `renderPage`
|
1655 | const initialProps = await Document.getInitialProps(ctx)
|
1656 |
|
1657 | return initialProps
|
1658 | }
|
1659 | }
|
1660 |
|
1661 | export default MyDocument
|
1662 | ```
|
1663 |
|
1664 | ### Custom error handling
|
1665 |
|
1666 | 404 or 500 errors are handled both client and server side by a default component `error.js`. If you wish to override it, define a `_error.js` in the pages folder:
|
1667 |
|
1668 | ⚠️ The `pages/_error.js` component is only used in production. In development you get an error with call stack to know where the error originated from. ⚠️
|
1669 |
|
1670 | ```jsx
|
1671 | import React from 'react'
|
1672 |
|
1673 | function Error({ statusCode }) {
|
1674 | return (
|
1675 | <p>
|
1676 | {statusCode
|
1677 | ? `An error ${statusCode} occurred on server`
|
1678 | : 'An error occurred on client'}
|
1679 | </p>
|
1680 | )
|
1681 | }
|
1682 |
|
1683 | Error.getInitialProps = ({ res, err }) => {
|
1684 | const statusCode = res ? res.statusCode : err ? err.statusCode : 404
|
1685 | return { statusCode }
|
1686 | }
|
1687 |
|
1688 | export default Error
|
1689 | ```
|
1690 |
|
1691 | ### Reusing the built-in error page
|
1692 |
|
1693 | If you want to render the built-in error page you can by using `next/error`:
|
1694 |
|
1695 | ```jsx
|
1696 | import React from 'react'
|
1697 | import Error from 'next/error'
|
1698 | import fetch from 'isomorphic-unfetch'
|
1699 |
|
1700 | const Page = ({ errorCode, stars }) => {
|
1701 | if (errorCode) {
|
1702 | return <Error statusCode={errorCode} />
|
1703 | }
|
1704 |
|
1705 | return <div>Next stars: {stars}</div>
|
1706 | }
|
1707 |
|
1708 | Page.getInitialProps = async () => {
|
1709 | const res = await fetch('https://api.github.com/repos/zeit/next.js')
|
1710 | const errorCode = res.statusCode > 200 ? res.statusCode : false
|
1711 | const json = await res.json()
|
1712 |
|
1713 | return { errorCode, stars: json.stargazers_count }
|
1714 | }
|
1715 |
|
1716 | export default Page
|
1717 | ```
|
1718 |
|
1719 | > If you have created a custom error page you have to import your own `_error` component from `./_error` instead of `next/error`.
|
1720 |
|
1721 | The Error component also takes `title` as a property if you want to pass in a text message along with a `statusCode`.
|
1722 |
|
1723 | ### Custom configuration
|
1724 |
|
1725 | For custom advanced behavior of Next.js, you can create a `next.config.js` in the root of your project directory (next to `pages/` and `package.json`).
|
1726 |
|
1727 | Note: `next.config.js` is a regular Node.js module, not a JSON file. It gets used by the Next server and build phases, and not included in the browser build.
|
1728 |
|
1729 | ```js
|
1730 | // next.config.js
|
1731 | module.exports = {
|
1732 | /* config options here */
|
1733 | }
|
1734 | ```
|
1735 |
|
1736 | Or use a function:
|
1737 |
|
1738 | ```js
|
1739 | module.exports = (phase, { defaultConfig }) => {
|
1740 | return {
|
1741 | /* config options here */
|
1742 | }
|
1743 | }
|
1744 | ```
|
1745 |
|
1746 | `phase` is the current context in which the configuration is loaded. You can see all phases here: [constants](/packages/next/next-server/lib/constants.ts)
|
1747 | Phases can be imported from `next/constants`:
|
1748 |
|
1749 | ```js
|
1750 | const { PHASE_DEVELOPMENT_SERVER } = require('next/constants')
|
1751 | module.exports = (phase, { defaultConfig }) => {
|
1752 | if (phase === PHASE_DEVELOPMENT_SERVER) {
|
1753 | return {
|
1754 | /* development only config options here */
|
1755 | }
|
1756 | }
|
1757 |
|
1758 | return {
|
1759 | /* config options for all phases except development here */
|
1760 | }
|
1761 | }
|
1762 | ```
|
1763 |
|
1764 | #### Setting a custom build directory
|
1765 |
|
1766 | You can specify a name to use for a custom build directory. For example, the following config will create a `build` folder instead of a `.next` folder. If no configuration is specified then next will create a `.next` folder.
|
1767 |
|
1768 | ```js
|
1769 | // next.config.js
|
1770 | module.exports = {
|
1771 | distDir: 'build',
|
1772 | }
|
1773 | ```
|
1774 |
|
1775 | #### Disabling etag generation
|
1776 |
|
1777 | You can disable etag generation for HTML pages depending on your cache strategy. If no configuration is specified then Next will generate etags for every page.
|
1778 |
|
1779 | ```js
|
1780 | // next.config.js
|
1781 | module.exports = {
|
1782 | generateEtags: false,
|
1783 | }
|
1784 | ```
|
1785 |
|
1786 | #### Configuring the onDemandEntries
|
1787 |
|
1788 | Next exposes some options that give you some control over how the server will dispose or keep in memories pages built:
|
1789 |
|
1790 | ```js
|
1791 | module.exports = {
|
1792 | onDemandEntries: {
|
1793 | // period (in ms) where the server will keep pages in the buffer
|
1794 | maxInactiveAge: 25 * 1000,
|
1795 | // number of pages that should be kept simultaneously without being disposed
|
1796 | pagesBufferLength: 2,
|
1797 | },
|
1798 | }
|
1799 | ```
|
1800 |
|
1801 | This is development-only feature. If you want to cache SSR pages in production, please see [SSR-caching](https://github.com/zeit/next.js/tree/canary/examples/ssr-caching) example.
|
1802 |
|
1803 | #### Configuring extensions looked for when resolving pages in `pages`
|
1804 |
|
1805 | Aimed at modules like [`@next/mdx`](https://github.com/zeit/next.js/tree/canary/packages/next-mdx), that add support for pages ending with `.mdx`. `pageExtensions` allows you to configure the extensions looked for in the `pages` directory when resolving pages.
|
1806 |
|
1807 | ```js
|
1808 | // next.config.js
|
1809 | module.exports = {
|
1810 | pageExtensions: ['mdx', 'jsx', 'js'],
|
1811 | }
|
1812 | ```
|
1813 |
|
1814 | #### Configuring the build ID
|
1815 |
|
1816 | Next.js uses a constant generated at build time to identify which version of your application is being served. This can cause problems in multi-server deployments when `next build` is ran on every server. In order to keep a static build id between builds you can provide the `generateBuildId` function:
|
1817 |
|
1818 | ```js
|
1819 | // next.config.js
|
1820 | module.exports = {
|
1821 | generateBuildId: async () => {
|
1822 | // For example get the latest git commit hash here
|
1823 | return 'my-build-id'
|
1824 | },
|
1825 | }
|
1826 | ```
|
1827 |
|
1828 | To fall back to the default of generating a unique id return `null` from the function:
|
1829 |
|
1830 | ```js
|
1831 | module.exports = {
|
1832 | generateBuildId: async () => {
|
1833 | // When process.env.YOUR_BUILD_ID is undefined we fall back to the default
|
1834 | if (process.env.YOUR_BUILD_ID) {
|
1835 | return process.env.YOUR_BUILD_ID
|
1836 | }
|
1837 |
|
1838 | return null
|
1839 | },
|
1840 | }
|
1841 | ```
|
1842 |
|
1843 | #### Configuring next process script
|
1844 |
|
1845 | You can pass any node arguments to `next` CLI command.
|
1846 |
|
1847 | ```bash
|
1848 | NODE_OPTIONS="--throw-deprecation" next
|
1849 | NODE_OPTIONS="-r esm" next
|
1850 | NODE_OPTIONS="--inspect" next
|
1851 | ```
|
1852 |
|
1853 | ### Customizing webpack config
|
1854 |
|
1855 | <details>
|
1856 | <summary><b>Examples</b></summary>
|
1857 | <ul>
|
1858 | <li><a href="/examples/with-webpack-bundle-analyzer">Custom webpack bundle analyzer</a></li>
|
1859 | </ul>
|
1860 | </details>
|
1861 |
|
1862 | Some commonly asked for features are available as modules:
|
1863 |
|
1864 | - [@zeit/next-css](https://github.com/zeit/next-plugins/tree/master/packages/next-css)
|
1865 | - [@zeit/next-sass](https://github.com/zeit/next-plugins/tree/master/packages/next-sass)
|
1866 | - [@zeit/next-less](https://github.com/zeit/next-plugins/tree/master/packages/next-less)
|
1867 | - [@zeit/next-preact](https://github.com/zeit/next-plugins/tree/master/packages/next-preact)
|
1868 | - [@next/mdx](https://github.com/zeit/next.js/tree/canary/packages/next-mdx)
|
1869 |
|
1870 | > **Warning:** The `webpack` function is executed twice, once for the server and once for the client. This allows you to distinguish between client and server configuration using the `isServer` property.
|
1871 |
|
1872 | Multiple configurations can be combined together with function composition. For example:
|
1873 |
|
1874 | ```js
|
1875 | const withMDX = require('@next/mdx')
|
1876 | const withSass = require('@zeit/next-sass')
|
1877 |
|
1878 | module.exports = withMDX(
|
1879 | withSass({
|
1880 | webpack(config, options) {
|
1881 | // Further custom configuration here
|
1882 | return config
|
1883 | },
|
1884 | })
|
1885 | )
|
1886 | ```
|
1887 |
|
1888 | In order to extend our usage of `webpack`, you can define a function that extends its config via `next.config.js`.
|
1889 |
|
1890 | ```js
|
1891 | // next.config.js is not transformed by Babel. So you can only use javascript features supported by your version of Node.js.
|
1892 |
|
1893 | module.exports = {
|
1894 | webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
|
1895 | // Note: we provide webpack above so you should not `require` it
|
1896 | // Perform customizations to webpack config
|
1897 | // Important: return the modified config
|
1898 |
|
1899 | // Example using webpack option
|
1900 | config.plugins.push(new webpack.IgnorePlugin(/\/__tests__\//))
|
1901 | return config
|
1902 | },
|
1903 | webpackDevMiddleware: config => {
|
1904 | // Perform customizations to webpack dev middleware config
|
1905 | // Important: return the modified config
|
1906 | return config
|
1907 | },
|
1908 | }
|
1909 | ```
|
1910 |
|
1911 | The second argument to `webpack` is an object containing properties useful when customizing its configuration:
|
1912 |
|
1913 | - `buildId` - `String` the build id used as a unique identifier between builds
|
1914 | - `dev` - `Boolean` shows if the compilation is done in development mode
|
1915 | - `isServer` - `Boolean` shows if the resulting configuration will be used for server side (`true`), or client side compilation (`false`)
|
1916 | - `defaultLoaders` - `Object` Holds loader objects Next.js uses internally, so that you can use them in custom configuration
|
1917 | - `babel` - `Object` the `babel-loader` configuration for Next.js
|
1918 |
|
1919 | Example usage of `defaultLoaders.babel`:
|
1920 |
|
1921 | ```js
|
1922 | // Example next.config.js for adding a loader that depends on babel-loader
|
1923 | // This source was taken from the @next/mdx plugin source:
|
1924 | // https://github.com/zeit/next.js/tree/canary/packages/next-mdx
|
1925 | module.exports = {
|
1926 | webpack: (config, options) => {
|
1927 | config.module.rules.push({
|
1928 | test: /\.mdx/,
|
1929 | use: [
|
1930 | options.defaultLoaders.babel,
|
1931 | {
|
1932 | loader: '@mdx-js/loader',
|
1933 | options: pluginOptions.options,
|
1934 | },
|
1935 | ],
|
1936 | })
|
1937 |
|
1938 | return config
|
1939 | },
|
1940 | }
|
1941 | ```
|
1942 |
|
1943 | ### Customizing babel config
|
1944 |
|
1945 | <details>
|
1946 | <summary><b>Examples</b></summary>
|
1947 | <ul>
|
1948 | <li><a href="/examples/with-custom-babel-config">Custom babel configuration</a></li>
|
1949 | </ul>
|
1950 | </details>
|
1951 |
|
1952 | In order to extend our usage of `babel`, you can simply define a `.babelrc` file at the root of your app. This file is optional.
|
1953 |
|
1954 | If found, we're going to consider it the _source of truth_, therefore it needs to define what next needs as well, which is the `next/babel` preset.
|
1955 |
|
1956 | This is designed so that you are not surprised by modifications we could make to the babel configurations.
|
1957 |
|
1958 | Here's an example `.babelrc` file:
|
1959 |
|
1960 | ```json
|
1961 | {
|
1962 | "presets": ["next/babel"],
|
1963 | "plugins": []
|
1964 | }
|
1965 | ```
|
1966 |
|
1967 | The `next/babel` preset includes everything needed to transpile React applications. This includes:
|
1968 |
|
1969 | - preset-env
|
1970 | - preset-react
|
1971 | - preset-typescript
|
1972 | - plugin-proposal-class-properties
|
1973 | - plugin-proposal-object-rest-spread
|
1974 | - plugin-transform-runtime
|
1975 | - styled-jsx
|
1976 |
|
1977 | These presets / plugins **should not** be added to your custom `.babelrc`. Instead, you can configure them on the `next/babel` preset:
|
1978 |
|
1979 | ```json
|
1980 | {
|
1981 | "presets": [
|
1982 | [
|
1983 | "next/babel",
|
1984 | {
|
1985 | "preset-env": {},
|
1986 | "transform-runtime": {},
|
1987 | "styled-jsx": {},
|
1988 | "class-properties": {}
|
1989 | }
|
1990 | ]
|
1991 | ],
|
1992 | "plugins": []
|
1993 | }
|
1994 | ```
|
1995 |
|
1996 | The `modules` option on `"preset-env"` should be kept to `false` otherwise webpack code splitting is disabled.
|
1997 |
|
1998 | ### Exposing configuration to the server / client side
|
1999 |
|
2000 | There is a common need in applications to provide configuration values.
|
2001 |
|
2002 | Next.js supports 2 ways of providing configuration:
|
2003 |
|
2004 | - Build-time configuration
|
2005 | - Runtime configuration
|
2006 |
|
2007 | #### Build-time configuration
|
2008 |
|
2009 | The way build-time configuration works is by inlining the provided values into the Javascript bundle.
|
2010 |
|
2011 | You can add the `env` key in `next.config.js`:
|
2012 |
|
2013 | ```js
|
2014 | // next.config.js
|
2015 | module.exports = {
|
2016 | env: {
|
2017 | customKey: 'value',
|
2018 | },
|
2019 | }
|
2020 | ```
|
2021 |
|
2022 | This will allow you to use `process.env.customKey` in your code. For example:
|
2023 |
|
2024 | ```jsx
|
2025 | // pages/index.js
|
2026 | function Index() {
|
2027 | return <h1>The value of customKey is: {process.env.customKey}</h1>
|
2028 | }
|
2029 |
|
2030 | export default Index
|
2031 | ```
|
2032 |
|
2033 | > **Warning:** Note that it is not possible to destructure process.env variables due to the webpack `DefinePlugin` replacing process.env.XXXX inline at build time.
|
2034 |
|
2035 | ```js
|
2036 | // Will not work
|
2037 | const { CUSTOM_KEY, CUSTOM_SECRET } = process.env
|
2038 | AuthMethod({ key: CUSTOM_KEY, secret: CUSTOM_SECRET })
|
2039 |
|
2040 | // Will work as replaced inline
|
2041 | AuthMethod({ key: process.env.CUSTOM_KEY, secret: process.env.CUSTOM_SECRET })
|
2042 | ```
|
2043 |
|
2044 | #### Runtime configuration
|
2045 |
|
2046 | > **Warning:** Note that these options are not available when using `target: 'serverless'`
|
2047 |
|
2048 | > **Warning:** Generally you want to use build-time configuration to provide your configuration.
|
2049 | > The reason for this is that runtime configuration adds rendering / initialization overhead and is **incompatible with [automatic static optimization](#automatic-static-optimization)**.
|
2050 |
|
2051 | The `next/config` module gives your app access to the `publicRuntimeConfig` and `serverRuntimeConfig` stored in your `next.config.js`.
|
2052 |
|
2053 | Place any server-only runtime config under a `serverRuntimeConfig` property.
|
2054 |
|
2055 | Anything accessible to both client and server-side code should be under `publicRuntimeConfig`.
|
2056 |
|
2057 | > **Note**: A page that relies on `publicRuntimeConfig` **must** use `getInitialProps` to opt-out of [automatic static optimization](#automatic-static-optimization).
|
2058 | > You can also de-optimize your entire application by creating a [Custom `<App>`](#custom-app) with `getInitialProps`.
|
2059 |
|
2060 | ```js
|
2061 | // next.config.js
|
2062 | module.exports = {
|
2063 | serverRuntimeConfig: {
|
2064 | // Will only be available on the server side
|
2065 | mySecret: 'secret',
|
2066 | secondSecret: process.env.SECOND_SECRET, // Pass through env variables
|
2067 | },
|
2068 | publicRuntimeConfig: {
|
2069 | // Will be available on both server and client
|
2070 | staticFolder: '/static',
|
2071 | },
|
2072 | }
|
2073 | ```
|
2074 |
|
2075 | ```js
|
2076 | // pages/index.js
|
2077 | import getConfig from 'next/config'
|
2078 | // Only holds serverRuntimeConfig and publicRuntimeConfig from next.config.js nothing else.
|
2079 | const { serverRuntimeConfig, publicRuntimeConfig } = getConfig()
|
2080 |
|
2081 | console.log(serverRuntimeConfig.mySecret) // Will only be available on the server side
|
2082 | console.log(publicRuntimeConfig.staticFolder) // Will be available on both server and client
|
2083 |
|
2084 | function MyImage() {
|
2085 | return (
|
2086 | <div>
|
2087 | <img src={`${publicRuntimeConfig.staticFolder}/logo.png`} alt="logo" />
|
2088 | </div>
|
2089 | )
|
2090 | }
|
2091 |
|
2092 | export default MyImage
|
2093 | ```
|
2094 |
|
2095 | ### Starting the server on alternative hostname
|
2096 |
|
2097 | To start the development server using a different default hostname you can use `--hostname hostname_here` or `-H hostname_here` option with next dev. This will start a TCP server listening for connections on the provided host.
|
2098 |
|
2099 | ### CDN support with Asset Prefix
|
2100 |
|
2101 | To set up a CDN, you can set up the `assetPrefix` setting and configure your CDN's origin to resolve to the domain that Next.js is hosted on.
|
2102 |
|
2103 | ```js
|
2104 | const isProd = process.env.NODE_ENV === 'production'
|
2105 | module.exports = {
|
2106 | // You may only need to add assetPrefix in the production.
|
2107 | assetPrefix: isProd ? 'https://cdn.mydomain.com' : '',
|
2108 | }
|
2109 | ```
|
2110 |
|
2111 | Note: Next.js will automatically use that prefix in the scripts it loads, but this has no effect whatsoever on `/static`. If you want to serve those assets over the CDN, you'll have to introduce the prefix yourself. One way of introducing a prefix that works inside your components and varies by environment is documented [in this example](https://github.com/zeit/next.js/tree/master/examples/with-universal-configuration-build-time).
|
2112 |
|
2113 | If your CDN is on a separate domain and you would like assets to be requested using a [CORS aware request](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes) you can set a config option for that.
|
2114 |
|
2115 | ```js
|
2116 | // next.config.js
|
2117 | module.exports = {
|
2118 | crossOrigin: 'anonymous',
|
2119 | }
|
2120 | ```
|
2121 |
|
2122 | ## Automatic Static Optimization
|
2123 |
|
2124 | Next.js automatically determines that a page is static (can be prerendered) if it has no blocking data requirements.
|
2125 | This determination is made by the absence of `getInitialProps` in the page.
|
2126 |
|
2127 | If `getInitialProps` is present, Next.js will not statically optimize the page.
|
2128 | Instead, Next.js will use its default behavior and render the page on-demand, per-request (meaning Server-Side Rendering).
|
2129 |
|
2130 | If `getInitialProps` is absent, Next.js will **statically optimize** your page automatically by prerendering it to static HTML. During prerendering, the router's `query` object will be empty since we do not have `query` information to provide during this phase. Any `query` values will be populated client side after hydration.
|
2131 |
|
2132 | This feature allows Next.js to emit hybrid applications that contain **both server-rendered and statically generated pages**.
|
2133 | This ensures Next.js always emits applications that are **fast by default**.
|
2134 |
|
2135 | > **Note**: Statically generated pages are still reactive: Next.js will hydrate your application client-side to give it full interactivity.
|
2136 |
|
2137 | This feature provides many benefits.
|
2138 | For example, optimized pages require no server-side computation and can be instantly streamed to the end-user from CDN locations.
|
2139 |
|
2140 | The result is an _ultra fast_ loading experience for your users.
|
2141 |
|
2142 | `next build` will emit `.html` files for statically optimized pages.
|
2143 | The result will be a file named `.next/server/static/${BUILD_ID}/about.html` instead of `.next/server/static/${BUILD_ID}/about.js`.
|
2144 | This behavior is similar for `target: 'serverless'`.
|
2145 |
|
2146 | The built-in Next.js server (`next start`) and programmatic API (`app.getRequestHandler()`) both support this build output transparently.
|
2147 | There is no configuration or special handling required.
|
2148 |
|
2149 | > **Note**: If you have a [custom `<App>`](#custom-app) with `getInitialProps` then this optimization will be disabled.
|
2150 |
|
2151 | > **Note**: If you have a [custom `<Document>`](#custom-document) with `getInitialProps` be sure you check if `ctx.req` is defined before assuming the page is server-side rendered.
|
2152 | > `ctx.req` will be `undefined` for pages that are prerendered.
|
2153 |
|
2154 | ## Automatic Static Optimization Indicator
|
2155 |
|
2156 | When a page qualifies for automatic static optimization we show an indicator to let you know.
|
2157 | This is helpful since the automatic static optimization can be very beneficial and knowing immediately in development if it qualifies can be useful.
|
2158 | See above for information on the benefits of this optimization.
|
2159 |
|
2160 | In some cases this indicator might not be as useful like when working on electron applications. For these cases you can disable the indicator in your `next.config.js` by setting
|
2161 |
|
2162 | ```js
|
2163 | module.exports = {
|
2164 | devIndicators: {
|
2165 | autoPrerender: false,
|
2166 | },
|
2167 | }
|
2168 | ```
|
2169 |
|
2170 | ## Production deployment
|
2171 |
|
2172 | To deploy, instead of running `next`, you want to build for production usage ahead of time. Therefore, building and starting are separate commands:
|
2173 |
|
2174 | ```bash
|
2175 | next build
|
2176 | next start
|
2177 | ```
|
2178 |
|
2179 | To deploy Next.js with [ZEIT Now](https://zeit.co/now) see the [ZEIT Guide for Deploying Next.js](https://zeit.co/guides/deploying-nextjs-with-now/) or the [Next.js Learn section about deploying on ZEIT Now](https://nextjs.org/learn/basics/deploying-a-nextjs-app/deploying-to-zeit-now).
|
2180 |
|
2181 | Next.js can be deployed to other hosting solutions too. Please have a look at the ['Deployment'](https://github.com/zeit/next.js/wiki/Deployment) section of the wiki.
|
2182 |
|
2183 | Note: `NODE_ENV` is properly configured by the `next` subcommands, if absent, to maximize performance. if you’re using Next.js [programmatically](#custom-server-and-routing), it’s your responsibility to set `NODE_ENV=production` manually!
|
2184 |
|
2185 | Note: we recommend putting `.next`, or your [custom dist folder](https://github.com/zeit/next.js#custom-configuration), in `.gitignore` or `.npmignore`. Otherwise, use `files` or `now.files` to opt-into a whitelist of files you want to deploy, excluding `.next` or your custom dist folder.
|
2186 |
|
2187 | ### Compression
|
2188 |
|
2189 | Next.js provides [gzip](https://tools.ietf.org/html/rfc6713#section-3) compression to compress rendered content and static files. Compression only works with the `server` target. In general you will want to enable compression on a HTTP proxy like [nginx](https://www.nginx.com/), to offload load from the `Node.js` process.
|
2190 |
|
2191 | To disable **compression** in Next.js, set `compress` to `false` in `next.config.js`:
|
2192 |
|
2193 | ```js
|
2194 | // next.config.js
|
2195 | module.exports = {
|
2196 | compress: false,
|
2197 | }
|
2198 | ```
|
2199 |
|
2200 | ### Serverless deployment
|
2201 |
|
2202 | <details>
|
2203 | <summary><b>Examples</b></summary>
|
2204 | <ul>
|
2205 | <li><a href="https://github.com/zeit/now-examples/tree/master/nextjs">now.sh</a></li>
|
2206 | <li><a href="https://github.com/TejasQ/anna-artemov.now.sh">anna-artemov.now.sh</a></li>
|
2207 | <li>We encourage contributing more examples to this section</li>
|
2208 | </ul>
|
2209 | </details>
|
2210 |
|
2211 | Serverless deployment dramatically improves reliability and scalability by splitting your application into smaller parts (also called [**lambdas**](https://zeit.co/docs/v2/deployments/concepts/lambdas/)).
|
2212 | In the case of Next.js, each page in the `pages` directory becomes a serverless lambda.
|
2213 |
|
2214 | There are [a number of benefits](https://zeit.co/blog/serverless-express-js-lambdas-with-now-2#benefits-of-serverless-express) to serverless.
|
2215 | The referenced link talks about some of them in the context of Express, but the principles apply universally:
|
2216 | serverless allows for distributed points of failure, infinite scalability, and is incredibly affordable with a "pay for what you use" model.
|
2217 |
|
2218 | To enable **serverless mode** in Next.js, add the `serverless` build `target` in `next.config.js`:
|
2219 |
|
2220 | ```js
|
2221 | // next.config.js
|
2222 | module.exports = {
|
2223 | target: 'serverless',
|
2224 | }
|
2225 | ```
|
2226 |
|
2227 | The `serverless` target will output a single lambda or [HTML file](#automatic-static-optimization) per page.
|
2228 | This file is completely standalone and doesn't require any dependencies to run:
|
2229 |
|
2230 | - `pages/index.js` => `.next/serverless/pages/index.js`
|
2231 | - `pages/about.js` => `.next/serverless/pages/about.js`
|
2232 | - `pages/blog.js` => `.next/serverless/pages/blog.html`
|
2233 |
|
2234 | The signature of the Next.js Serverless function is similar to the Node.js HTTP server callback:
|
2235 |
|
2236 | ```ts
|
2237 | export function render(req: http.IncomingMessage, res: http.ServerResponse) => void
|
2238 | ```
|
2239 |
|
2240 | - [http.IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage)
|
2241 | - [http.ServerResponse](https://nodejs.org/api/http.html#http_class_http_serverresponse)
|
2242 | - `void` refers to the function not having a return value and is equivalent to JavaScript's `undefined`. Calling the function will finish the request.
|
2243 |
|
2244 | The static HTML files are ready to be served as-is.
|
2245 | You can read more about this feature, including how to opt-out, in the [Automatic Static Optimization section](#automatic-static-optimization).
|
2246 |
|
2247 | Using the serverless target, you can deploy Next.js to [ZEIT Now](https://zeit.co/now) with all of the benefits and added ease of control like for example; [custom routes](https://zeit.co/guides/custom-next-js-server-to-routes/) and caching headers. See the [ZEIT Guide for Deploying Next.js with Now](https://zeit.co/guides/deploying-nextjs-with-now/) for more information.
|
2248 |
|
2249 | #### One Level Lower
|
2250 |
|
2251 | Next.js provides low-level APIs for serverless deployments as hosting platforms have different function signatures. In general you will want to wrap the output of a Next.js serverless build with a compatibility layer.
|
2252 |
|
2253 | For example if the platform supports the Node.js [`http.Server`](https://nodejs.org/api/http.html#http_class_http_server) class:
|
2254 |
|
2255 | ```js
|
2256 | const http = require('http')
|
2257 | const page = require('./.next/serverless/pages/about.js')
|
2258 | const server = new http.Server((req, res) => page.render(req, res))
|
2259 | server.listen(3000, () => console.log('Listening on http://localhost:3000'))
|
2260 | ```
|
2261 |
|
2262 | For specific platform examples see [the examples section above](#serverless-deployment).
|
2263 |
|
2264 | #### Summary
|
2265 |
|
2266 | - Low-level API for implementing serverless deployment
|
2267 | - Every page in the `pages` directory becomes a serverless function (lambda)
|
2268 | - Creates the smallest possible serverless function (50Kb base zip size)
|
2269 | - Optimized for fast [cold start](https://zeit.co/blog/serverless-ssr#cold-start) of the function
|
2270 | - The serverless function has 0 dependencies (they are included in the function bundle)
|
2271 | - Uses the [http.IncomingMessage](https://nodejs.org/api/http.html#http_class_http_incomingmessage) and [http.ServerResponse](https://nodejs.org/api/http.html#http_class_http_serverresponse) from Node.js
|
2272 | - opt-in using `target: 'serverless'` in `next.config.js`
|
2273 | - Does not load `next.config.js` when executing the function, note that this means `publicRuntimeConfig` / `serverRuntimeConfig` are not supported
|
2274 |
|
2275 | ## Browser support
|
2276 |
|
2277 | Next.js supports IE11 and all modern browsers out of the box using [`@babel/preset-env`](https://new.babeljs.io/docs/en/next/babel-preset-env.html). In order to support IE11 Next.js adds a global `Promise` polyfill. In cases where your own code or any external NPM dependencies you are using requires features not supported by your target browsers you will need to implement polyfills.
|
2278 |
|
2279 | The [polyfills](https://github.com/zeit/next.js/tree/canary/examples/with-polyfills) example demonstrates the recommended approach to implement polyfills.
|
2280 |
|
2281 | ## TypeScript
|
2282 |
|
2283 | Next.js provides an integrated TypeScript experience out of the box, similar to an IDE.
|
2284 |
|
2285 | To get started, create a empty `tsconfig.json` file in the root of your project:
|
2286 |
|
2287 | ```bash
|
2288 | touch tsconfig.json
|
2289 | ```
|
2290 |
|
2291 | Next.js will automatically configure this file with default values (providing [your own `tsconfig.json`](https://www.typescriptlang.org/docs/handbook/compiler-options.html) is also supported).
|
2292 |
|
2293 | Then, run `next dev` (normally `npm run dev`) and Next.js will guide you through installing the necessary packages to complete setup.
|
2294 |
|
2295 | ```bash
|
2296 | npm run dev
|
2297 |
|
2298 | # You'll see instructions like these:
|
2299 | #
|
2300 | # Please install typescript, @types/react, and @types/node by running:
|
2301 | #
|
2302 | # yarn add --dev typescript @types/react @types/node
|
2303 | #
|
2304 | # ...
|
2305 | ```
|
2306 |
|
2307 | You're now ready to start converting files from `.js` to `.tsx` and leveraging the benefits TypeScript provides!
|
2308 |
|
2309 | To learn more about TypeScript checkout its [documentation](https://www.typescriptlang.org/).
|
2310 |
|
2311 | > **Note**: Next.js will create a file named `next-env.d.ts` in the root of your project.
|
2312 | > This file ensures Next.js' types are picked up by the TypeScript compiler.
|
2313 | >
|
2314 | > **You cannot remove this file, however, you can edit it (but don't need to).**
|
2315 |
|
2316 | > **Note**: Next.js does not enable TypeScript's `strict` mode by default.
|
2317 | > When you feel comfortable with TypeScript, you may turn this option on in your `tsconfig.json`.
|
2318 |
|
2319 | > **Note**: By default, Next.js reports TypeScript errors during development for pages you are actively working on.
|
2320 | > TypeScript errors for inactive pages **do not** block the development process.
|
2321 | >
|
2322 | > If you don't want to leverage this behavior and instead, e.g. prefer your editor's integration, you can set the following option in `next.config.js`:
|
2323 | >
|
2324 | > ```js
|
2325 | > // next.config.js
|
2326 | > module.exports = {
|
2327 | > typescript: {
|
2328 | > ignoreDevErrors: true,
|
2329 | > },
|
2330 | > }
|
2331 | > ```
|
2332 | >
|
2333 | > Next.js will still fail your **production build** (`next build`) when TypeScript errors are present in your project.
|
2334 | >
|
2335 | > If you'd like Next.js to dangerously produce production code even when your application is broken, you can set the following option in your `next.config.js`.
|
2336 | > Be sure you are running type checks as part of your build or deploy process!
|
2337 | >
|
2338 | > ```js
|
2339 | > // next.config.js
|
2340 | > module.exports = {
|
2341 | > typescript: {
|
2342 | > // !! WARN !!
|
2343 | > // Dangerously allow production builds to successfully complete even if
|
2344 | > // your project has type errors.
|
2345 | > //
|
2346 | > // This option is rarely needed, and should be reserved for advanced
|
2347 | > // setups. You may be looking for `ignoreDevErrors` instead.
|
2348 | > // !! WARN !!
|
2349 | > ignoreBuildErrors: true,
|
2350 | > },
|
2351 | > }
|
2352 | > ```
|
2353 |
|
2354 | ### Exported types
|
2355 |
|
2356 | Next.js provides `NextPage` type that can be used for pages in the `pages` directory. `NextPage` adds definitions for [`getInitialProps`](#fetching-data-and-component-lifecycle) so that it can be used without any extra typing needed.
|
2357 |
|
2358 | ```tsx
|
2359 | import { NextPage } from 'next'
|
2360 |
|
2361 | interface Props {
|
2362 | userAgent?: string
|
2363 | }
|
2364 |
|
2365 | const Page: NextPage<Props> = ({ userAgent }) => (
|
2366 | <main>Your user agent: {userAgent}</main>
|
2367 | )
|
2368 |
|
2369 | Page.getInitialProps = async ({ req }) => {
|
2370 | const userAgent = req ? req.headers['user-agent'] : navigator.userAgent
|
2371 | return { userAgent }
|
2372 | }
|
2373 |
|
2374 | export default Page
|
2375 | ```
|
2376 |
|
2377 | For `React.Component` you can use `NextPageContext`:
|
2378 |
|
2379 | ```tsx
|
2380 | import React from 'react'
|
2381 | import { NextPageContext } from 'next'
|
2382 |
|
2383 | interface Props {
|
2384 | userAgent?: string
|
2385 | }
|
2386 |
|
2387 | export default class Page extends React.Component<Props> {
|
2388 | static async getInitialProps({ req }: NextPageContext) {
|
2389 | const userAgent = req ? req.headers['user-agent'] : navigator.userAgent
|
2390 | return { userAgent }
|
2391 | }
|
2392 |
|
2393 | render() {
|
2394 | const { userAgent } = this.props
|
2395 | return <main>Your user agent: {userAgent}</main>
|
2396 | }
|
2397 | }
|
2398 | ```
|
2399 |
|
2400 | ## AMP Support
|
2401 |
|
2402 | <details>
|
2403 | <summary><b>Examples</b></summary>
|
2404 | <ul>
|
2405 | <li><a href="https://github.com/zeit/next.js/tree/canary/examples/amp">amp</a></li>
|
2406 | </ul>
|
2407 | </details>
|
2408 |
|
2409 | ### Enabling AMP Support
|
2410 |
|
2411 | To enable AMP support for a page, add `export const config = { amp: true }` to your page.
|
2412 |
|
2413 | ### AMP First Page
|
2414 |
|
2415 | ```js
|
2416 | // pages/about.js
|
2417 | export const config = { amp: true }
|
2418 |
|
2419 | export default function AboutPage(props) {
|
2420 | return <h3>My AMP About Page!</h3>
|
2421 | }
|
2422 | ```
|
2423 |
|
2424 | ### Hybrid AMP Page
|
2425 |
|
2426 | ```js
|
2427 | // pages/hybrid-about.js
|
2428 | import { useAmp } from 'next/amp'
|
2429 |
|
2430 | export const config = { amp: 'hybrid' }
|
2431 |
|
2432 | export default function AboutPage(props) {
|
2433 | return (
|
2434 | <div>
|
2435 | <h3>My AMP Page</h3>
|
2436 | {useAmp() ? (
|
2437 | <amp-img
|
2438 | width="300"
|
2439 | height="300"
|
2440 | src="/my-img.jpg"
|
2441 | alt="a cool image"
|
2442 | layout="responsive"
|
2443 | />
|
2444 | ) : (
|
2445 | <img width="300" height="300" src="/my-img.jpg" alt="a cool image" />
|
2446 | )}
|
2447 | </div>
|
2448 | )
|
2449 | }
|
2450 | ```
|
2451 |
|
2452 | ### AMP Page Modes
|
2453 |
|
2454 | AMP pages can specify two modes:
|
2455 |
|
2456 | - AMP-only (default)
|
2457 | - Pages have no Next.js or React client-side runtime
|
2458 | - Pages are automatically optimized with [AMP Optimizer](https://github.com/ampproject/amp-toolbox/tree/master/packages/optimizer), an optimizer that applies the same transformations as AMP caches (improves performance by up to 42%)
|
2459 | - Pages have a user-accessible (optimized) version of the page and a search-engine indexable (unoptimized) version of the page
|
2460 | - Opt-in via `export const config = { amp: true }`
|
2461 | - Hybrid
|
2462 | - Pages are able to be rendered as traditional HTML (default) and AMP HTML (by adding `?amp=1` to the URL)
|
2463 | - The AMP version of the page only has valid optimizations applied with AMP Optimizer so that it is indexable by search-engines
|
2464 | - Opt-in via `export const config = { amp: 'hybrid' }`
|
2465 | - Able to differentiate between modes using `useAmp` from `next/amp`
|
2466 |
|
2467 | Both of these page modes provide a consistently fast experience for users accessing pages through search engines.
|
2468 |
|
2469 | ### AMP Behavior with `next export`
|
2470 |
|
2471 | When using `next export` to statically prerender pages Next.js will detect if the page supports AMP and change the exporting behavior based on that.
|
2472 |
|
2473 | Hybrid AMP (`pages/about.js`) would output:
|
2474 |
|
2475 | - `out/about.html` - with client-side React runtime
|
2476 | - `out/about.amp.html` - AMP page
|
2477 |
|
2478 | AMP-only (`pages/about.js`) would output:
|
2479 |
|
2480 | - `out/about.html` - Optimized AMP page
|
2481 |
|
2482 | During export Next.js automatically detects if a page is hybrid AMP and outputs the AMP version to `page.amp.html`. We also automatically insert the `<link rel="amphtml" href="/page.amp" />` and `<link rel="canonical" href="/" />` tags for you.
|
2483 |
|
2484 | > **Note**: When using `exportTrailingSlash: true` in `next.config.js`, output will be different. For Hybrid AMP pages, output will be `out/page/index.html` and `out/page.amp/index.html`, and for AMP-only pages, output will be `out/page/index.html`
|
2485 |
|
2486 | ### Adding AMP Components
|
2487 |
|
2488 | The AMP community provides [many components](https://amp.dev/documentation/components/) to make AMP pages more interactive. You can add these components to your page by using `next/head`:
|
2489 |
|
2490 | ```js
|
2491 | // pages/hello.js
|
2492 | import Head from 'next/head'
|
2493 |
|
2494 | export const config = { amp: true }
|
2495 |
|
2496 | export default function MyAmpPage() {
|
2497 | return (
|
2498 | <div>
|
2499 | <Head>
|
2500 | <script
|
2501 | async
|
2502 | key="amp-timeago"
|
2503 | custom-element="amp-timeago"
|
2504 | src="https://cdn.ampproject.org/v0/amp-timeago-0.1.js"
|
2505 | />
|
2506 | </Head>
|
2507 |
|
2508 | <p>Some time: {date.toJSON()}</p>
|
2509 | <amp-timeago
|
2510 | width="0"
|
2511 | height="15"
|
2512 | datetime={date.toJSON()}
|
2513 | layout="responsive"
|
2514 | >
|
2515 | .
|
2516 | </amp-timeago>
|
2517 | </div>
|
2518 | )
|
2519 | }
|
2520 | ```
|
2521 |
|
2522 | ### AMP Validation
|
2523 |
|
2524 | AMP pages are automatically validated with [amphtml-validator](https://www.npmjs.com/package/amphtml-validator) during development. Errors and warnings will appear in the terminal where you started Next.js.
|
2525 |
|
2526 | Pages are also validated during `next export` and any warnings / errors will be printed to the terminal.
|
2527 | Any AMP errors will cause `next export` to exit with status code `1` because the export is not valid AMP.
|
2528 |
|
2529 | ### TypeScript Support
|
2530 |
|
2531 | AMP currently doesn't have built-in types for TypeScript, but it's in their roadmap ([#13791](https://github.com/ampproject/amphtml/issues/13791)). As a workaround you can manually add the types to `amp.d.ts` like [here](https://stackoverflow.com/a/50601125).
|
2532 |
|
2533 | ## Static HTML export
|
2534 |
|
2535 | <details>
|
2536 | <summary><b>Examples</b></summary>
|
2537 | <ul>
|
2538 | <li><a href="/examples/with-static-export">Static export</a></li>
|
2539 | </ul>
|
2540 | </details>
|
2541 |
|
2542 | `next export` is a way to run your Next.js app as a standalone static app without the need for a Node.js server.
|
2543 | The exported app supports almost every feature of Next.js, including dynamic urls, prefetching, preloading and dynamic imports.
|
2544 |
|
2545 | The way `next export` works is by prerendering all pages possible to HTML. It does so based on a mapping of `pathname` key to page object. This mapping is called the `exportPathMap`.
|
2546 |
|
2547 | The page object has 2 values:
|
2548 |
|
2549 | - `page` - `String` the page inside the `pages` directory to render
|
2550 | - `query` - `Object` the `query` object passed to `getInitialProps` when prerendering. Defaults to `{}`
|
2551 |
|
2552 | ### Usage
|
2553 |
|
2554 | Simply develop your app as you normally do with Next.js. Then run:
|
2555 |
|
2556 | ```
|
2557 | next build
|
2558 | next export
|
2559 | ```
|
2560 |
|
2561 | By default `next export` doesn't require any configuration. It will generate a default `exportPathMap` containing the routes to pages inside the `pages` directory. This default mapping is available as `defaultPathMap` in the example below.
|
2562 |
|
2563 | If your application has dynamic routes you can add a dynamic `exportPathMap` in `next.config.js`.
|
2564 | This function is asynchronous and gets the default `exportPathMap` as a parameter.
|
2565 |
|
2566 | ```js
|
2567 | // next.config.js
|
2568 | module.exports = {
|
2569 | exportPathMap: async function(
|
2570 | defaultPathMap,
|
2571 | { dev, dir, outDir, distDir, buildId }
|
2572 | ) {
|
2573 | return {
|
2574 | '/': { page: '/' },
|
2575 | '/about': { page: '/about' },
|
2576 | '/readme.md': { page: '/readme' },
|
2577 | '/p/hello-nextjs': { page: '/post', query: { title: 'hello-nextjs' } },
|
2578 | '/p/learn-nextjs': { page: '/post', query: { title: 'learn-nextjs' } },
|
2579 | '/p/deploy-nextjs': { page: '/post', query: { title: 'deploy-nextjs' } },
|
2580 | }
|
2581 | },
|
2582 | }
|
2583 | ```
|
2584 |
|
2585 | The pages will be exported as html files, i.e. `/about` will become `/about.html`.
|
2586 |
|
2587 | It is possible to configure Next.js to export pages as `index.html` files and require trailing slashes, i.e. `/about` becomes `/about/index.html` and is routable via `/about/`.
|
2588 | This was the default behavior prior to Next.js 9.
|
2589 | You can use the following `next.config.js` to switch back to this behavior:
|
2590 |
|
2591 | ```js
|
2592 | // next.config.js
|
2593 | module.exports = {
|
2594 | exportTrailingSlash: true,
|
2595 | }
|
2596 | ```
|
2597 |
|
2598 | > **Note**: If the export path is a filename (e.g. `/readme.md`) and is different than `.html`, you may need to set the `Content-Type` header to `text/html` when serving this content.
|
2599 |
|
2600 | The second argument is an `object` with:
|
2601 |
|
2602 | - `dev` - `true` when `exportPathMap` is being called in development. `false` when running `next export`. In development `exportPathMap` is used to define routes.
|
2603 | - `dir` - Absolute path to the project directory
|
2604 | - `outDir` - Absolute path to the `out/` directory (configurable with `-o` or `--outdir`). When `dev` is `true` the value of `outDir` will be `null`.
|
2605 | - `distDir` - Absolute path to the `.next/` directory (configurable using the `distDir` config key)
|
2606 | - `buildId` - The `buildId` the export is running for
|
2607 |
|
2608 | Then simply run these commands:
|
2609 |
|
2610 | ```bash
|
2611 | next build
|
2612 | next export
|
2613 | ```
|
2614 |
|
2615 | For that you may need to add a NPM script to `package.json` like this:
|
2616 |
|
2617 | ```json
|
2618 | {
|
2619 | "scripts": {
|
2620 | "build": "next build",
|
2621 | "export": "npm run build && next export"
|
2622 | }
|
2623 | }
|
2624 | ```
|
2625 |
|
2626 | And run it at once with:
|
2627 |
|
2628 | ```bash
|
2629 | npm run export
|
2630 | ```
|
2631 |
|
2632 | Then you have a static version of your app in the `out` directory.
|
2633 |
|
2634 | > You can also customize the output directory. For that run `next export -h` for the help.
|
2635 |
|
2636 | Now you can deploy the `out` directory to any static hosting service. Note that there is an additional step for deploying to GitHub Pages, [documented here](https://github.com/zeit/next.js/wiki/Deploying-a-Next.js-app-into-GitHub-Pages).
|
2637 |
|
2638 | For an example, simply visit the `out` directory and run following command to deploy your app to [ZEIT Now](https://zeit.co/now).
|
2639 |
|
2640 | ```bash
|
2641 | now
|
2642 | ```
|
2643 |
|
2644 | ### Limitation
|
2645 |
|
2646 | With `next export`, we build a HTML version of your app. At export time we will run `getInitialProps` of your pages.
|
2647 |
|
2648 | The `req` and `res` fields of the `context` object passed to `getInitialProps` are empty objects during export as there is no server running.
|
2649 |
|
2650 | > **Note**: If your pages don't have `getInitialProps` you may not need `next export` at all, `next build` is already enough thanks to [automatic static optimization](#automatic-static-optimization).
|
2651 |
|
2652 | > You won't be able to render HTML dynamically when static exporting, as we pre-build the HTML files. If you want to do dynamic rendering use `next start` or the custom server API
|
2653 |
|
2654 | ## Multi Zones
|
2655 |
|
2656 | <details>
|
2657 | <summary><b>Examples</b></summary>
|
2658 | <ul>
|
2659 | <li><a href="/examples/with-zones">With Zones</a></li>
|
2660 | </ul>
|
2661 | </details>
|
2662 |
|
2663 | A zone is a single deployment of a Next.js app. Just like that, you can have multiple zones and then you can merge them as a single app.
|
2664 |
|
2665 | For an example, you can have two zones like this:
|
2666 |
|
2667 | - An app for serving `/blog/**`
|
2668 | - Another app for serving all other pages
|
2669 |
|
2670 | With multi zones support, you can merge both these apps into a single one allowing your customers to browse it using a single URL, but you can develop and deploy both apps independently.
|
2671 |
|
2672 | > This is exactly the same concept of microservices, but for frontend apps.
|
2673 |
|
2674 | ### How to define a zone
|
2675 |
|
2676 | There are no special zones related APIs. You only need to do following:
|
2677 |
|
2678 | - Make sure to keep only the pages you need in your app, meaning that an app can't have pages from another app, if app `A` has `/blog` then app `B` shouldn't have it too.
|
2679 | - Make sure to add an [assetPrefix](https://github.com/zeit/next.js#cdn-support-with-asset-prefix) to avoid conflicts with static files.
|
2680 |
|
2681 | ### How to merge them
|
2682 |
|
2683 | You can merge zones using any HTTP proxy.
|
2684 |
|
2685 | You can use [now dev](https://zeit.co/docs/v2/development/basics) as your local development server. It allows you to easily define routing routes for multiple apps like below:
|
2686 |
|
2687 | ```json
|
2688 | {
|
2689 | "version": 2,
|
2690 | "builds": [
|
2691 | { "src": "docs/next.config.js", "use": "@now/next" },
|
2692 | { "src": "home/next.config.js", "use": "@now/next" }
|
2693 | ],
|
2694 | "routes": [
|
2695 | { "src": "/docs(.*)", "dest": "docs$1", "continue": true },
|
2696 | { "src": "(?!/?docs)(.*)", "dest": "home$1", "continue": true }
|
2697 | ]
|
2698 | }
|
2699 | ```
|
2700 |
|
2701 | For the production deployment, you can use the same configuration and run `now` to do the deployment with [ZEIT Now](https://zeit.co/now). Otherwise you can also configure a proxy server to route using a set of routes like the ones above, e.g deploy the docs app to `https://docs.example.com` and the home app to `https://home.example.com` and then add a proxy server for both apps in `https://example.com`.
|
2702 |
|
2703 | ## FAQ
|
2704 |
|
2705 | <details>
|
2706 | <summary>Is this production ready?</summary>
|
2707 | Next.js has been powering https://zeit.co since its inception.
|
2708 |
|
2709 | We’re ecstatic about both the developer experience and end-user performance, so we decided to share it with the community.
|
2710 |
|
2711 | </details>
|
2712 |
|
2713 | <details>
|
2714 | <summary>How big is it?</summary>
|
2715 |
|
2716 | The client side bundle size should be measured in a per-app basis.
|
2717 | A small Next main bundle is around 65kb gzipped.
|
2718 |
|
2719 | </details>
|
2720 |
|
2721 | <details>
|
2722 | <summary>Is this like `create-react-app`?</summary>
|
2723 |
|
2724 | Yes and No.
|
2725 |
|
2726 | Yes in that both make your life easier.
|
2727 |
|
2728 | No in that it enforces a _structure_ so that we can do more advanced things like:
|
2729 |
|
2730 | - Server side rendering
|
2731 | - Automatic code splitting
|
2732 |
|
2733 | In addition, Next.js provides two built-in features that are critical for every single website:
|
2734 |
|
2735 | - Routing with lazy component loading: `<Link>` (by importing `next/link`)
|
2736 | - A way for components to alter `<head>`: `<Head>` (by importing `next/head`)
|
2737 |
|
2738 | If you want to create re-usable React components that you can embed in your Next.js app or other React applications, using `create-react-app` is a great idea. You can later `import` it and keep your codebase clean!
|
2739 |
|
2740 | </details>
|
2741 |
|
2742 | <details>
|
2743 | <summary>How do I use CSS-in-JS solutions?</summary>
|
2744 |
|
2745 | Next.js bundles [styled-jsx](https://github.com/zeit/styled-jsx) supporting scoped css. However you can use any CSS-in-JS solution in your Next app by just including your favorite library [as mentioned before](#css-in-js) in the document.
|
2746 |
|
2747 | </details>
|
2748 |
|
2749 | <details>
|
2750 | <summary>What syntactic features are transpiled? How do I change them?</summary>
|
2751 |
|
2752 | We track V8. Since V8 has wide support for ES6 and `async` and `await`, we transpile those. Since V8 doesn’t support class decorators, we don’t transpile those.
|
2753 |
|
2754 | See the documentation about [customizing the babel config](#customizing-babel-config) and [next/preset](/packages/next/build/babel/preset.ts) for more information.
|
2755 |
|
2756 | </details>
|
2757 |
|
2758 | <details>
|
2759 | <summary>Why a new Router?</summary>
|
2760 |
|
2761 | Next.js is special in that:
|
2762 |
|
2763 | - Routes don’t need to be known ahead of time
|
2764 | - Routes are always lazy-loadable
|
2765 | - Top-level components can define `getInitialProps` that should _block_ the loading of the route (either when server-rendering or lazy-loading)
|
2766 |
|
2767 | As a result, we were able to introduce a very simple approach to routing that consists of two pieces:
|
2768 |
|
2769 | - Every top level component receives a `url` object to inspect the url or perform modifications to the history
|
2770 | - A `<Link />` component is used to wrap elements like anchors (`<a/>`) to perform client-side transitions
|
2771 |
|
2772 | </details>
|
2773 |
|
2774 | <details>
|
2775 | <summary>How do I define a custom fancy route?</summary>
|
2776 |
|
2777 | Next.js provide [dynamic routing](#dynamic-routing) solution out of the box. This allows to use pretty links in url.
|
2778 |
|
2779 | You can check an [example](https://github.com/zeit/next.js/tree/canary/examples/dynamic-routing) to see how it works.
|
2780 |
|
2781 | </details>
|
2782 |
|
2783 | <details>
|
2784 | <summary>How do I fetch data?</summary>
|
2785 |
|
2786 | It’s up to you. `getInitialProps` is an `async` function (or a regular function that returns a `Promise`). It can retrieve data from anywhere.
|
2787 |
|
2788 | </details>
|
2789 |
|
2790 | <details>
|
2791 | <summary>Can I use it with GraphQL?</summary>
|
2792 |
|
2793 | Yes! Here's an example with [Apollo](/examples/with-apollo).
|
2794 |
|
2795 | </details>
|
2796 |
|
2797 | <details>
|
2798 | <summary>Can I use it with Redux and thunk?</summary>
|
2799 |
|
2800 | Yes! Here's an [example](/examples/with-redux-thunk).
|
2801 |
|
2802 | </details>
|
2803 |
|
2804 | <details>
|
2805 | <summary>Can I use it with Redux?</summary>
|
2806 |
|
2807 | Yes! Here's an [example](/examples/with-redux).
|
2808 |
|
2809 | </details>
|
2810 |
|
2811 | <details>
|
2812 | <summary>Can I use Next with my favorite Javascript library or toolkit?</summary>
|
2813 |
|
2814 | Since our first release we've had **many** example contributions, you can check them out in the [examples](/examples) directory.
|
2815 |
|
2816 | </details>
|
2817 |
|
2818 | <details>
|
2819 | <summary>What is this inspired by?</summary>
|
2820 |
|
2821 | Many of the goals we set out to accomplish were the ones listed in [The 7 principles of Rich Web Applications](http://rauchg.com/2014/7-principles-of-rich-web-applications/) by Guillermo Rauch.
|
2822 |
|
2823 | The ease-of-use of PHP is a great inspiration. We feel Next.js is a suitable replacement for many scenarios where you otherwise would use PHP to output HTML.
|
2824 |
|
2825 | Unlike PHP, we benefit from the ES6 module system and every file exports a **component or function** that can be easily imported for lazy evaluation or testing.
|
2826 |
|
2827 | As we were researching options for server-rendering React that didn’t involve a large number of steps, we came across [react-page](https://github.com/facebookarchive/react-page) (now deprecated), a similar approach to Next.js by the creator of React Jordan Walke.
|
2828 |
|
2829 | </details>
|
2830 |
|
2831 | ## Contributing
|
2832 |
|
2833 | Please see our [contributing.md](/contributing.md).
|
2834 |
|
2835 | ## Authors
|
2836 |
|
2837 | - Arunoda Susiripala ([@arunoda](https://twitter.com/arunoda)) – [ZEIT](https://zeit.co)
|
2838 | - Tim Neutkens ([@timneutkens](https://twitter.com/timneutkens)) – [ZEIT](https://zeit.co)
|
2839 | - Naoyuki Kanezawa ([@nkzawa](https://twitter.com/nkzawa)) – [ZEIT](https://zeit.co)
|
2840 | - Tony Kovanen ([@tonykovanen](https://twitter.com/tonykovanen)) – [ZEIT](https://zeit.co)
|
2841 | - Guillermo Rauch ([@rauchg](https://twitter.com/rauchg)) – [ZEIT](https://zeit.co)
|
2842 | - Dan Zajdband ([@impronunciable](https://twitter.com/impronunciable)) – Knight-Mozilla / Coral Project
|