1
0
Fork 0
mirror of https://github.com/terribleplan/next.js.git synced 2024-01-19 02:48:18 +00:00
next.js/Readme.md

366 lines
12 KiB
Markdown
Raw Normal View History

2016-10-05 23:35:00 +00:00
# next.js
2016-10-25 06:09:45 +00:00
Next.js is a minimalistic framework for server-rendered React applications.
2016-10-05 23:35:00 +00:00
## How to use
2016-10-25 06:09:45 +00:00
Install it:
```
$ npm install next --save
```
After that, the file-system is the main API. Every `.js` file becomes a route that gets automatically processed and rendered.
2016-10-05 23:35:00 +00:00
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
2016-10-19 23:59:18 +00:00
We use [glamor](https://github.com/threepointone/glamor) to provide a great built-in solution for CSS isolation and modularization without trading off any CSS features
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'
import { style } from 'next/css'
2016-10-05 23:35:00 +00:00
2016-10-14 21:13:46 +00:00
export default () => (
2016-10-19 23:59:18 +00:00
<div className={style}>
2016-10-05 23:35:00 +00:00
Hello world
</div>
2016-10-14 21:13:46 +00:00
)
2016-10-05 23:35:00 +00:00
const style = style({
2016-10-05 23:35:00 +00:00
main: {
background: 'red',
2016-10-19 23:59:18 +00:00
':hover': {
background: 'gray'
}
2016-10-05 23:35:00 +00:00
'@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
)
```
2016-10-25 06:10:38 +00:00
### Component lifecycle
2016-10-05 23:35:00 +00:00
2016-10-20 00:08:41 +00:00
When you need state, lifecycle hooks or **initial data population** you can export a `React.Component`:
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 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`
### 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'
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-20 00:58:42 +00:00
## Production deployment
2016-10-05 23:35:00 +00:00
2016-10-20 00:58:42 +00:00
To deploy, instead of running `next`, you probably want to build ahead of time. Therefore, building and starting are separate commands:
2016-10-05 23:35:00 +00:00
2016-10-05 23:58:36 +00:00
```bash
2016-10-05 23:35:00 +00:00
next build
next start
```
2016-10-20 00:58:42 +00:00
For example, to deploy with [`now`](https://zeit.co/now) a `package.json` like follows is recommended:
2016-10-05 23:35:00 +00:00
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
2016-10-20 00:58:42 +00:00
Then run `now` and enjoy!
Note: we recommend putting `.next` in `.npmignore` or `.gitigore`. Otherwise, use `files` or `now.files` to opt-into a whitelist of files you want to deploy (and obviously exclude `.next`)
## FAQ
2016-10-15 13:15:10 +00:00
2016-10-24 19:59:46 +00:00
<details>
<summary>Is this production ready?</summary>
Next.js has been powering `https://zeit.co` since its inception.
Were ecstatic about both the developer experience and end-user performance, so we decided to share it with the community.
</details>
2016-10-15 13:16:25 +00:00
2016-10-24 19:59:46 +00:00
<details>
<summary>How big is it?</summary>
The client side next bundle, which includes React and Glamor is **${X}kb** gzipped.
The Next runtime (lazy loading, routing, `<Head>`) contributes **${Y}%** to the size of that bundle.
The codebase is ~1500LOC (excluding CLI programs).
</details>
<details>
<summary>Is this like `create-react-app`?</summary>
Yes and No.
Yes in that both make your life easier.
No in that it enforces a _structure_ so that we can do more advanced things like:
2016-10-25 06:09:45 +00:00
- Server side rendering
- Automatic code splitting
2016-10-24 19:59:46 +00:00
In addition, Next.js provides two built-in features that are critical for every single website:
2016-10-25 06:09:45 +00:00
- Routing with lazy component loading: `<Link>` (by importing `next/link`)
- A way for components to alter `<head>`: `<Head>` (by importing `next/head`)
2016-10-24 19:59:46 +00:00
2016-10-25 06:09:45 +00:00
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!
2016-10-24 19:59:46 +00:00
</details>
<details>
<summary>Why CSS-in-JS?</summary>
`next/css` is powered by [Glamor](https://github.com/threepointone/glamor). While it exposes a JavaScript API, it produces regular CSS and therefore important features like `:hover`, animations, media queries all work.
Theres *no tradeoff* in power. Instead, we gain the power of simpler composition and usage of JavaScript expressions.
*Compiling* regular CSS files would be counter-productive to some of our goals. Some of these are listed below.
In the future, however, we _might_ be able to take advantage of custom elements / shadow DOM to also support the full CSS syntax once browser support is wide enough.
### Compilation performance
Parsing, prefixing, modularizing and hot-code-reloading CSS can be avoided by just using JavaScript.
This results in better compilation performance and less memory usage, specially for large projects. No `cssom`, `postcss`, `cssnext` or transformation plugins.
It also means fewer dependencies and fewer things for Next to do. Everything is Just JavaScript® (since JSX is completely optional)
### Lifecycle performance
Since every class name is invoked with the `css()` helper, Next.js can intelligently add or remove `<style>` elements that are not being used.
2016-10-25 06:09:45 +00:00
This is important for server-side rendering, but also during the lifecycle of the page. Since Next.js enables `pushState` transitions that load components dynamically, unnecessary `<style>` elements would bring down performance over time.
2016-10-24 19:59:46 +00:00
This is a very signifcant benefit over approaches like `require(xxxxx.css')`.
### Correctness
Since the class names and styles are defined as JavaScript objects, a variety of aids for correctness are much more easily enabled:
- Linting
- Type checking
- Autocompletion
While these are tractable for CSS itself, we dont need to duplicate the efforts in tooling and libraries to accomplish them.
</details>
<details>
<summary>What syntactic features are transpiled? How do I change them?</summary>
We track V8. Since V8 has wide support for ES6 and `async` and `await`, we transpile those. Since V8 doesnt support class decorators, we dont transpile those.
See [this](link to default babel config we use) and [this](link to issue that tracks the ability to change babel options)
</details>
<details>
<summary>Why a new Router?</summary>
Next.js is special in that:
- Routes dont need to be known ahead of time
- Routes are always be lazy-loadable
- Top-level components can define `getInitialProps` that should _block_ the loading of the route (either when server-rendering or lazy-loading)
As a result, we were able to introduce a very simple approach to routing that consists of two pieces:
- Every top level component receives a `url` object to inspect the url or perform modifications to the history
- A `<Link />` component is used to wrap elements like anchors (`<a/>`) to perform client-side transitions
We tested the flexibility of the routing with some interesting scenarios. For an example, check out [nextgram](https://github.com/zeit/nextgram).
</details>
<details>
<summary>How do I define a custom fancy route?</summary>
Were adding the ability to map between an arbitrary URL and any component by supplying a request handler: [#25](https://github.com/zeit/next.js/issues/25)
On the client side, we'll add a parameter to `<Link>` so that it _decorates_ the URL differently from the URL it _fetches_.
</details>
<details>
<summary>How do I fetch data?</summary>
Its up to you. `getInitialProps` is an `async` function (or a regular function that returns a `Promise`). It can retrieve data from anywhere.
</details>
<details>
<summary>Why does it load the runtime from a CDN by default?</summary>
2016-10-25 06:09:45 +00:00
We intend for Next.js to be a great starting point for any website or app, no matter how small.
2016-10-24 19:59:46 +00:00
If youre building a very small mostly-content website, you still want to benefit from features like lazy-loading, a component architecture and module bundling.
But in some cases, the size of React itself would far exceed the content of the page!
For this reason we want to promote a situation where users can share the cache for the basic runtime across internet properties. The application code continues to load from your server as usual.
We are committed to providing a great uptime and levels of security for our CDN. Even so, we also **automatically fall back** if the CDN script fails to load [with a simple trick]().
To turn the CDN off, just set `{ “next”: { “cdn”: false } }` in `package.json`.
</details>
<details>
<summary>What is this inspired by?</summary>
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.
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.
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.
As we were researching options for server-rendering React that didnt 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.
</details>
## Future directions
The following issues are currently being explored and input from the community is appreciated:
2016-10-24 20:00:50 +00:00
- Support for pluggable renderers [[#20](https://github.com/zeit/next.js/issues/20)]
2016-10-24 19:59:46 +00:00
- Style isolation through Shadow DOM or "full css support" [[#22](https://github.com/zeit/next.js/issues/22)]
- Better JSX [[#22](https://github.com/zeit/next.js/issues/23)]
- Custom server logic and routing [[#25](https://github.com/zeit/next.js/issues/25)]
- Custom babel config [[#26](https://github.com/zeit/next.js/issues/26)]
- Custom webpack config [[#40](https://github.com/zeit/next.js/issues/40)]
2016-10-24 19:40:29 +00:00
## Authors
- Naoyuki Kanezawa ([@nkzawa](https://twitter.com/nkzawa)) ▲ZEIT
- Tony Kovanen ([@rase-](https://twitter.com/rase-)) ▲ZEIT
- Guillermo Rauch ([@rauchg](https://twitter.com/rauchg)) ▲ZEIT
- Dan Zajdband ([@impronunciable](https://twitter.com/impronunciable)) Knight-Mozilla / Coral Project