2016-10-05 23:35:00 +00:00
|
|
|
# next.js
|
|
|
|
|
|
|
|
`Next.js` is a minimalistic framework for server-rendered React applications.
|
|
|
|
|
|
|
|
## How to use
|
|
|
|
|
|
|
|
The file-system is the main API. Every `.js` file becomes a route that gets automatically processed and rendered.
|
|
|
|
|
2016-10-05 23:36:18 +00:00
|
|
|
Populate `./pages/index.js` inside your project:
|
2016-10-05 23:35:00 +00:00
|
|
|
|
2016-10-05 23:58:36 +00:00
|
|
|
```jsx
|
2016-10-05 23:35:00 +00:00
|
|
|
import React from 'react'
|
|
|
|
export default () => (
|
|
|
|
<div>Welcome to next.js!</div>
|
|
|
|
)
|
|
|
|
```
|
|
|
|
|
|
|
|
and then just run `next` and go to `http://localhost:3000`
|
|
|
|
|
|
|
|
So far, we get:
|
|
|
|
|
|
|
|
- Automatic transpilation and bundling (with webpack and babel)
|
|
|
|
- Hot code reloading
|
2016-10-05 23:36:18 +00:00
|
|
|
- Server rendering and indexing of `./pages`
|
|
|
|
- Static file serving. `./static/` is mapped to `/static/`
|
2016-10-05 23:35:00 +00:00
|
|
|
|
|
|
|
### Bundling (code splitting)
|
|
|
|
|
|
|
|
Every `import` you declare gets bundled and served with each page
|
|
|
|
|
2016-10-05 23:58:36 +00:00
|
|
|
```jsx
|
2016-10-05 23:35:00 +00:00
|
|
|
import React from 'react'
|
2016-10-14 21:13:46 +00:00
|
|
|
import cowsay from 'cowsay-browser'
|
2016-10-05 23:35:00 +00:00
|
|
|
export default () => (
|
2016-10-14 21:13:46 +00:00
|
|
|
<pre>{ cowsay({ text: 'hi there!' }) }</pre>
|
2016-10-05 23:35:00 +00:00
|
|
|
)
|
|
|
|
```
|
|
|
|
|
|
|
|
That means pages never load unneccessary code!
|
|
|
|
|
|
|
|
### CSS
|
|
|
|
|
|
|
|
We use [Aphrodite](https://github.com/Khan/aphrodite) to provide a great built-in solution for CSS modularization
|
|
|
|
|
2016-10-05 23:58:36 +00:00
|
|
|
```jsx
|
2016-10-05 23:35:00 +00:00
|
|
|
import React from 'react'
|
|
|
|
import { css, StyleSheet } from 'next/css'
|
|
|
|
|
2016-10-14 21:13:46 +00:00
|
|
|
export default () => (
|
2016-10-05 23:35:00 +00:00
|
|
|
<div className={ css(styles.main) }>
|
|
|
|
Hello world
|
|
|
|
</div>
|
2016-10-14 21:13:46 +00:00
|
|
|
)
|
2016-10-05 23:35:00 +00:00
|
|
|
|
|
|
|
const styles = StyleSheet.create({
|
|
|
|
main: {
|
|
|
|
background: 'red',
|
|
|
|
'@media (max-width: 600px)': {
|
|
|
|
background: 'blue'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
```
|
|
|
|
|
|
|
|
### `<head>` side effects
|
|
|
|
|
|
|
|
We expose a built-in component for appending elements to the `<head>` of the page.
|
|
|
|
|
2016-10-05 23:58:36 +00:00
|
|
|
```jsx
|
2016-10-05 23:35:00 +00:00
|
|
|
import React from 'react'
|
|
|
|
import Head from 'next/head'
|
|
|
|
export default () => (
|
2016-10-14 21:13:46 +00:00
|
|
|
<div>
|
|
|
|
<Head>
|
|
|
|
<title>My page title</title>
|
|
|
|
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
|
|
|
|
</Head>
|
|
|
|
<p>Hello world!</p>
|
|
|
|
</div>
|
2016-10-05 23:35:00 +00:00
|
|
|
)
|
|
|
|
```
|
|
|
|
|
|
|
|
### Stateful components
|
|
|
|
|
|
|
|
When state, lifecycle hooks or initial data population you can export a `React.Component`:
|
|
|
|
|
2016-10-05 23:58:36 +00:00
|
|
|
```jsx
|
2016-10-05 23:35:00 +00:00
|
|
|
import React from 'react'
|
|
|
|
export default class extends React.Component {
|
2016-10-09 00:50:09 +00:00
|
|
|
static async getInitialProps ({ req }) {
|
|
|
|
return req
|
2016-10-05 23:35:00 +00:00
|
|
|
? { userAgent: req.headers.userAgent }
|
|
|
|
: { userAgent: navigator.userAgent }
|
|
|
|
}
|
|
|
|
|
|
|
|
render () {
|
|
|
|
return <div>
|
|
|
|
Hello World {this.props.userAgent}
|
|
|
|
</div>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### Routing
|
|
|
|
|
|
|
|
Client-side transitions between routes are enabled via a `<Link>` component
|
|
|
|
|
|
|
|
#### pages/index.js
|
|
|
|
|
2016-10-05 23:58:36 +00:00
|
|
|
```jsx
|
2016-10-05 23:35:00 +00:00
|
|
|
import React from 'react'
|
|
|
|
import Link from 'next/link'
|
|
|
|
export default () => (
|
|
|
|
<div>Click <Link href="/about"><a>here</a></Link> to read more</div>
|
|
|
|
)
|
|
|
|
```
|
|
|
|
|
|
|
|
#### pages/about.js
|
|
|
|
|
2016-10-05 23:58:36 +00:00
|
|
|
```jsx
|
2016-10-05 23:35:00 +00:00
|
|
|
import React from 'react'
|
|
|
|
export default () => (
|
|
|
|
<p>Welcome to About!</p>
|
|
|
|
)
|
|
|
|
```
|
|
|
|
|
|
|
|
Client-side routing behaves exactly like the native UA:
|
|
|
|
|
|
|
|
1. The component is fetched
|
|
|
|
2. If it defines `getInitialProps`, data is fetched. If an error occurs, `_error.js` is rendered
|
|
|
|
3. After 1 and 2 complete, `pushState` is performed and the new component rendered
|
|
|
|
|
|
|
|
Each top-level component receives a `url` property with the following API:
|
|
|
|
|
|
|
|
- `path` - `String` of the current path excluding the query string
|
|
|
|
- `query` - `Object` with the parsed query string. Defaults to `{}`
|
|
|
|
- `push(url)` - performs a `pushState` call associated with the current component
|
|
|
|
- `replace(url)` - performs a `replaceState` call associated with the current component
|
|
|
|
- `pushTo(url)` - performs a `pushState` call that renders the new `url`. This is equivalent to following a `<Link>`
|
|
|
|
- `replaceTo(url)` - performs a `replaceState` call that renders the new `url`
|
|
|
|
|
2016-10-15 22:36:54 +00:00
|
|
|
### Error handling
|
|
|
|
|
|
|
|
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`:
|
|
|
|
|
|
|
|
```jsx
|
|
|
|
import React from 'react'
|
2016-10-16 22:44:26 +00:00
|
|
|
|
|
|
|
export default class Error extends React.Component {
|
|
|
|
static getInitialProps ({ res, xhr }) {
|
|
|
|
const statusCode = res ? res.statusCode : xhr.status
|
|
|
|
return { statusCode }
|
|
|
|
}
|
|
|
|
|
|
|
|
render () {
|
|
|
|
return (
|
|
|
|
<p>An error { this.props.statusCode } occurred</p>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
2016-10-15 22:36:54 +00:00
|
|
|
```
|
|
|
|
|
2016-10-05 23:35:00 +00:00
|
|
|
### Production deployment
|
|
|
|
|
|
|
|
To deploy, run:
|
|
|
|
|
2016-10-05 23:58:36 +00:00
|
|
|
```bash
|
2016-10-05 23:35:00 +00:00
|
|
|
next build
|
|
|
|
next start
|
|
|
|
```
|
|
|
|
|
|
|
|
For example, to deploy with `now` a `package.json` like follows is recommended:
|
|
|
|
|
2016-10-05 23:58:36 +00:00
|
|
|
```json
|
2016-10-05 23:35:00 +00:00
|
|
|
{
|
|
|
|
"name": "my-app",
|
|
|
|
"dependencies": {
|
|
|
|
"next": "latest"
|
|
|
|
},
|
|
|
|
"scripts": {
|
|
|
|
"dev": "next",
|
|
|
|
"build": "next build",
|
|
|
|
"start": "next start"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
2016-10-15 13:15:10 +00:00
|
|
|
|
|
|
|
### In progress
|
|
|
|
|
2016-10-15 13:16:25 +00:00
|
|
|
The following tasks are planned and part of our roadmap
|
|
|
|
|
2016-10-15 13:15:10 +00:00
|
|
|
- [ ] Add option to supply a `req`, `res` handling function for custom routing
|
|
|
|
- [ ] Add option to extend or replace custom babel configuration
|
|
|
|
- [ ] Add option to extend or replace custom webpack configuration
|
2016-10-15 13:17:47 +00:00
|
|
|
- [ ] Investigate pluggable component-oriented rendering backends (Inferno, Preact, etc)
|