From aed6d6f31c35c34d5a22ce4767da24c2f4d880f7 Mon Sep 17 00:00:00 2001 From: raoenhui Date: Tue, 28 Aug 2018 22:47:05 +0800 Subject: [PATCH 1/4] add readme --- readme-cn.md | 1799 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1799 insertions(+) create mode 100644 readme-cn.md diff --git a/readme-cn.md b/readme-cn.md new file mode 100644 index 0000000000000..ae7086fefc45f --- /dev/null +++ b/readme-cn.md @@ -0,0 +1,1799 @@ +screen shot 2016-10-25 at 2 37 27 pm + +[![NPM version](https://img.shields.io/npm/v/next.svg)](https://www.npmjs.com/package/next) +[![Build Status](https://travis-ci.org/zeit/next.js.svg?branch=master)](https://travis-ci.org/zeit/next.js) +[![Build status](https://ci.appveyor.com/api/projects/status/gqp5hs71l3ebtx1r/branch/master?svg=true)](https://ci.appveyor.com/project/arunoda/next-js/branch/master) +[![Coverage Status](https://coveralls.io/repos/zeit/next.js/badge.svg?branch=master)](https://coveralls.io/r/zeit/next.js?branch=master) +[![Join the community on Spectrum](https://withspectrum.github.io/badge/badge.svg)](https://spectrum.chat/next-js) + +Next.js 是一个轻巧的React服务端渲染应用框架。 +翻译版本为6.1.1-canary.2。 + +**可访问 [nextjs.org/learn](https://nextjs.org/learn) 开始学习 Next.js.** + +[README in English](readme.md) + +--- + + + + + +- [怎么使用](#how-to-use) + - [安装](#setup) + - [代码自动分割](#automatic-code-splitting) + - [CSS](#css) + - [支持嵌入样式](#built-in-css-support) + - [内嵌样式](#css-in-js) + - [使用 CSS / Sass / Less / Stylus files](#importing-css--sass--less--stylus-files) + - [静态文件服务(如图像)](#static-file-serving-eg-images) + - [``](#populating-head) + - [获取数据以及组件生命周期](#fetching-data-and-component-lifecycle) + - [路由](#routing) + - [`` 用法](#with-link) + - [URL 对象](#with-url-object) + - [替换路由](#replace-instead-of-push-url) + - [组件支持点击事件 `onClick`](#using-a-component-that-supports-onclick) + - [暴露 `href` 给子元素](#forcing-the-link-to-expose-href-to-its-child) + - [禁止滚动到页面顶部](#disabling-the-scroll-changes-to-top-on-page) + - [命令式](#imperatively) + - [拦截器 `popstate`](#intercepting-popstate) + - [URL对象用法](#with-url-object-1) + - [路由事件](#router-events) + - [浅层路由](#shallow-routing) + - [高阶组件](#using-a-higher-order-component) + - [预加载页面](#prefetching-pages) + - [``用法](#with-link-1) + - [命令式prefetch写法](#imperatively-1) + - [自定义服务端路由](#custom-server-and-routing) + - [禁止文件路由](#disabling-file-system-routing) + - [动态前缀](#dynamic-assetprefix) + - [动态导入](#dynamic-import) + - [1. 基础支持 (同样支持 SSR)](#1-basic-usage-also-does-ssr) + - [2. 自定义加载组件](#2-with-custom-loading-component) + - [3. 禁止使用SSR](#3-with-no-ssr) + - [4. 同时加载多个模块](#4-with-multiple-modules-at-once) + - [自定义 ``](#custom-app) + - [自定义 ``](#custom-document) + - [自定义错误处理](#custom-error-handling) + - [渲染内置错误页面](#reusing-the-built-in-error-page) + - [自定义配置](#custom-configuration) + - [设置自定义构建目录](#setting-a-custom-build-directory) + - [禁止etag生成](#disabling-etag-generation) + - [配置onDemandEntries](#configuring-the-ondemandentries) + - [配置页面后缀名解析扩展](#configuring-extensions-looked-for-when-resolving-pages-in-pages) + - [配置构建ID](#configuring-the-build-id) + - [自定义webpack配置](#customizing-webpack-config) + - [自定义babel配置](#customizing-babel-config) + - [暴露配置到服务端和客户端](#exposing-configuration-to-the-server--client-side) + - [启动服务选择hostname](#starting-the-server-on-alternative-hostname) + - [CDN支持前缀](#cdn-support-with-asset-prefix) +- [项目部署](#production-deployment) +- [浏览器支持](#browser-support) +- [导出静态页面](#static-html-export) + - [使用](#usage) + - [限制](#limitation) +- [多zone](#multi-zones) + - [怎么定义一个zone](#how-to-define-a-zone) + - [怎么合并他们](#how-to-merge-them) +- [技巧](#recipes) +- [FAQ](#faq) +- [贡献](#contributing) +- [作者](#authors) + + + +## 怎么使用 + + +### 安装 + + +安装它: + +```bash +npm install --save next react react-dom +``` + +将下面脚本添加到 package.json 中: + +```json +{ + "scripts": { + "dev": "next", + "build": "next build", + "start": "next start" + } +} +``` + +下面, 文件系统是主要的API. 每个`.js` 文件将变成一个路由,自动处理和渲染。 + +新建 `./pages/index.js` 到你的项目中: + +```jsx +export default () =>
Welcome to next.js!
+``` + +运行 `npm run dev` 命令并打开 `http://localhost:3000`。 如果你想使用其他端口,可运行 `npm run dev -- -p <设置端口号>`. + + +目前为止我们可以了解到: + +- 自动打包编译 (使用 webpack 和 babel) +- 热加载 +- 以 `./pages`作为服务端的渲染和索引 +- Static file serving. `./static/` is mapped to `/static/` (given you [create a `./static/` directory](#static-file-serving-eg-images) inside your project) +- 静态文件服务. `./static/` 映射到 `/static/` (可以 [创建一个静态目录](#static-file-serving-eg-images) 在你的项目中) + +这里有个简单的案例,可以下载看看 [sample app - nextgram](https://github.com/zeit/nextgram) + + +### 代码自动分割 + +每个页面只会导入`import`中绑定以及被用到的代码. 也就是说并不会加载不需要的代码! + +```jsx +import cowsay from 'cowsay-browser' + +export default () => +
+    {cowsay.say({ text: 'hi there!' })}
+  
+``` + +### CSS + + +#### 支持嵌入样式 + +

+ 案例 + +

+ +我们绑定 [styled-jsx](https://github.com/zeit/styled-jsx) 来生成独立作用域的CSS. 目标是支持 "shadow CSS",但是 [不支持独立模块作用域的js](https://github.com/w3c/webcomponents/issues/71). + +```jsx +export default () => +
+ Hello world +

scoped!

+ + +
+``` + +想查看更多案例可以点击 [styled-jsx documentation](https://www.npmjs.com/package/styled-jsx)查看. + + +#### 内嵌样式 + +

+ + Examples + + +

+ +有些情况可以使用css内嵌js写法。如下所示: + +```jsx +export default () =>

hi there

+``` + +更复杂的内嵌样式解决方案,特别是服务端渲染的时样式更改。我们可以通过包裹自定义Document,来添加样式,案例如下:[custom ``](#user-content-custom-document) + + +#### 使用 CSS / Sass / Less / Stylus files + +To support importing `.css`, `.scss`, `.less` or `.styl` files you can use these modules, which configure sensible defaults for server rendered applications. +支持用`.css`, `.scss`, `.less` or `.styl`,需要配置默认文件next.config.js,具体可查看下面链接 + +- [@zeit/next-css](https://github.com/zeit/next-plugins/tree/master/packages/next-css) +- [@zeit/next-sass](https://github.com/zeit/next-plugins/tree/master/packages/next-sass) +- [@zeit/next-less](https://github.com/zeit/next-plugins/tree/master/packages/next-less) +- [@zeit/next-stylus](https://github.com/zeit/next-plugins/tree/master/packages/next-stylus) + + +### 静态文件服务(如图像) + +在根目录下新建文件夹叫`static`。代码可以通过`/static/`来引入相关的静态资源。 + +```jsx +export default () => my image +``` + +_注意:不要自定义静态文件夹的名字,只能叫`static` ,因为只有这个名字Next.js才会把它当作静态资源。 + + + +### 生成`` + +`` + +

+ Examples + +

+ +我们设置一个内置组件来装载``到页面中。 + +```jsx +import Head from 'next/head' + +export default () => +
+ + My page title + + +

Hello world!

+
+``` + +我们定义`key`属性来避免重复的`` 标签,保证`` 只渲染一次,如下所示: + +```jsx +import Head from 'next/head' +export default () => ( +
+ + My page title + + + + + +

Hello world!

+
+) +``` + +只有第二个``才被渲染。 + +注意:在卸载组件时,' '的内容将被清除。请确保每个页面都在其``定义了所需要的内容,而不是假设其他页面已经加过了 + + +### 获取数据以及组件生命周期 + +

+ Examples + +

+ +如果你需要一个有状态、生命周期或有初始数据的React组件(而不是上面的无状态函数),如下所示: + +```jsx +import React from 'react' + +export default class extends React.Component { + static async getInitialProps({ req }) { + const userAgent = req ? req.headers['user-agent'] : navigator.userAgent + return { userAgent } + } + + render() { + return ( +
+ Hello World {this.props.userAgent} +
+ ) + } +} +``` + +相信你注意到,当页面渲染时加载数据,我们使用了一个异步方法`getInitialProps`。它能异步获取js普通对象,并绑定在`props`上 + +当服务渲染时,`getInitialProps`将会把数据序列化,就像`JSON.stringify`。所以确保`getInitialProps`返回的是一个普通js对象,而不是`Date`, `Map` 或 `Set`类型。 + +当页面初次加载时,`getInitialProps`只会在服务端执行一次。`getInitialProps`只有在路由切换的时候(如`Link`组件跳转或路由自定义跳转)时,客户端的才会被执行。 + +当页面初始化加载时,`getInitialProps`只会加载在服务端。只有当路由跳转(`Link`组件跳转或API方法跳转)时,客户端才会执行`getInitialProps`。 + +_Note: `getInitialProps` can **not** be used in children components. Only in `pages`._ + +注意:`getInitialProps`将不能使用在子组件中。只能使用在`pages`页面中。 + +
+ +> 只有服务端用到的模块放在 `getInitialProps`里,请确保正确的导入了它们,可参考[import them properly](https://arunoda.me/blog/ssr-and-server-only-modules)。 +> 否则会拖慢你的应用速度。 + +
+ +你也可以给5⃣无状态组件定义 `getInitialProps`: + +```jsx +const Page = ({ stars }) => +
+ Next stars: {stars} +
+ +Page.getInitialProps = async ({ req }) => { + const res = await fetch('https://api.github.com/repos/zeit/next.js') + const json = await res.json() + return { stars: json.stargazers_count } +} + +export default Page +``` + +`getInitialProps`入参对象的属性如下: + +- `pathname` - URL的path部分 +- `query` - URL的query部分,并被解析成对象 +- `asPath` - 显示在浏览器中的实际路径(包含查询部分),为`String`类型 +- `req` - HTTP请求对象 (只有服务器端有) +- `res` - HTTP返回对象 (只有服务器端有) +- `jsonPageRes` - [获取数据响应对象](https://developer.mozilla.org/en-US/docs/Web/API/Response) (只有客户端有) +- `err` - 渲染过程中的任何错误 + + +### 路由 + + +#### ``用法 + +

+ Examples + +

+ +可以用 `` 组件实现客户端的路由切换。 + +```jsx +// pages/index.js +import Link from 'next/link' + +export default () => +
+ Click{' '} + + here + {' '} + to read more +
+``` + +```jsx +// pages/about.js +export default () =>

Welcome to About!

+``` + +注意:可以使用[``](#prefetching-pages)使链接和预加载在后台同时进行,来达到页面的最佳性能。 + +客户端路由行为与浏览器很相似: + +1. 组件获取 +2. If it defines `getInitialProps`, data is fetched. If an error occurs, `_error.js` is rendered2. +2. 如果组件定义了`getInitialProps`,数据获取了。如果有错误情况将会渲染 `_error.js`。 +3. After 1 and 2 complete, `pushState` is performed and the new component is rendered +3. 1和2都完成了,`pushState`执行,新组件被渲染。 + +**不建议使用该特性,使用[withRouter](https://github.com/zeit/next.js#using-a-higher-order-component)来代替** - 每个顶级组件都接收`url` 属性,API如下: + +- `pathname` - `String` of the current path excluding the query string +- `pathname` - 不包含查询内容的当前路径,为`String`类型 +- `query` - 查询内容,被解析成`Object`类型. 默认为`{}` +- `asPath` - 展现在浏览器上的实际路径,包含查询内容,为`String`类型 + + +##### URL 对象 + +

+ Examples + +

+ +组件``接收URL对象,而且它会自动格式化生成URL字符串 + +```jsx +// pages/index.js +import Link from 'next/link' + +export default () => +
+ Click{' '} + + here + {' '} + to read more +
+``` + +将生成URL字符串`/about?name=Zeit`,你可以使用任何在[Node.js URL module documentation](https://nodejs.org/api/url.html#url_url_strings_and_url_objects)定义过的属性。 + + + +##### 替换路由 + +The default behaviour for the `` component is to `push` a new url into the stack. You can use the `replace` prop to prevent adding a new entry. + +```jsx +// pages/index.js +import Link from 'next/link' + +export default () => +
+ Click{' '} + + here + {' '} + to read more +
+``` + + +##### 组件支持点击事件 `onClick` + +`` supports any component that supports the `onClick` event. In case you don't provide an `` tag, it will only add the `onClick` event handler and won't pass the `href` property. + +```jsx +// pages/index.js +import Link from 'next/link' + +export default () => +
+ Click{' '} + + image + +
+``` + +
+##### 暴露 `href` 给子元素 + +If child is an `` 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 `` 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. + +**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. + +```jsx +import Link from 'next/link' +import Unexpected_A from 'third-library' + +export default ({ href, name }) => + + + {name} + + +``` + + +##### 禁止滚动到页面顶部 + +``的默认行为就是滚到页面顶部。当有hash定义时(#),页面将会滚动到对应的id上,就像``标签一样。为了预防滚动到顶部,可以给``加 +`scroll={false}`属性: + +```jsx +Disables scrolling +Changes with scrolling to top +``` + + +#### 命令式 + +

+ Examples + +

+ +你也可以用`next/router`实现客户端路由切换 + + +```jsx +import Router from 'next/router' + +export default () => +
+ Click Router.push('/about')}>here to read more +
+``` + + +#### 拦截器 `popstate` + +有些情况(比如使用[custom router](#custom-server-and-routing)),你可能想监听[`popstate`](https://developer.mozilla.org/en-US/docs/Web/Events/popstate),在路由跳转前做一些动作。 +比如,你可以操作request或强制SSR刷新 + +```jsx +import Router from 'next/router' + +Router.beforePopState(({ url, as, options }) => { + // I only want to allow these two routes! + if (as !== "/" || as !== "/other") { + // Have SSR render bad routes as a 404. + window.location.href = as + return false + } + + return true +}); +``` + +如果你在`beforePopState`中返回false,`Router`将不会执行`popstate`事件。 +例如[Disabling File-System Routing](#disabling-file-system-routing)。 + +以上`Router`对象的API如下: + +- `route` - 当前路由的`String`类型 +- `pathname` - 不包含查询内容的当前路径,为`String`类型 +- `query` - 查询内容,被解析成`Object`类型. 默认为`{}` +- `asPath` - 展现在浏览器上的实际路径,包含查询内容,为`String`类型 +- `push(url, as=url)` - 页面渲染第一个参数url的页面,浏览器栏显示的是第二个参数url +- `replace(url, as=url)` - performs a `replaceState` call with the given url +- `beforePopState(cb=function)` - 在路由器处理事件之前拦截. + +`push` 和 `replace` 函数的第二个参数`as`,是为了装饰URL作用。如果你在服务器端设置了自定义路由将会起作用。 + +注意:为了用编程方式,而不是用导航栏触发或组件获取的方式来切换路由,可以在组件里使用`props.url.push` 或 `props.url.replace`。 + + +##### URL对象用法 + +`push` 或 `replace`可接收的URL对象(``组件的URL对象一样)来生成URL。 + +```jsx +import Router from 'next/router' + +const handler = () => + Router.push({ + pathname: '/about', + query: { name: 'Zeit' } + }) + +export default () => +
+ Click here to read more +
+``` + +也可以像``组件一样添加额外的参数。 + + +##### 路由事件 + +你可以监听路由相关事件。 +下面是事件支持列表: + +- `routeChangeStart(url)` - 路由开始切换时触发 +- `routeChangeComplete(url)` - 完成路由切换时触发 +- `routeChangeError(err, url)` - 路由切换报错时触发 +- `beforeHistoryChange(url)` - 浏览器history模式开始切换时触发 +- `hashChangeStart(url)` - 开始切换hash值但是没有切换页面路由时触发 +- `hashChangeComplete(url)` - 完成切换hash值但是没有切换页面路由时触发 + +> 这里的`url`是指显示在浏览器中的url。如果你用了`Router.push(url, as)`(或类似的方法),那浏览器中的url将会显示as的值。 + +下面是如何正确使用路由事件`routeChangeStart`的例子: + +```js +const handleRouteChange = url => { + console.log('App is changing to: ', url) +} + +Router.events.on('routeChangeStart', handleRouteChange) +``` + +如果你不想长期监听该事件,你可以用`off`事件去取消监听: + +```js +Router.events.off('routeChangeStart', handleRouteChange) +``` + +如果路由加载被取消(比如快速连续双击链接) + +```js +Router.events.on('routeChangeError', (err, url) => { + if (err.cancelled) { + console.log(`Route to ${url} was cancelled!`) + } +}) +``` + + +##### 浅层路由 + +

+ Examples + +

+ +浅层路由允许你改变URL但是不执行 `getInitialProps`生命周期。你可以加载相同页面的URL,得到更新后的路由属性`pathname`和`query`,并不失去state状态。 + +你可以给`Router.push` 或 `Router.replace`方法加`shallow: true`参数。如下面的例子所示: + +```js +// Current URL is "/" +const href = '/?counter=10' +const as = href +Router.push(href, as, { shallow: true }) +``` + +现在URL更新为`/?counter=10`。在组件里查看`this.props.url`你将会看到更新的URL。 + +你可以在[`componentWillReceiveProps`](https://facebook.github.io/react/docs/react-component.html#componentwillreceiveprops)钩子函数中监听URL的变化。 + +```js +componentWillReceiveProps(nextProps) { + const { pathname, query } = nextProps.url + // fetch data based on the new query +} +``` + +> 注意: +> +> 浅层路由只作用于相同URL的参数改变,比如我们假定有个其他路由`about`,而你向下面代码样运行: +> ```js +> Router.push('/?counter=10', '/about?counter=10', { shallow: true }) +> ``` +> 那么这将会出现新页面,即使我们加了浅层路由,但是它还是会卸载当前页,会加载新的页面并触发新页面的`getInitialProps`。 + + +#### 高阶组件 + +

+ Examples + +

+ +如果你想应用里每个组件都处理路由对象,你可以使用`withRouter`高阶组件。下面是如何使用它: + +```jsx +import { withRouter } from 'next/router' + +const ActiveLink = ({ children, router, href }) => { + const style = { + marginRight: 10, + color: router.pathname === href? 'red' : 'black' + } + + const handleClick = (e) => { + e.preventDefault() + router.push(href) + } + + return ( + + {children} + + ) +} + +export default withRouter(ActiveLink) +``` + +上面路由对象的API可以参考[`next/router`](#imperatively). + + +### 预加载页面 + +⚠️ 只有生产环境才有此功能 ⚠️ + +

+ Examples + +

+ +Next.js有允许你预加载页面的API。 + +用Next.js服务端渲染你的页面,可以达到所有你应用里所有未来会跳转的路径即时响应,有效的应用Next.js,可以通过预加载应用程序的功能,最大程度的初始化网站性能。[查看更多](https://zeit.co/blog/next#anticipation-is-the-key-to-performance). + +> Next.js的预加载功能只预加载JS代码。当页面渲染时,你可能需要等待数据请求。 + + +#### ``用法 + +你可以给添加 `prefetch` 属性,Next.js将会在后台预加载这些页面。 + +```jsx +import Link from 'next/link' + +// example header component +export default () => + +``` + + +#### 命令式prefetch写法 + +大多数预加载是通过处理的,但是我们还提供了命令式API用于更复杂的场景。 + +```jsx +import Router from 'next/router' + +export default ({ url }) => +
+ setTimeout(() => url.pushTo('/dynamic'), 100)}> + A route transition will happen after 100ms + + {// but we can prefetch it! + Router.prefetch('/dynamic')} +
+``` + +路由实例只允许在应用程序的客户端。以防服务端渲染发生错误,建议prefetch事件写在`componentDidMount()`生命周期里。 + +```jsx +import React from 'react' +import Router from 'next/router' + +export default class MyLink extends React.Component { + componentDidMount() { + Router.prefetch('/dynamic') + } + + render() { + return ( +
+ setTimeout(() => url.pushTo('/dynamic'), 100)}> + A route transition will happen after 100ms + +
+ ) + } +} +``` + + +### 自定义服务端路由 + +

+ Examples + +

+ + +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: + +一般你使用 `next start` 命令来启动next服务,你还可以编写代码来自定义路由。 + +```json +{ + "scripts": { + "dev": "node server.js", + "build": "next build", + "start": "NODE_ENV=production node server.js" + } +} +``` + +下面这个例子使 `/a` 路由解析为`./pages/b`,以及`/b` 路由解析为`./pages/a`; + +```js +// This file doesn't go through babel or webpack transformation. +// Make sure the syntax and sources this file requires are compatible with the current node version you are running +// See https://github.com/zeit/next.js/issues/1245 for discussions on Universal Webpack or universal Babel +const { createServer } = require('http') +const { parse } = require('url') +const next = require('next') + +const dev = process.env.NODE_ENV !== 'production' +const app = next({ dev }) +const handle = app.getRequestHandler() + +app.prepare().then(() => { + createServer((req, res) => { + // Be sure to pass `true` as the second argument to `url.parse`. + // This tells it to parse the query portion of the URL. + const parsedUrl = parse(req.url, true) + const { pathname, query } = parsedUrl + + if (pathname === '/a') { + app.render(req, res, '/b', query) + } else if (pathname === '/b') { + app.render(req, res, '/a', query) + } else { + handle(req, res, parsedUrl) + } + }).listen(3000, err => { + if (err) throw err + console.log('> Ready on http://localhost:3000') + }) +}) +``` + +`next`的API如下所示 +- `next(opts: object)` + +opts的属性如下: +- `dev` (`boolean`) 判断 Next.js应用是否在开发环境 - 默认 `false` +- `dir` (`string`) Next项目路径 - 默认 `'.'` +- `quiet` (`boolean`) Hide error messages containing server information - 默认 `false` +- `quiet` (`boolean`) 是否隐藏包含服务端消息在内的错误信息 - 默认 `false` +- `conf` (`object`) 与`next.config.js`的对象相同 - 默认 `{}` + +生产环境的话,可以更改package.json里的`start`脚本为`NODE_ENV=production node server.js`。 + + +#### 禁止文件路由 +默认情况,`Next`将会把`/pages`下的所有文件匹配路由(如`/pages/some-file.js` 渲染为 `site.com/some-file`) + +如果你的项目使用自定义路由,那么有可能不同的路由会得到相同的内容,可以优化SEO和用户体验。 + +禁止路由链接到`/pages`下的文件,只需设置`next.config.js`文件如下所示: + +```js +// next.config.js +module.exports = { + useFileSystemPublicRoutes: false +} +``` + +注意`useFileSystemPublicRoutes`只禁止服务端的文件路由;但是客户端的还是禁止不了。 + +你如果想配置客户端路由不能跳转文件路由,可以参考[Intercepting `popstate`](#intercepting-popstate)。 + + +#### 动态前缀 + +有时你需要设置动态前缀,可以在请求时设置`assetPrefix`改变前缀。 + +使用方法如下: + +```js +const next = require('next') +const micro = require('micro') + +const dev = process.env.NODE_ENV !== 'production' +const app = next({ dev }) +const handleNextRequests = app.getRequestHandler() + +app.prepare().then(() => { + const server = micro((req, res) => { + // Add assetPrefix support based on the hostname + if (req.headers.host === 'my-app.com') { + app.setAssetPrefix('http://cdn.com/myapp') + } else { + app.setAssetPrefix('') + } + + handleNextRequests(req, res) + }) + + server.listen(port, (err) => { + if (err) { + throw err + } + + console.log(`> Ready on http://localhost:${port}`) + }) +}) + +``` + + +### 动态导入 + +

+ Examples + +

+ +ext.js支持JavaScript的TC39提议[dynamic import proposal](https://github.com/tc39/proposal-dynamic-import)。你可以动态导入JavaScript模块(如React组件)。 + +动态导入相当于把代码分成各个块管理。Next.js服务端动态导入功能,你可以做很多炫酷事情。 + +下面介绍一些动态导入方式: + + +#### 1. 基础支持 (同样支持 SSR) + +```jsx +import dynamic from 'next/dynamic' + +const DynamicComponent = dynamic(import('../components/hello')) + +export default () => +
+
+ +

HOME PAGE is here!

+
+``` + + +#### 2. 自定义加载组件 + +```jsx +import dynamic from 'next/dynamic' + +const DynamicComponentWithCustomLoading = dynamic( + import('../components/hello2'), + { + loading: () =>

...

+ } +) + +export default () => +
+
+ +

HOME PAGE is here!

+
+``` + + +#### 3. 禁止使用SSR + +```jsx +import dynamic from 'next/dynamic' + +const DynamicComponentWithNoSSR = dynamic(import('../components/hello3'), { + ssr: false +}) + +export default () => +
+
+ +

HOME PAGE is here!

+
+``` + + +#### 4. 同时加载多个模块 + +```jsx +import dynamic from 'next/dynamic' + +const HelloBundle = dynamic({ + modules: () => { + const components = { + Hello1: import('../components/hello1'), + Hello2: import('../components/hello2') + } + + return components + }, + render: (props, { Hello1, Hello2 }) => +
+

+ {props.title} +

+ + +
+}) + +export default () => +``` + + +### 自定义 `` + +

+ Examples + + +

+ +组件来初始化页面。你可以重写它来控制页面初始化,如下面的事: + +- 当页面变化时保持页面布局 +- 当路由变化时保持页面状态 +- 使用`componentDidCatch`自定义处理错误 +- 注入额外数据到页面里 (如GraphQL查询) + +重写的话,新建`./pages/_app.js`文件,重写App模块如下所示: + +```js +import App, {Container} from 'next/app' +import React from 'react' + +export default class MyApp extends App { + static async getInitialProps ({ Component, router, ctx }) { + let pageProps = {} + + if (Component.getInitialProps) { + pageProps = await Component.getInitialProps(ctx) + } + + return {pageProps} + } + + render () { + const {Component, pageProps} = this.props + return + + + } +} +``` + + +### 自定义 `` + +

+ Examples + + +

+ +- 在服务端呈现 +- 初始化服务端时添加文档标记元素 +- 通常实现服务端渲染会使用一些css-in-js库,如[styled-components](./examples/with-styled-components), [glamorous](./examples/with-glamorous) 或 [emotion](with-emotion)。[styled-jsx](https://github.com/zeit/styled-jsx)是Next.js自带默认使用的css-in-js库 + +`Next.js`会自动定义文档标记,比如,你从来不需要添加``, ``等。如果想自定义文档标记,你可以新建`./pages/_document.js`,然后扩展`Document`类: + +```jsx +// _document is only rendered on the server side and not on the client side +// Event handlers like onClick can't be added to this file + +// ./pages/_document.js +import Document, { Head, Main, NextScript } from 'next/document' + +export default class MyDocument extends Document { + static async getInitialProps(ctx) { + const initialProps = await Document.getInitialProps(ctx) + return { ...initialProps } + } + + render() { + return ( + + + + + +
+ + + + ) + } +} +``` + +钩子[`getInitialProps`](#fetching-data-and-component-lifecycle)接收到的参数`ctx`对象都是一样的 + +- 回调函数`renderPage`是会执行React渲染逻辑的函数(同步),这种做法有助于此函数支持一些类似于 Aphrodite的 renderStatic等一些服务器端渲染容器。 + +__注意:`
`外的React组件将不会渲染到浏览器中,所以那添加应用逻辑代码。如果你页面需要公共组件(菜单或工具栏),可以参照上面说的`App`组件代替。__ + + +### 自定义错误处理 + +404和500错误客户端和服务端都会通过`error.js`组件处理。如果你想改写它,则新建`_error.js`在文件夹中: + +```jsx +import React from 'react' + +export default class Error extends React.Component { + static getInitialProps({ res, err }) { + const statusCode = res ? res.statusCode : err ? err.statusCode : null; + return { statusCode } + } + + render() { + return ( +

+ {this.props.statusCode + ? `An error ${this.props.statusCode} occurred on server` + : 'An error occurred on client'} +

+ ) + } +} +``` + + +### 渲染内置错误页面 + +如果你想渲染内置错误页面,你可以使用`next/error`: + +```jsx +import React from 'react' +import Error from 'next/error' +import fetch from 'isomorphic-unfetch' + +export default class Page extends React.Component { + static async getInitialProps() { + const res = await fetch('https://api.github.com/repos/zeit/next.js') + const statusCode = res.statusCode > 200 ? res.statusCode : false + const json = await res.json() + + return { statusCode, stars: json.stargazers_count } + } + + render() { + if (this.props.statusCode) { + return + } + + return ( +
+ Next stars: {this.props.stars} +
+ ) + } +} +``` + +> 如果你自定义了个错误页面,你可以引入自己的错误页面来代替`next/error` + + +### 自定义配置 + +如果你想自定义Next.js的高级配置,可以在根目录下新建`next.config.js`文件(与`pages/` 和 `package.json`一起) + +注意:`next.config.js`是一个Node.js模块,不是一个JSON文件,可以用于Next启动服务已经构建阶段,但是不作用于浏览器端。 + +```js +// next.config.js +module.exports = { + /* config options here */ +} +``` + +或使用一个函数: + +```js +module.exports = (phase, {defaultConfig}) => { + // + // https://github.com/zeit/ + return { + /* config options here */ + } +} +``` + +`phase`是配置文件被加载时的当前内容。你可看到所有的phases常量:[constants](./lib/constants.js) +这些常量可以通过`next/constants`引入: + +```js +const {PHASE_DEVELOPMENT_SERVER} = require('next/constants') +module.exports = (phase, {defaultConfig}) => { + if(phase === PHASE_DEVELOPMENT_SERVER) { + return { + /* development only config options here */ + } + } + + return { + /* config options for all phases except development here */ + } +} +``` + + +#### 设置自定义构建目录 + +你可以自定义一个构建目录,如新建`build`文件夹来代替`.next` 文件夹成为构建目录。如果没有配置构建目录,构建时将会自动新建`.next`文件夹 + +```js +// next.config.js +module.exports = { + distDir: 'build' +} +``` + + +#### 禁止etag生成 + +你可以禁止etag生成根据你的缓存策略。如果没有配置,Next将会生成etags到每个页面中。 + +```js +// next.config.js +module.exports = { + generateEtags: false +} +``` + + +#### 配置onDemandEntries + +Next暴露一些选项来给你控制服务器部署以及缓存页面: + +```js +module.exports = { + onDemandEntries: { + // period (in ms) where the server will keep pages in the buffer + maxInactiveAge: 25 * 1000, + // number of pages that should be kept simultaneously without being disposed + pagesBufferLength: 2, + } +} +``` + +这个只是在开发环境才有的功能。如果你在生成环境中想缓存SSR页面,请查看[SSR-caching](https://github.com/zeit/next.js/tree/canary/examples/ssr-caching + + +#### 配置页面后缀名解析扩展 + +如typescript模块[`@zeit/next-typescript`](https://github.com/zeit/next-plugins/tree/master/packages/next-typescript),需要支持解析后缀名为`.ts`的文件。`pageExtensions` 允许你扩展后缀名来解析各种pages下的文件。 + +```js +// next.config.js +module.exports = { + pageExtensions: ['jsx', 'js'] +} +``` + + +#### 配置构建ID + +Next.js使用一个常量来判断你的应用服务是哪个版本。因为多个服务部署应用,那`next build`命令将会在多个服务器中运行,为了保持同一个构建ID,可以配置`generateBuildId`函数: + +```js +// next.config.js +module.exports = { + generateBuildId: async () => { + // For example get the latest git commit hash here + return 'my-build-id' + } +} +``` + + +### 自定义webpack配置 + +

+ Examples + +

+ +可以使用些一些常见的模块 + +- [@zeit/next-css](https://github.com/zeit/next-plugins/tree/master/packages/next-css) +- [@zeit/next-sass](https://github.com/zeit/next-plugins/tree/master/packages/next-sass) +- [@zeit/next-less](https://github.com/zeit/next-plugins/tree/master/packages/next-less) +- [@zeit/next-preact](https://github.com/zeit/next-plugins/tree/master/packages/next-preact) +- [@zeit/next-typescript](https://github.com/zeit/next-plugins/tree/master/packages/next-typescript) + +*注意: `webpack`方法将被执行两次,一次在服务端一次在客户端。你可以用`isServer`属性区分客户端和服务端来配置* + +多配置可以组合在一起,如: + +```js +const withTypescript = require('@zeit/next-typescript') +const withSass = require('@zeit/next-sass') + +module.exports = withTypescript(withSass({ + webpack(config, options) { + // Further custom configuration here + return config + } +})) +``` + +为了扩展`webpack`使用,可以在`next.config.js`定义函数。 + +```js +// next.config.js is not transformed by Babel. So you can only use javascript features supported by your version of Node.js. + +module.exports = { + webpack: (config, { buildId, dev, isServer, defaultLoaders }) => { + // Perform customizations to webpack config + // Important: return the modified config + return config + }, + webpackDevMiddleware: config => { + // Perform customizations to webpack dev middleware config + // Important: return the modified config + return config + } +} +``` + +`webpack`的第二个参数是个对象,你可以自定义配置它,对象属性如下所示: + +- `buildId` - 字符串类型,构建的唯一标示 +- `dev` - `Boolean`型,判断你是否在开发环境下 +- `isServer` - `Boolean` 型,为`true`使用在服务端, 为`false`使用在客户端. +- `defaultLoaders` - 对象型 ,内部加载器, 你可以如下配置 + - `babel` - 对象型,配置`babel-loader. + - `hotSelfAccept` - 对象型, `hot-self-accept-loader`配置选项.这个加载器只能用于高阶案例。如 [`@zeit/next-typescript`](https://github.com/zeit/next-plugins/tree/master/packages/next-typescript)添加顶层typescript页面。 + +`defaultLoaders.babel`使用案例如下: + +```js +// Example next.config.js for adding a loader that depends on babel-loader +// This source was taken from the @zeit/next-mdx plugin source: +// https://github.com/zeit/next-plugins/blob/master/packages/next-mdx +module.exports = { + webpack: (config, {}) => { + config.module.rules.push({ + test: /\.mdx/, + use: [ + options.defaultLoaders.babel, + { + loader: '@mdx-js/loader', + options: pluginOptions.options + } + ] + }) + + return config + } +} +``` + + +### 自定义babel配置 + +

+ Examples + +

+ +为了扩展方便我们使用`babel`,可以在应用根目录新建`.babelrc`文件,该文件可配置。 + +如果有该文件,我们将会考虑来源的真实性,因此同样你需要定义next,也就是 `next/babel`预设。 + +下面是`.babelrc`文件案例: + +```json +{ + "presets": ["next/babel"], + "plugins": [] +} +``` + +`next/babel`预设可处理各种React应用所需要的情况。包括: + +- preset-env +- preset-react +- plugin-proposal-class-properties +- plugin-proposal-object-rest-spread +- plugin-transform-runtime +- styled-jsx + +presets / plugins不允许添加到`.babelrc`中,然而你可以配置`next/babel`预设: + +```json +{ + "presets": [ + ["next/babel", { + "preset-env": {}, + "transform-runtime": {}, + "styled-jsx": {}, + "class-properties": {} + }] + ], + "plugins": [] +} +``` + +`"preset-env"`模块选项应该保持为false,否则webpack代码分割将被禁用。 + + + +### 暴露配置到服务端和客户端 + +`next/config`模块使你应用运行时可以读取些存储在`next.config.js`的配置项。`serverRuntimeConfig`属性只在服务器端可用,`publicRuntimeConfig`属性在服务端和客户端可用。 + +```js +// next.config.js +module.exports = { + serverRuntimeConfig: { // Will only be available on the server side + mySecret: 'secret' + }, + publicRuntimeConfig: { // Will be available on both server and client + staticFolder: '/static', + mySecret: process.env.MY_SECRET // Pass through env variables + } +} +``` + +```js +// pages/index.js +import getConfig from 'next/config' +// Only holds serverRuntimeConfig and publicRuntimeConfig from next.config.js nothing else. +const {serverRuntimeConfig, publicRuntimeConfig} = getConfig() + +console.log(serverRuntimeConfig.mySecret) // Will only be available on the server side +console.log(publicRuntimeConfig.staticFolder) // Will be available on both server and client + +export default () =>
+ logo +
+``` + + +### 启动服务选择hostname + +启动开发环境服务可以设置不同的hostname,你可以在启动命令后面加上`--hostname 主机名` 或 `-H 主机名`。它将会启动一个TCP服务器来监听连接所提供的主机。 + + +### CDN支持前缀 + +建立一个CDN,你能配置`assetPrefix`选项,去配置你的CDN源。 + +```js +const isProd = process.env.NODE_ENV === 'production' +module.exports = { + // You may only need to add assetPrefix in the production. + assetPrefix: isProd ? 'https://cdn.mydomain.com' : '' +} +``` + +注意:Next.js运行时将会自动添加前缀,但是对于`/static`是没有效果的,如果你想这些静态资源也能使用CDN,你需要自己添加前缀。有一个方法可以判断你的环境来加前缀,如 [in this example](https://github.com/zeit/next.js/tree/master/examples/with-universal-configuration)。 + + +## 项目部署 + +部署中,你可以先构建打包生成环境代码,再启动服务。因此,构建和启动分为下面两条命令: + +```bash +next build +next start +``` + +例如,使用[`now`](https://zeit.co/now)去部署`package.json`配置文件如下: + +```json +{ + "name": "my-app", + "dependencies": { + "next": "latest" + }, + "scripts": { + "dev": "next", + "build": "next build", + "start": "next start" + } +} +``` + +然后就可以直接运行`now`了。 + +Next.js也有其他托管解决方案。请查考wiki章节['Deployment'](https://github.com/zeit/next.js/wiki/Deployment) 。 + +注意:`NODE_ENV`可以通过`next`命令配置,如果没有配置,会最大渲染,如果你使用编程式写法的话[programmatically](#custom-server-and-routing),你需要手动设置`NODE_ENV=production`。 + +注意:推荐将`.next`或自定义打包文件夹[custom dist folder](https://github.com/zeit/next.js#custom-configuration)放入`.gitignore` 或 `.npmignore`中。否则,使用`files` 或 `now.files` +添加部署白名单,并排除`.next`或自定义打包文件夹。 + + +## 浏览器支持 + +Next.js支持IE11和所有的现代浏览器使用了[`@babel/preset-env`](https://new.babeljs.io/docs/en/next/babel-preset-env.html)没包括polyfills。有时候你的代码或引入的其他npm包的部分功能现代浏览器不支持,则需要用polyfills去实现。 + +ployflls实现案例为[polyfills](https://github.com/zeit/next.js/tree/canary/examples/with-polyfills)。 + + +## 导出静态页面 + +

+ Examples + +

+ +`next export`可以输出一个Next.js应用作为静态资源应用而不依靠 Node.js服务。 +这个输出的应用几乎支持Next.js的所有功能,包括动态路由,预获取,预加载以及动态导入。 + +`next export`将把所有有可能渲染出的HTML都生成。这是基于映射对象的`pathname`关键字关联到页面对象。这个映射叫做`exportPathMap`。 + +The page object has 2 values: +页面对象有2个属性: + +- `page` - 字符串类型,页面生成目录 +- `query` - 对象类型,当预渲染时,`query`对象将会传入页面的生命周期`getInitialProps`中。默认为`{}`。 + + + +### 使用 + +通常开发Next.js应用你将会运行: + +``` +next build +next export +``` + +`next export`命令默认不需要任何配置,将会自动生成默认`exportPathMap`生成`pages`目录下的路由你页面。 + +如果你想动态配置路由,可以在`next.config.js`中添加异步函数`exportPathMap`。 + +```js +// next.config.js +module.exports = { + exportPathMap: async function (defaultPathMap) { + return { + '/': { page: '/' }, + '/about': { page: '/about' }, + '/readme.md': { page: '/readme' }, + '/p/hello-nextjs': { page: '/post', query: { title: 'hello-nextjs' } }, + '/p/learn-nextjs': { page: '/post', query: { title: 'learn-nextjs' } }, + '/p/deploy-nextjs': { page: '/post', query: { title: 'deploy-nextjs' } } + } + } +} +``` + +> 注意:如果path的结尾是目录名,则将导出`/dir-name/index.html`,但是如果结尾有扩展名,将会导出对应的文件,如上`/readme.md`。如果你使用`.html`以外的扩展名解析文件时,你需要设置header的`Content-Type`头为"text/html". + +输入下面命令: + +```sh +next build +next export +``` + +你可以在`package.json`添加一个NPM脚本,如下所示: + +```json +{ + "scripts": { + "build": "next build", + "export": "npm run build && next export" + } +} +``` + +接着只用执行一次下面命令: + +```sh +npm run export +``` + +然后你将会有一个静态页面应用在`out` 目录下。 + +> 你也可以自定义输出目录。可以运行`next export -h`命令查看帮助。 + +现在你可以部署`out`目录到任意静态资源服务器上。注意如果部署GitHub Pages需要加个额外的步骤,[文档如下](https://github.com/zeit/next.js/wiki/Deploying-a-Next.js-app-into-GitHub-Pages) + +例如,访问`out`目录并用下面命令部署应用[ZEIT Now](https://zeit.co/now). + +```sh +now +``` + + +### 限制 + +使用`next export`,我们创建了个静态HTML应用。构建时将会运行页面里生命周期`getInitialProps` 函数。 + +`req`和`res`只在服务端可用,不能通过`getInitialProps`。 + +> 所以你不能预构建HTML文件时动态渲染HTML页面。如果你想动态渲染可以运行`next start`或其他自定义服务端API。 + + +## 多zone + +

+ Examples + +

+ +一个zone时一个单独的Next.js应用。如果你有很多zone,你可以合并成一个应用。 + +例如,你如下有两个zone: + +* https://docs.my-app.com 服务于路由 `/docs/**` +* https://ui.my-app.com 服务于所有页面 + +有多zone应用技术支持,你可以将几个应用合并到一个,而且可以自定义URL路径,使你能同时单独开发各个应用。 + +> 与microservices观念类似, 只是应用于前端应用. + + +### 怎么定义一个zone + +zone没有单独的API文档。你需要做下面事即可: + +* 确保你的应用里只有需要的页面 (例如, https://ui.my-app.com 不包含 `/docs/**`) +* 确保你的应用有个前缀[assetPrefix](https://github.com/zeit/next.js#cdn-support-with-asset-prefix)。(你也可以定义动态前缀[dynamically](https://github.com/zeit/next.js#dynamic-assetprefix)) + + +### 怎么合并他们 + +你能使用HTTP代理合并 zone + +你能使用代理[micro proxy](https://github.com/zeit/micro-proxy)来作为你的本地代理服务。它允许你定义路由规则如下: + +```json +{ + "rules": [ + {"pathname": "/docs**", "method":["GET", "POST", "OPTIONS"], "dest": "https://docs.my-app.com"}, + {"pathname": "/**", "dest": "https://ui.my-app.com"} + ] +} +``` + +生产环境部署,如果你使用了[ZEIT now](https://zeit.co/now),可以它的使用[path alias](https://zeit.co/docs/features/path-aliases) 功能。否则,你可以设置你已使用的代理服务编写上面规则来路由HTML页面 + + +## 技巧 + +- [设置301重定向](https://www.raygesualdo.com/posts/301-redirects-with-nextjs/) +- [只处理服务器端模块](https://arunoda.me/blog/ssr-and-server-only-modules) +- [构建项目React-Material-UI-Next-Express-Mongoose-Mongodb](https://github.com/builderbook/builderbook) +- [构建一个SaaS产品 React-Material-UI-Next-MobX-Express-Mongoose-MongoDB-TypeScript](https://github.com/async-labs/saas) + + +## 问答 + +
+ 这个产品准备好了吗? + Next.js has been powering https://zeit.co since its inception. + https://zeit.co 都是用Next.js写的。 + + We’re ecstatic about both the developer experience and end-user performance, so we decided to share it with the community. + 它的开发体验和终端用户体验都很好,所以我们决定开源出来给大家共享。 +
+ +
+ 体积多大? + +客户端大小根据应用需求不一样大小也不一样。 + +一个最简单Next应该用gzip压缩后大约65kb + +
+ +
+ 这个像 `create-react-app`? + +是或不是. + +是,因为它让你的SSR开发更简单。 + +不是,因为它规定了一定的目录结构,使我们能做以下更高级的事: +- 服务端渲染 +- 自动代码分割 + +此外,Next.js还提供两个内置特性: +- 路由与懒加载组件: `` (通过引入 `next/link`) +- 修改``的组件: `` (通过引入 `next/head`) + +如果你想写共用组件,可以嵌入Next.js应用和React应用中,推荐使用`create-react-app`。你可以更改`import`保持代码清晰。 + + +
+ +
+ 怎么解决css嵌入js问题? + +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. +Next.js自带[styled-jsx](https://github.com/zeit/styled-jsx)库支持css嵌入js。而且你可以选择其他嵌入方法到你的项目中,可参考文档[as mentioned before](#css-in-js)。 + +
+ +
+ What syntactic features are transpiled? How do I change them? + +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. + +See [this](https://github.com/zeit/next.js/blob/master/server/build/webpack.js#L79) and [this](https://github.com/zeit/next.js/issues/26) + +
+ +
+ Why a new Router? + +Next.js is special in that: + +- Routes don’t need to be known ahead of time +- Routes are always 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 `` component is used to wrap elements like anchors (``) 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). + +
+ +
+How do I define a custom fancy route? + +We [added](#custom-server-and-routing) the ability to map between an arbitrary URL and any component by supplying a request handler. + +On the client side, we have a parameter call `as` on `` that _decorates_ the URL differently from the URL it _fetches_. +
+ +
+How do I fetch data? + +It’s up to you. `getInitialProps` is an `async` function (or a regular function that returns a `Promise`). It can retrieve data from anywhere. +
+ +
+ Can I use it with GraphQL? + +Yes! Here's an example with [Apollo](./examples/with-apollo). + +
+ +
+Can I use it with Redux? + +Yes! Here's an [example](./examples/with-redux) +
+ +
+Can I use Next with my favorite Javascript library or toolkit? + +Since our first release we've had **many** example contributions, you can check them out in the [examples](./examples) directory +
+ +
+What is this inspired by? + +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 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. + +
+ +
+## 贡献 + +可查看 [contributing.md](./contributing.md) + + +## 作者 + +- Arunoda Susiripala ([@arunoda](https://twitter.com/arunoda)) – [ZEIT](https://zeit.co) +- Tim Neutkens ([@timneutkens](https://twitter.com/timneutkens)) – [ZEIT](https://zeit.co) +- Naoyuki Kanezawa ([@nkzawa](https://twitter.com/nkzawa)) – [ZEIT](https://zeit.co) +- Tony Kovanen ([@tonykovanen](https://twitter.com/tonykovanen)) – [ZEIT](https://zeit.co) +- Guillermo Rauch ([@rauchg](https://twitter.com/rauchg)) – [ZEIT](https://zeit.co) +- Dan Zajdband ([@impronunciable](https://twitter.com/impronunciable)) – Knight-Mozilla / Coral Project From e151bec68aba466ce1e8e2842f08446ff0d5c127 Mon Sep 17 00:00:00 2001 From: qqnewtouch Date: Sat, 1 Sep 2018 22:49:38 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=B8=AD=E6=96=87?= =?UTF-8?q?=E6=96=87=E6=A1=A3=EF=BC=8C=E5=A6=82=E4=B8=AD=E8=8B=B1=E6=96=87?= =?UTF-8?q?=E7=A9=BA=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- readme-cn.md => README-zh-CN.md | 381 ++++++++++++++++---------------- 1 file changed, 187 insertions(+), 194 deletions(-) rename readme-cn.md => README-zh-CN.md (68%) diff --git a/readme-cn.md b/README-zh-CN.md similarity index 68% rename from readme-cn.md rename to README-zh-CN.md index ae7086fefc45f..7e4b10597b764 100644 --- a/readme-cn.md +++ b/README-zh-CN.md @@ -6,8 +6,8 @@ [![Coverage Status](https://coveralls.io/repos/zeit/next.js/badge.svg?branch=master)](https://coveralls.io/r/zeit/next.js?branch=master) [![Join the community on Spectrum](https://withspectrum.github.io/badge/badge.svg)](https://spectrum.chat/next-js) -Next.js 是一个轻巧的React服务端渲染应用框架。 -翻译版本为6.1.1-canary.2。 +Next.js 是一个轻量级的 React 服务端渲染应用框架。 +翻译版本为 7.0.0-canary.8。 **可访问 [nextjs.org/learn](https://nextjs.org/learn) 开始学习 Next.js.** @@ -33,25 +33,25 @@ Next.js 是一个轻巧的React服务端渲染应用框架。 - [`` 用法](#with-link) - [URL 对象](#with-url-object) - [替换路由](#replace-instead-of-push-url) - - [组件支持点击事件 `onClick`](#using-a-component-that-supports-onclick) - - [暴露 `href` 给子元素](#forcing-the-link-to-expose-href-to-its-child) + - [组件支持点击事件`onClick`](#using-a-component-that-supports-onclick) + - [暴露`href`给子元素](#forcing-the-link-to-expose-href-to-its-child) - [禁止滚动到页面顶部](#disabling-the-scroll-changes-to-top-on-page) - [命令式](#imperatively) - [拦截器 `popstate`](#intercepting-popstate) - - [URL对象用法](#with-url-object-1) + - [URL 对象用法](#with-url-object-1) - [路由事件](#router-events) - [浅层路由](#shallow-routing) - [高阶组件](#using-a-higher-order-component) - [预加载页面](#prefetching-pages) - [``用法](#with-link-1) - - [命令式prefetch写法](#imperatively-1) + - [命令式 prefetch 写法](#imperatively-1) - [自定义服务端路由](#custom-server-and-routing) - [禁止文件路由](#disabling-file-system-routing) - [动态前缀](#dynamic-assetprefix) - [动态导入](#dynamic-import) - [1. 基础支持 (同样支持 SSR)](#1-basic-usage-also-does-ssr) - [2. 自定义加载组件](#2-with-custom-loading-component) - - [3. 禁止使用SSR](#3-with-no-ssr) + - [3. 禁止使用 SSR](#3-with-no-ssr) - [4. 同时加载多个模块](#4-with-multiple-modules-at-once) - [自定义 ``](#custom-app) - [自定义 ``](#custom-document) @@ -59,22 +59,22 @@ Next.js 是一个轻巧的React服务端渲染应用框架。 - [渲染内置错误页面](#reusing-the-built-in-error-page) - [自定义配置](#custom-configuration) - [设置自定义构建目录](#setting-a-custom-build-directory) - - [禁止etag生成](#disabling-etag-generation) - - [配置onDemandEntries](#configuring-the-ondemandentries) + - [禁止 etag 生成](#disabling-etag-generation) + - [配置 onDemandEntries](#configuring-the-ondemandentries) - [配置页面后缀名解析扩展](#configuring-extensions-looked-for-when-resolving-pages-in-pages) - - [配置构建ID](#configuring-the-build-id) - - [自定义webpack配置](#customizing-webpack-config) - - [自定义babel配置](#customizing-babel-config) + - [配置构建 ID](#configuring-the-build-id) + - [自定义 webpack 配置](#customizing-webpack-config) + - [自定义 babel 配置](#customizing-babel-config) - [暴露配置到服务端和客户端](#exposing-configuration-to-the-server--client-side) - - [启动服务选择hostname](#starting-the-server-on-alternative-hostname) - - [CDN支持前缀](#cdn-support-with-asset-prefix) + - [启动服务选择 hostname](#starting-the-server-on-alternative-hostname) + - [CDN 支持前缀](#cdn-support-with-asset-prefix) - [项目部署](#production-deployment) - [浏览器支持](#browser-support) - [导出静态页面](#static-html-export) - [使用](#usage) - [限制](#limitation) -- [多zone](#multi-zones) - - [怎么定义一个zone](#how-to-define-a-zone) +- [多 zone](#multi-zones) + - [怎么定义一个 zone](#how-to-define-a-zone) - [怎么合并他们](#how-to-merge-them) - [技巧](#recipes) - [FAQ](#faq) @@ -107,7 +107,7 @@ npm install --save next react react-dom } ``` -下面, 文件系统是主要的API. 每个`.js` 文件将变成一个路由,自动处理和渲染。 +下面, 文件系统是主要的 API. 每个`.js` 文件将变成一个路由,自动处理和渲染。 新建 `./pages/index.js` 到你的项目中: @@ -152,7 +152,7 @@ export default () =>

-我们绑定 [styled-jsx](https://github.com/zeit/styled-jsx) 来生成独立作用域的CSS. 目标是支持 "shadow CSS",但是 [不支持独立模块作用域的js](https://github.com/w3c/webcomponents/issues/71). +我们绑定 [styled-jsx](https://github.com/zeit/styled-jsx) 来生成独立作用域的 CSS. 目标是支持 "shadow CSS",但是 [不支持独立模块作用域的 JS](https://github.com/w3c/webcomponents/issues/71). ```jsx export default () => @@ -192,19 +192,18 @@ export default () =>

-有些情况可以使用css内嵌js写法。如下所示: +有些情况可以使用 CSS 内嵌 JS 写法。如下所示: ```jsx export default () =>

hi there

``` -更复杂的内嵌样式解决方案,特别是服务端渲染的时样式更改。我们可以通过包裹自定义Document,来添加样式,案例如下:[custom ``](#user-content-custom-document) +更复杂的内嵌样式解决方案,特别是服务端渲染的时样式更改。我们可以通过包裹自定义 Document,来添加样式,案例如下:[custom ``](#user-content-custom-document) #### 使用 CSS / Sass / Less / Stylus files -To support importing `.css`, `.scss`, `.less` or `.styl` files you can use these modules, which configure sensible defaults for server rendered applications. -支持用`.css`, `.scss`, `.less` or `.styl`,需要配置默认文件next.config.js,具体可查看下面链接 +支持用`.css`, `.scss`, `.less` or `.styl`,需要配置默认文件 next.config.js,具体可查看下面链接 - [@zeit/next-css](https://github.com/zeit/next-plugins/tree/master/packages/next-css) - [@zeit/next-sass](https://github.com/zeit/next-plugins/tree/master/packages/next-sass) @@ -220,7 +219,7 @@ To support importing `.css`, `.scss`, `.less` or `.styl` files you can use these export default () => my image ``` -_注意:不要自定义静态文件夹的名字,只能叫`static` ,因为只有这个名字Next.js才会把它当作静态资源。 +_注意:不要自定义静态文件夹的名字,只能叫`static` ,因为只有这个名字 Next.js 才会把它当作静态资源。 @@ -251,7 +250,7 @@ export default () => ``` -我们定义`key`属性来避免重复的`` 标签,保证`` 只渲染一次,如下所示: +我们定义`key`属性来避免重复的``标签,保证``只渲染一次,如下所示: ```jsx import Head from 'next/head' @@ -271,7 +270,7 @@ export default () => ( 只有第二个``才被渲染。 -注意:在卸载组件时,' '的内容将被清除。请确保每个页面都在其``定义了所需要的内容,而不是假设其他页面已经加过了 +注意:在卸载组件时,``的内容将被清除。请确保每个页面都在其``定义了所需要的内容,而不是假设其他页面已经加过了 ### 获取数据以及组件生命周期 @@ -281,7 +280,7 @@ export default () => (

-如果你需要一个有状态、生命周期或有初始数据的React组件(而不是上面的无状态函数),如下所示: +如果你需要一个有状态、生命周期或有初始数据的 React 组件(而不是上面的无状态函数),如下所示: ```jsx import React from 'react' @@ -302,26 +301,24 @@ export default class extends React.Component { } ``` -相信你注意到,当页面渲染时加载数据,我们使用了一个异步方法`getInitialProps`。它能异步获取js普通对象,并绑定在`props`上 +相信你注意到,当页面渲染时加载数据,我们使用了一个异步方法`getInitialProps`。它能异步获取 JS 普通对象,并绑定在`props`上 -当服务渲染时,`getInitialProps`将会把数据序列化,就像`JSON.stringify`。所以确保`getInitialProps`返回的是一个普通js对象,而不是`Date`, `Map` 或 `Set`类型。 +当服务渲染时,`getInitialProps`将会把数据序列化,就像`JSON.stringify`。所以确保`getInitialProps`返回的是一个普通 JS 对象,而不是`Date`, `Map` 或 `Set`类型。 当页面初次加载时,`getInitialProps`只会在服务端执行一次。`getInitialProps`只有在路由切换的时候(如`Link`组件跳转或路由自定义跳转)时,客户端的才会被执行。 -当页面初始化加载时,`getInitialProps`只会加载在服务端。只有当路由跳转(`Link`组件跳转或API方法跳转)时,客户端才会执行`getInitialProps`。 - -_Note: `getInitialProps` can **not** be used in children components. Only in `pages`._ +当页面初始化加载时,`getInitialProps`只会加载在服务端。只有当路由跳转(`Link`组件跳转或 API 方法跳转)时,客户端才会执行`getInitialProps`。 注意:`getInitialProps`将不能使用在子组件中。只能使用在`pages`页面中。
-> 只有服务端用到的模块放在 `getInitialProps`里,请确保正确的导入了它们,可参考[import them properly](https://arunoda.me/blog/ssr-and-server-only-modules)。 +> 只有服务端用到的模块放在`getInitialProps`里,请确保正确的导入了它们,可参考[import them properly](https://arunoda.me/blog/ssr-and-server-only-modules)。 > 否则会拖慢你的应用速度。
-你也可以给5⃣无状态组件定义 `getInitialProps`: +你也可以给无状态组件定义`getInitialProps`: ```jsx const Page = ({ stars }) => @@ -340,11 +337,11 @@ export default Page `getInitialProps`入参对象的属性如下: -- `pathname` - URL的path部分 -- `query` - URL的query部分,并被解析成对象 +- `pathname` - URL 的 path 部分 +- `query` - URL 的 query 部分,并被解析成对象 - `asPath` - 显示在浏览器中的实际路径(包含查询部分),为`String`类型 -- `req` - HTTP请求对象 (只有服务器端有) -- `res` - HTTP返回对象 (只有服务器端有) +- `req` - HTTP 请求对象 (只有服务器端有) +- `res` - HTTP 返回对象 (只有服务器端有) - `jsonPageRes` - [获取数据响应对象](https://developer.mozilla.org/en-US/docs/Web/API/Response) (只有客户端有) - `err` - 渲染过程中的任何错误 @@ -387,17 +384,10 @@ export default () =>

Welcome to About!

客户端路由行为与浏览器很相似: 1. 组件获取 -2. If it defines `getInitialProps`, data is fetched. If an error occurs, `_error.js` is rendered2. 2. 如果组件定义了`getInitialProps`,数据获取了。如果有错误情况将会渲染 `_error.js`。 -3. After 1 and 2 complete, `pushState` is performed and the new component is rendered 3. 1和2都完成了,`pushState`执行,新组件被渲染。 -**不建议使用该特性,使用[withRouter](https://github.com/zeit/next.js#using-a-higher-order-component)来代替** - 每个顶级组件都接收`url` 属性,API如下: - -- `pathname` - `String` of the current path excluding the query string -- `pathname` - 不包含查询内容的当前路径,为`String`类型 -- `query` - 查询内容,被解析成`Object`类型. 默认为`{}` -- `asPath` - 展现在浏览器上的实际路径,包含查询内容,为`String`类型 +如果需要注入`pathname`, `query` 或 `asPath`到你组件中,你可以使用[withRouter](#using-a-higher-order-component)。 ##### URL 对象 @@ -409,7 +399,7 @@ export default () =>

Welcome to About!

-组件``接收URL对象,而且它会自动格式化生成URL字符串 +组件``接收 URL 对象,而且它会自动格式化生成 URL 字符串 ```jsx // pages/index.js @@ -425,13 +415,13 @@ export default () => ``` -将生成URL字符串`/about?name=Zeit`,你可以使用任何在[Node.js URL module documentation](https://nodejs.org/api/url.html#url_url_strings_and_url_objects)定义过的属性。 +将生成 URL 字符串`/about?name=Zeit`,你可以使用任何在[Node.js URL module documentation](https://nodejs.org/api/url.html#url_url_strings_and_url_objects)定义过的属性。 ##### 替换路由 -The default behaviour for the `` component is to `push` a new url into the stack. You can use the `replace` prop to prevent adding a new entry. +``组件默认将新 url 推入路由栈中。你可以使用`replace`属性来防止添加新输入。 ```jsx // pages/index.js @@ -450,7 +440,7 @@ export default () => ##### 组件支持点击事件 `onClick` -`` supports any component that supports the `onClick` event. In case you don't provide an `` tag, it will only add the `onClick` event handler and won't pass the `href` property. +``支持每个组件所支持的`onClick`事件。如果你不提供``标签,只会处理`onClick`事件而`href`将不起作用。 ```jsx // pages/index.js @@ -468,9 +458,9 @@ export default () => ##### 暴露 `href` 给子元素 -If child is an `` 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 `` 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. +如子元素是一个没有 href 属性的``标签,我们将会指定它以免用户重复操作。然而有些时候,我们需要里面有``标签,但是`Link`组件不会被识别成*超链接*,结果不能将`href`传递给子元素。在这种场景下,你可以定义一个`Link`组件中的布尔属性`passHref`,强制将`href`传递给子元素。 -**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. +**注意**: 使用`a`之外的标签而且没有通过`passHref`的链接可能会使导航看上去正确,但是当搜索引擎爬行检测时,将不会识别成链接(由于缺乏 href 属性),这会对你网站的 SEO 产生负面影响。 ```jsx import Link from 'next/link' @@ -487,7 +477,7 @@ export default ({ href, name }) => ##### 禁止滚动到页面顶部 -``的默认行为就是滚到页面顶部。当有hash定义时(#),页面将会滚动到对应的id上,就像``标签一样。为了预防滚动到顶部,可以给``加 +``的默认行为就是滚到页面顶部。当有 hash 定义时(#),页面将会滚动到对应的 id 上,就像``标签一样。为了预防滚动到顶部,可以给``加 `scroll={false}`属性: ```jsx @@ -522,7 +512,7 @@ export default () => #### 拦截器 `popstate` 有些情况(比如使用[custom router](#custom-server-and-routing)),你可能想监听[`popstate`](https://developer.mozilla.org/en-US/docs/Web/Events/popstate),在路由跳转前做一些动作。 -比如,你可以操作request或强制SSR刷新 +比如,你可以操作 request 或强制 SSR 刷新 ```jsx import Router from 'next/router' @@ -539,27 +529,25 @@ Router.beforePopState(({ url, as, options }) => { }); ``` -如果你在`beforePopState`中返回false,`Router`将不会执行`popstate`事件。 +如果你在`beforePopState`中返回 false,`Router`将不会执行`popstate`事件。 例如[Disabling File-System Routing](#disabling-file-system-routing)。 -以上`Router`对象的API如下: +以上`Router`对象的 API 如下: - `route` - 当前路由的`String`类型 - `pathname` - 不包含查询内容的当前路径,为`String`类型 - `query` - 查询内容,被解析成`Object`类型. 默认为`{}` - `asPath` - 展现在浏览器上的实际路径,包含查询内容,为`String`类型 -- `push(url, as=url)` - 页面渲染第一个参数url的页面,浏览器栏显示的是第二个参数url +- `push(url, as=url)` - 页面渲染第一个参数 url 的页面,浏览器栏显示的是第二个参数 url - `replace(url, as=url)` - performs a `replaceState` call with the given url - `beforePopState(cb=function)` - 在路由器处理事件之前拦截. -`push` 和 `replace` 函数的第二个参数`as`,是为了装饰URL作用。如果你在服务器端设置了自定义路由将会起作用。 - -注意:为了用编程方式,而不是用导航栏触发或组件获取的方式来切换路由,可以在组件里使用`props.url.push` 或 `props.url.replace`。 +`push` 和 `replace` 函数的第二个参数`as`,是为了装饰 URL 作用。如果你在服务器端设置了自定义路由将会起作用。 -##### URL对象用法 +##### URL 对象用法 -`push` 或 `replace`可接收的URL对象(``组件的URL对象一样)来生成URL。 +`push` 或 `replace`可接收的 URL 对象(``组件的 URL 对象一样)来生成 URL。 ```jsx import Router from 'next/router' @@ -587,11 +575,11 @@ export default () => - `routeChangeStart(url)` - 路由开始切换时触发 - `routeChangeComplete(url)` - 完成路由切换时触发 - `routeChangeError(err, url)` - 路由切换报错时触发 -- `beforeHistoryChange(url)` - 浏览器history模式开始切换时触发 -- `hashChangeStart(url)` - 开始切换hash值但是没有切换页面路由时触发 -- `hashChangeComplete(url)` - 完成切换hash值但是没有切换页面路由时触发 +- `beforeHistoryChange(url)` - 浏览器 history 模式开始切换时触发 +- `hashChangeStart(url)` - 开始切换 hash 值但是没有切换页面路由时触发 +- `hashChangeComplete(url)` - 完成切换 hash 值但是没有切换页面路由时触发 -> 这里的`url`是指显示在浏览器中的url。如果你用了`Router.push(url, as)`(或类似的方法),那浏览器中的url将会显示as的值。 +> 这里的`url`是指显示在浏览器中的 url。如果你用了`Router.push(url, as)`(或类似的方法),那浏览器中的 url 将会显示 as 的值。 下面是如何正确使用路由事件`routeChangeStart`的例子: @@ -629,7 +617,7 @@ Router.events.on('routeChangeError', (err, url) => {

-浅层路由允许你改变URL但是不执行 `getInitialProps`生命周期。你可以加载相同页面的URL,得到更新后的路由属性`pathname`和`query`,并不失去state状态。 +浅层路由允许你改变 URL 但是不执行`getInitialProps`生命周期。你可以加载相同页面的 URL,得到更新后的路由属性`pathname`和`query`,并不失去 state 状态。 你可以给`Router.push` 或 `Router.replace`方法加`shallow: true`参数。如下面的例子所示: @@ -640,20 +628,23 @@ const as = href Router.push(href, as, { shallow: true }) ``` -现在URL更新为`/?counter=10`。在组件里查看`this.props.url`你将会看到更新的URL。 +现在 URL 更新为`/?counter=10`。在组件里查看`this.props.router.query`你将会看到更新的 URL。 -你可以在[`componentWillReceiveProps`](https://facebook.github.io/react/docs/react-component.html#componentwillreceiveprops)钩子函数中监听URL的变化。 +你可以在[`componentdidupdate`](https://facebook.github.io/react/docs/react-component.html#componentdidupdate)钩子函数中监听 URL 的变化。 ```js -componentWillReceiveProps(nextProps) { - const { pathname, query } = nextProps.url - // fetch data based on the new query +componentDidUpdate(prevProps) { + const { pathname, query } = this.props.router + // verify props have changed to avoid an infinite loop + if (query.id !== prevProps.router.query.id) { + // fetch data based on the new query + } } ``` > 注意: > -> 浅层路由只作用于相同URL的参数改变,比如我们假定有个其他路由`about`,而你向下面代码样运行: +> 浅层路由只作用于相同 URL 的参数改变,比如我们假定有个其他路由`about`,而你向下面代码样运行: > ```js > Router.push('/?counter=10', '/about?counter=10', { shallow: true }) > ``` @@ -695,7 +686,7 @@ const ActiveLink = ({ children, router, href }) => { export default withRouter(ActiveLink) ``` -上面路由对象的API可以参考[`next/router`](#imperatively). +上面路由对象的 API 可以参考[`next/router`](#imperatively). ### 预加载页面 @@ -707,16 +698,16 @@ export default withRouter(ActiveLink)

-Next.js有允许你预加载页面的API。 +Next.js 有允许你预加载页面的 API。 -用Next.js服务端渲染你的页面,可以达到所有你应用里所有未来会跳转的路径即时响应,有效的应用Next.js,可以通过预加载应用程序的功能,最大程度的初始化网站性能。[查看更多](https://zeit.co/blog/next#anticipation-is-the-key-to-performance). +用 Next.js 服务端渲染你的页面,可以达到所有你应用里所有未来会跳转的路径即时响应,有效的应用 Next.js,可以通过预加载应用程序的功能,最大程度的初始化网站性能。[查看更多](https://zeit.co/blog/next#anticipation-is-the-key-to-performance). -> Next.js的预加载功能只预加载JS代码。当页面渲染时,你可能需要等待数据请求。 +> Next.js 的预加载功能只预加载 JS 代码。当页面渲染时,你可能需要等待数据请求。 #### ``用法 -你可以给添加 `prefetch` 属性,Next.js将会在后台预加载这些页面。 +你可以给添加 `prefetch` 属性,Next.js 将会在后台预加载这些页面。 ```jsx import Link from 'next/link' @@ -745,44 +736,49 @@ export default () => ``` -#### 命令式prefetch写法 +#### 命令式 prefetch 写法 -大多数预加载是通过处理的,但是我们还提供了命令式API用于更复杂的场景。 +大多数预加载是通过处理的,但是我们还提供了命令式 API 用于更复杂的场景。 ```jsx -import Router from 'next/router' +import { withRouter } from 'next/router' -export default ({ url }) => +export default withRouter(({ router }) => +) ``` -路由实例只允许在应用程序的客户端。以防服务端渲染发生错误,建议prefetch事件写在`componentDidMount()`生命周期里。 +路由实例只允许在应用程序的客户端。以防服务端渲染发生错误,建议 prefetch 事件写在`componentDidMount()`生命周期里。 ```jsx import React from 'react' -import Router from 'next/router' +import { withRouter } from 'next/router' -export default class MyLink extends React.Component { +class MyLink extends React.Component { componentDidMount() { - Router.prefetch('/dynamic') + const { router } = this.props + router.prefetch('/dynamic') } render() { + const { router } = this.props return ( ) } } + +export default withRouter(MyLink) ``` @@ -801,9 +797,9 @@ export default class MyLink extends React.Component {

-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: +一般你使用`next start`命令来启动 next 服务,你还可以编写代码来自定义路由,如使用路由正则等。 -一般你使用 `next start` 命令来启动next服务,你还可以编写代码来自定义路由。 +当使用自定义服务文件,如下面例子所示叫 server.js 时,确保你更新了 package.json 中的脚本。 ```json { @@ -850,23 +846,22 @@ app.prepare().then(() => { }) ``` -`next`的API如下所示 +`next`的 API 如下所示 - `next(opts: object)` -opts的属性如下: -- `dev` (`boolean`) 判断 Next.js应用是否在开发环境 - 默认 `false` -- `dir` (`string`) Next项目路径 - 默认 `'.'` -- `quiet` (`boolean`) Hide error messages containing server information - 默认 `false` -- `quiet` (`boolean`) 是否隐藏包含服务端消息在内的错误信息 - 默认 `false` -- `conf` (`object`) 与`next.config.js`的对象相同 - 默认 `{}` +opts 的属性如下: +- `dev` (`boolean`) 判断 Next.js 应用是否在开发环境 - 默认`false` +- `dir` (`string`) Next 项目路径 - 默认`'.'` +- `quiet` (`boolean`) 是否隐藏包含服务端消息在内的错误信息 - 默认`false` +- `conf` (`object`) 与`next.config.js`的对象相同 - 默认`{}` -生产环境的话,可以更改package.json里的`start`脚本为`NODE_ENV=production node server.js`。 +生产环境的话,可以更改 package.json 里的`start`脚本为`NODE_ENV=production node server.js`。 #### 禁止文件路由 默认情况,`Next`将会把`/pages`下的所有文件匹配路由(如`/pages/some-file.js` 渲染为 `site.com/some-file`) -如果你的项目使用自定义路由,那么有可能不同的路由会得到相同的内容,可以优化SEO和用户体验。 +如果你的项目使用自定义路由,那么有可能不同的路由会得到相同的内容,可以优化 SEO 和用户体验。 禁止路由链接到`/pages`下的文件,只需设置`next.config.js`文件如下所示: @@ -929,9 +924,9 @@ app.prepare().then(() => {

-ext.js支持JavaScript的TC39提议[dynamic import proposal](https://github.com/tc39/proposal-dynamic-import)。你可以动态导入JavaScript模块(如React组件)。 +ext.js 支持 JavaScript 的 TC39 提议[dynamic import proposal](https://github.com/tc39/proposal-dynamic-import)。你可以动态导入 JavaScript 模块(如 React 组件)。 -动态导入相当于把代码分成各个块管理。Next.js服务端动态导入功能,你可以做很多炫酷事情。 +动态导入相当于把代码分成各个块管理。Next.js 服务端动态导入功能,你可以做很多炫酷事情。 下面介绍一些动态导入方式: @@ -973,7 +968,7 @@ export default () => ``` -#### 3. 禁止使用SSR +#### 3. 禁止使用 SSR ```jsx import dynamic from 'next/dynamic' @@ -1032,9 +1027,9 @@ export default () => - 当页面变化时保持页面布局 - 当路由变化时保持页面状态 - 使用`componentDidCatch`自定义处理错误 -- 注入额外数据到页面里 (如GraphQL查询) +- 注入额外数据到页面里 (如 GraphQL 查询) -重写的话,新建`./pages/_app.js`文件,重写App模块如下所示: +重写的话,新建`./pages/_app.js`文件,重写 App 模块如下所示: ```js import App, {Container} from 'next/app' @@ -1071,7 +1066,7 @@ export default class MyApp extends App { - 在服务端呈现 - 初始化服务端时添加文档标记元素 -- 通常实现服务端渲染会使用一些css-in-js库,如[styled-components](./examples/with-styled-components), [glamorous](./examples/with-glamorous) 或 [emotion](with-emotion)。[styled-jsx](https://github.com/zeit/styled-jsx)是Next.js自带默认使用的css-in-js库 +- 通常实现服务端渲染会使用一些 css-in-js 库,如[styled-components](./examples/with-styled-components), [glamorous](./examples/with-glamorous) 或 [emotion](with-emotion)。[styled-jsx](https://github.com/zeit/styled-jsx)是 Next.js 自带默认使用的 css-in-js 库 `Next.js`会自动定义文档标记,比如,你从来不需要添加``, ``等。如果想自定义文档标记,你可以新建`./pages/_document.js`,然后扩展`Document`类: @@ -1106,9 +1101,9 @@ export default class MyDocument extends Document { 钩子[`getInitialProps`](#fetching-data-and-component-lifecycle)接收到的参数`ctx`对象都是一样的 -- 回调函数`renderPage`是会执行React渲染逻辑的函数(同步),这种做法有助于此函数支持一些类似于 Aphrodite的 renderStatic等一些服务器端渲染容器。 +- 回调函数`renderPage`是会执行 React 渲染逻辑的函数(同步),这种做法有助于此函数支持一些类似于 Aphrodite 的 renderStatic 等一些服务器端渲染容器。 -__注意:`
`外的React组件将不会渲染到浏览器中,所以那添加应用逻辑代码。如果你页面需要公共组件(菜单或工具栏),可以参照上面说的`App`组件代替。__ +__注意:`
`外的 React 组件将不会渲染到浏览器中,所以那添加应用逻辑代码。如果你页面需要公共组件(菜单或工具栏),可以参照上面说的`App`组件代替。__ ### 自定义错误处理 @@ -1174,9 +1169,9 @@ export default class Page extends React.Component { ### 自定义配置 -如果你想自定义Next.js的高级配置,可以在根目录下新建`next.config.js`文件(与`pages/` 和 `package.json`一起) +如果你想自定义 Next.js 的高级配置,可以在根目录下新建`next.config.js`文件(与`pages/` 和 `package.json`一起) -注意:`next.config.js`是一个Node.js模块,不是一个JSON文件,可以用于Next启动服务已经构建阶段,但是不作用于浏览器端。 +注意:`next.config.js`是一个 Node.js 模块,不是一个 JSON 文件,可以用于 Next 启动服务已经构建阶段,但是不作用于浏览器端。 ```js // next.config.js @@ -1197,7 +1192,7 @@ module.exports = (phase, {defaultConfig}) => { } ``` -`phase`是配置文件被加载时的当前内容。你可看到所有的phases常量:[constants](./lib/constants.js) +`phase`是配置文件被加载时的当前内容。你可看到所有的 phases 常量:[constants](./lib/constants.js) 这些常量可以通过`next/constants`引入: ```js @@ -1228,9 +1223,9 @@ module.exports = { ``` -#### 禁止etag生成 +#### 禁止 etag 生成 -你可以禁止etag生成根据你的缓存策略。如果没有配置,Next将会生成etags到每个页面中。 +你可以禁止 etag 生成根据你的缓存策略。如果没有配置,Next 将会生成 etags 到每个页面中。 ```js // next.config.js @@ -1240,9 +1235,9 @@ module.exports = { ``` -#### 配置onDemandEntries +#### 配置 onDemandEntries -Next暴露一些选项来给你控制服务器部署以及缓存页面: +Next 暴露一些选项来给你控制服务器部署以及缓存页面: ```js module.exports = { @@ -1255,12 +1250,12 @@ module.exports = { } ``` -这个只是在开发环境才有的功能。如果你在生成环境中想缓存SSR页面,请查看[SSR-caching](https://github.com/zeit/next.js/tree/canary/examples/ssr-caching +这个只是在开发环境才有的功能。如果你在生成环境中想缓存 SSR 页面,请查看[SSR-caching](https://github.com/zeit/next.js/tree/canary/examples/ssr-caching) #### 配置页面后缀名解析扩展 -如typescript模块[`@zeit/next-typescript`](https://github.com/zeit/next-plugins/tree/master/packages/next-typescript),需要支持解析后缀名为`.ts`的文件。`pageExtensions` 允许你扩展后缀名来解析各种pages下的文件。 +如 typescript 模块[`@zeit/next-typescript`](https://github.com/zeit/next-plugins/tree/master/packages/next-typescript),需要支持解析后缀名为`.ts`的文件。`pageExtensions` 允许你扩展后缀名来解析各种 pages 下的文件。 ```js // next.config.js @@ -1270,9 +1265,9 @@ module.exports = { ``` -#### 配置构建ID +#### 配置构建 ID -Next.js使用一个常量来判断你的应用服务是哪个版本。因为多个服务部署应用,那`next build`命令将会在多个服务器中运行,为了保持同一个构建ID,可以配置`generateBuildId`函数: +Next.js 使用构建时生成的常量来标识你的应用服务是哪个版本。在每台服务器上运行构建命令时,可能会导致多服务器部署出现问题。为了保持同一个构建 ID,可以配置`generateBuildId`函数: ```js // next.config.js @@ -1285,7 +1280,7 @@ module.exports = { ``` -### 自定义webpack配置 +### 自定义 webpack 配置

Examples @@ -1341,8 +1336,8 @@ module.exports = { - `dev` - `Boolean`型,判断你是否在开发环境下 - `isServer` - `Boolean` 型,为`true`使用在服务端, 为`false`使用在客户端. - `defaultLoaders` - 对象型 ,内部加载器, 你可以如下配置 - - `babel` - 对象型,配置`babel-loader. - - `hotSelfAccept` - 对象型, `hot-self-accept-loader`配置选项.这个加载器只能用于高阶案例。如 [`@zeit/next-typescript`](https://github.com/zeit/next-plugins/tree/master/packages/next-typescript)添加顶层typescript页面。 + - `babel` - 对象型,配置`babel-loader`. + - `hotSelfAccept` - 对象型, `hot-self-accept-loader`配置选项.这个加载器只能用于高阶案例。如 [`@zeit/next-typescript`](https://github.com/zeit/next-plugins/tree/master/packages/next-typescript)添加顶层 typescript 页面。 `defaultLoaders.babel`使用案例如下: @@ -1369,7 +1364,7 @@ module.exports = { ``` -### 自定义babel配置 +### 自定义 babel 配置

Examples @@ -1378,7 +1373,9 @@ module.exports = { 为了扩展方便我们使用`babel`,可以在应用根目录新建`.babelrc`文件,该文件可配置。 -如果有该文件,我们将会考虑来源的真实性,因此同样你需要定义next,也就是 `next/babel`预设。 +如果有该文件,我们将会考虑数据源,因此也需要定义 next 项目需要的东西,也就是 `next/babel`预设。 + +这种设计方案将会使你不诧异于我们可以定制 babel 配置。 下面是`.babelrc`文件案例: @@ -1389,7 +1386,7 @@ module.exports = { } ``` -`next/babel`预设可处理各种React应用所需要的情况。包括: +`next/babel`预设可处理各种 React 应用所需要的情况。包括: - preset-env - preset-react @@ -1398,7 +1395,7 @@ module.exports = { - plugin-transform-runtime - styled-jsx -presets / plugins不允许添加到`.babelrc`中,然而你可以配置`next/babel`预设: +presets / plugins 不允许添加到`.babelrc`中,然而你可以配置`next/babel`预设: ```json { @@ -1414,7 +1411,7 @@ presets / plugins不允许添加到`.babelrc`中,然而你可以配置`next/ba } ``` -`"preset-env"`模块选项应该保持为false,否则webpack代码分割将被禁用。 +`"preset-env"`模块选项应该保持为 false,否则 webpack 代码分割将被禁用。 @@ -1450,14 +1447,14 @@ export default () =>
``` -### 启动服务选择hostname +### 启动服务选择 hostname -启动开发环境服务可以设置不同的hostname,你可以在启动命令后面加上`--hostname 主机名` 或 `-H 主机名`。它将会启动一个TCP服务器来监听连接所提供的主机。 +启动开发环境服务可以设置不同的 hostname,你可以在启动命令后面加上`--hostname 主机名` 或 `-H 主机名`。它将会启动一个 TCP 服务器来监听连接所提供的主机。 -### CDN支持前缀 +### CDN 支持前缀 -建立一个CDN,你能配置`assetPrefix`选项,去配置你的CDN源。 +建立一个 CDN,你能配置`assetPrefix`选项,去配置你的 CDN 源。 ```js const isProd = process.env.NODE_ENV === 'production' @@ -1467,7 +1464,7 @@ module.exports = { } ``` -注意:Next.js运行时将会自动添加前缀,但是对于`/static`是没有效果的,如果你想这些静态资源也能使用CDN,你需要自己添加前缀。有一个方法可以判断你的环境来加前缀,如 [in this example](https://github.com/zeit/next.js/tree/master/examples/with-universal-configuration)。 +注意:Next.js 运行时将会自动添加前缀,但是对于`/static`是没有效果的,如果你想这些静态资源也能使用 CDN,你需要自己添加前缀。有一个方法可以判断你的环境来加前缀,如 [in this example](https://github.com/zeit/next.js/tree/master/examples/with-universal-configuration)。 ## 项目部署 @@ -1497,7 +1494,7 @@ next start 然后就可以直接运行`now`了。 -Next.js也有其他托管解决方案。请查考wiki章节['Deployment'](https://github.com/zeit/next.js/wiki/Deployment) 。 +Next.js 也有其他托管解决方案。请查考 wiki 章节['Deployment'](https://github.com/zeit/next.js/wiki/Deployment) 。 注意:`NODE_ENV`可以通过`next`命令配置,如果没有配置,会最大渲染,如果你使用编程式写法的话[programmatically](#custom-server-and-routing),你需要手动设置`NODE_ENV=production`。 @@ -1507,9 +1504,9 @@ Next.js也有其他托管解决方案。请查考wiki章节['Deployment'](https: ## 浏览器支持 -Next.js支持IE11和所有的现代浏览器使用了[`@babel/preset-env`](https://new.babeljs.io/docs/en/next/babel-preset-env.html)没包括polyfills。有时候你的代码或引入的其他npm包的部分功能现代浏览器不支持,则需要用polyfills去实现。 +Next.js 支持 IE11 和所有的现代浏览器使用了[`@babel/preset-env`](https://new.babeljs.io/docs/en/next/babel-preset-env.html)。为了支持 IE11,Next.js 需要全局添加`Promise`的 polyfill。有时你的代码或引入的其他 NPM 包的部分功能现代浏览器不支持,则需要用 polyfills 去实现。 -ployflls实现案例为[polyfills](https://github.com/zeit/next.js/tree/canary/examples/with-polyfills)。 +ployflls 实现案例为[polyfills](https://github.com/zeit/next.js/tree/canary/examples/with-polyfills)。 ## 导出静态页面 @@ -1519,12 +1516,11 @@ ployflls实现案例为[polyfills](https://github.com/zeit/next.js/tree/canary/e

-`next export`可以输出一个Next.js应用作为静态资源应用而不依靠 Node.js服务。 -这个输出的应用几乎支持Next.js的所有功能,包括动态路由,预获取,预加载以及动态导入。 +`next export`可以输出一个 Next.js 应用作为静态资源应用而不依靠 Node.js 服务。 +这个输出的应用几乎支持 Next.js 的所有功能,包括动态路由,预获取,预加载以及动态导入。 -`next export`将把所有有可能渲染出的HTML都生成。这是基于映射对象的`pathname`关键字关联到页面对象。这个映射叫做`exportPathMap`。 +`next export`将把所有有可能渲染出的 HTML 都生成。这是基于映射对象的`pathname`关键字关联到页面对象。这个映射叫做`exportPathMap`。 -The page object has 2 values: 页面对象有2个属性: - `page` - 字符串类型,页面生成目录 @@ -1534,7 +1530,7 @@ The page object has 2 values: ### 使用 -通常开发Next.js应用你将会运行: +通常开发 Next.js 应用你将会运行: ``` next build @@ -1561,7 +1557,7 @@ module.exports = { } ``` -> 注意:如果path的结尾是目录名,则将导出`/dir-name/index.html`,但是如果结尾有扩展名,将会导出对应的文件,如上`/readme.md`。如果你使用`.html`以外的扩展名解析文件时,你需要设置header的`Content-Type`头为"text/html". +> 注意:如果 path 的结尾是目录名,则将导出`/dir-name/index.html`,但是如果结尾有扩展名,将会导出对应的文件,如上`/readme.md`。如果你使用`.html`以外的扩展名解析文件时,你需要设置 header 的`Content-Type`头为"text/html". 输入下面命令: @@ -1570,7 +1566,7 @@ next build next export ``` -你可以在`package.json`添加一个NPM脚本,如下所示: +你可以在`package.json`添加一个 NPM 脚本,如下所示: ```json { @@ -1591,7 +1587,7 @@ npm run export > 你也可以自定义输出目录。可以运行`next export -h`命令查看帮助。 -现在你可以部署`out`目录到任意静态资源服务器上。注意如果部署GitHub Pages需要加个额外的步骤,[文档如下](https://github.com/zeit/next.js/wiki/Deploying-a-Next.js-app-into-GitHub-Pages) +现在你可以部署`out`目录到任意静态资源服务器上。注意如果部署 GitHub Pages 需要加个额外的步骤,[文档如下](https://github.com/zeit/next.js/wiki/Deploying-a-Next.js-app-into-GitHub-Pages) 例如,访问`out`目录并用下面命令部署应用[ZEIT Now](https://zeit.co/now). @@ -1602,35 +1598,35 @@ now ### 限制 -使用`next export`,我们创建了个静态HTML应用。构建时将会运行页面里生命周期`getInitialProps` 函数。 +使用`next export`,我们创建了个静态 HTML 应用。构建时将会运行页面里生命周期`getInitialProps` 函数。 `req`和`res`只在服务端可用,不能通过`getInitialProps`。 -> 所以你不能预构建HTML文件时动态渲染HTML页面。如果你想动态渲染可以运行`next start`或其他自定义服务端API。 +> 所以你不能预构建 HTML 文件时动态渲染 HTML 页面。如果你想动态渲染可以运行`next start`或其他自定义服务端 API。 -## 多zone +## 多 zone

Examples

-一个zone时一个单独的Next.js应用。如果你有很多zone,你可以合并成一个应用。 +一个 zone 时一个单独的 Next.js 应用。如果你有很多 zone,你可以合并成一个应用。 -例如,你如下有两个zone: +例如,你如下有两个 zone: * https://docs.my-app.com 服务于路由 `/docs/**` * https://ui.my-app.com 服务于所有页面 -有多zone应用技术支持,你可以将几个应用合并到一个,而且可以自定义URL路径,使你能同时单独开发各个应用。 +有多 zone 应用技术支持,你可以将几个应用合并到一个,而且可以自定义 URL 路径,使你能同时单独开发各个应用。 -> 与microservices观念类似, 只是应用于前端应用. +> 与 microservices 观念类似, 只是应用于前端应用. -### 怎么定义一个zone +### 怎么定义一个 zone -zone没有单独的API文档。你需要做下面事即可: +zone 没有单独的 API 文档。你需要做下面事即可: * 确保你的应用里只有需要的页面 (例如, https://ui.my-app.com 不包含 `/docs/**`) * 确保你的应用有个前缀[assetPrefix](https://github.com/zeit/next.js#cdn-support-with-asset-prefix)。(你也可以定义动态前缀[dynamically](https://github.com/zeit/next.js#dynamic-assetprefix)) @@ -1638,7 +1634,7 @@ zone没有单独的API文档。你需要做下面事即可: ### 怎么合并他们 -你能使用HTTP代理合并 zone +你能使用 HTTP 代理合并 zone 你能使用代理[micro proxy](https://github.com/zeit/micro-proxy)来作为你的本地代理服务。它允许你定义路由规则如下: @@ -1651,25 +1647,23 @@ zone没有单独的API文档。你需要做下面事即可: } ``` -生产环境部署,如果你使用了[ZEIT now](https://zeit.co/now),可以它的使用[path alias](https://zeit.co/docs/features/path-aliases) 功能。否则,你可以设置你已使用的代理服务编写上面规则来路由HTML页面 +生产环境部署,如果你使用了[ZEIT now](https://zeit.co/now),可以它的使用[path alias](https://zeit.co/docs/features/path-aliases) 功能。否则,你可以设置你已使用的代理服务编写上面规则来路由 HTML 页面 ## 技巧 - [设置301重定向](https://www.raygesualdo.com/posts/301-redirects-with-nextjs/) - [只处理服务器端模块](https://arunoda.me/blog/ssr-and-server-only-modules) -- [构建项目React-Material-UI-Next-Express-Mongoose-Mongodb](https://github.com/builderbook/builderbook) -- [构建一个SaaS产品 React-Material-UI-Next-MobX-Express-Mongoose-MongoDB-TypeScript](https://github.com/async-labs/saas) +- [构建项目 React-Material-UI-Next-Express-Mongoose-Mongodb](https://github.com/builderbook/builderbook) +- [构建一个 SaaS 产品 React-Material-UI-Next-MobX-Express-Mongoose-MongoDB-TypeScript](https://github.com/async-labs/saas) ## 问答
- 这个产品准备好了吗? - Next.js has been powering https://zeit.co since its inception. - https://zeit.co 都是用Next.js写的。 + 这个产品可以用于生产环境吗? + https://zeit.co 都是一直用 Next.js 写的。 - We’re ecstatic about both the developer experience and end-user performance, so we decided to share it with the community. 它的开发体验和终端用户体验都很好,所以我们决定开源出来给大家共享。
@@ -1678,7 +1672,7 @@ zone没有单独的API文档。你需要做下面事即可: 客户端大小根据应用需求不一样大小也不一样。 -一个最简单Next应该用gzip压缩后大约65kb +一个最简单 Next 应该用 gzip 压缩后大约65kb
@@ -1687,99 +1681,98 @@ zone没有单独的API文档。你需要做下面事即可: 是或不是. -是,因为它让你的SSR开发更简单。 +是,因为它让你的 SSR 开发更简单。 不是,因为它规定了一定的目录结构,使我们能做以下更高级的事: - 服务端渲染 - 自动代码分割 -此外,Next.js还提供两个内置特性: +此外,Next.js 还提供两个内置特性: - 路由与懒加载组件: `` (通过引入 `next/link`) - 修改``的组件: `` (通过引入 `next/head`) -如果你想写共用组件,可以嵌入Next.js应用和React应用中,推荐使用`create-react-app`。你可以更改`import`保持代码清晰。 +如果你想写共用组件,可以嵌入 Next.js 应用和 React 应用中,推荐使用`create-react-app`。你可以更改`import`保持代码清晰。
- 怎么解决css嵌入js问题? + 怎么解决 CSS 嵌入 JS 问题? -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. -Next.js自带[styled-jsx](https://github.com/zeit/styled-jsx)库支持css嵌入js。而且你可以选择其他嵌入方法到你的项目中,可参考文档[as mentioned before](#css-in-js)。 +Next.js 自带[styled-jsx](https://github.com/zeit/styled-jsx)库支持 CSS 嵌入 JS。而且你可以选择其他嵌入方法到你的项目中,可参考文档[as mentioned before](#css-in-js)。
- What syntactic features are transpiled? How do I change them? + 哪些语法会被转换?怎么转换它们? -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. +我们遵循 V8 引擎的,如今 V8 引擎广泛支持 ES6 语法以及`async`和`await`语法,所以我们支持转换它们。但是 V8 引擎不支持修饰器语法,所以我们也不支持转换这语法。 -See [this](https://github.com/zeit/next.js/blob/master/server/build/webpack.js#L79) and [this](https://github.com/zeit/next.js/issues/26) +可以参照[这些](https://github.com/zeit/next.js/blob/master/server/build/webpack.js#L79) 以及 [这些](https://github.com/zeit/next.js/issues/26)
- Why a new Router? + 为什么使用新路由? -Next.js is special in that: +Next.js 的特别之处如下所示: -- Routes don’t need to be known ahead of time -- Routes are always lazy-loadable -- Top-level components can define `getInitialProps` that should _block_ the loading of the route (either when server-rendering or lazy-loading) +- 路由不需要被提前知道 +- 路由总是被懒加载 +- 顶层组件可以定义生命周期`getInitialProps`来阻止路由加载(当服务端渲染或路由懒加载时) -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 `` component is used to wrap elements like anchors (``) to perform client-side transitions +- 每个顶层组件都将会收到一个`url`对象,来检查 url 或修改历史记录 +- ``组件用于包装如(``)标签的元素容器,来执行客户端转换。 -We tested the flexibility of the routing with some interesting scenarios. For an example, check out [nextgram](https://github.com/zeit/nextgram). +我们使用了些有趣的场景来测试路由的灵活性,例如,可查看[nextgram](https://github.com/zeit/nextgram)。
-How do I define a custom fancy route? +我怎么定义自定义路由? -We [added](#custom-server-and-routing) the ability to map between an arbitrary URL and any component by supplying a request handler. +我们通过请求处理来[添加](#custom-server-and-routing)任意 URL 与任意组件之前的映射关系。 -On the client side, we have a parameter call `as` on `` that _decorates_ the URL differently from the URL it _fetches_. +在客户端,我们``组件有个属性`as`,可以装饰改变获取到的 URL。
-How do I fetch data? +怎么获取数据? -It’s up to you. `getInitialProps` is an `async` function (or a regular function that returns a `Promise`). It can retrieve data from anywhere. +这由你决定。`getInitialProps`是一个异步函数`async`(也就是函数将会返回个`Promise`)。你可以在任意位置获取数据。
- Can I use it with GraphQL? + 我可以使用 GraphQL 吗? -Yes! Here's an example with [Apollo](./examples/with-apollo). +是的! 这里有个例子[Apollo](./examples/with-apollo).
-Can I use it with Redux? +我可以使用 Redux 吗? -Yes! Here's an [example](./examples/with-redux) +是的! 这里有个[例子](./examples/with-redux)
-Can I use Next with my favorite Javascript library or toolkit? +我可以在 Next 应用中使用我喜欢的 Javascript 库或工具包吗? -Since our first release we've had **many** example contributions, you can check them out in the [examples](./examples) directory +从我们第一次发版就已经提供**很多**例子,你可以查看这些[例子](./examples)。
-What is this inspired by? +什么启发我们做这个? -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. +我们实现的大部分目标都是通过 Guillermo Rauch 的[Web 应用的7原则](http://rauchg.com/2014/7-principles-of-rich-web-applications/)来启发出的。 -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. +PHP 的易用性也是个很好的灵感来源,我们觉得 Next.js 可以替代很多需要用 PHP 输出 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. +与 PHP 不同的是,我们得利于 ES6 模块系统,每个文件会输出一个**组件或方法**,以便可以轻松的导入用于懒加载和测试 -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. +我们研究 React 的服务器渲染时并没有花费很大的步骤,因为我们发现一个类似于 Next.js 的产品,React 作者 Jordan Walke 写的[react-page](https://github.com/facebookarchive/react-page) (现在已经废弃)
From 155284fb13c4e9ae0338bec8bdc9e5cce8fc91ce Mon Sep 17 00:00:00 2001 From: iceRao Date: Sun, 2 Sep 2018 00:18:31 +0800 Subject: [PATCH 3/4] Update README-zh-CN.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 当前翻译版本为 7.0.0-canary.8 --- README-zh-CN.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README-zh-CN.md b/README-zh-CN.md index 7e4b10597b764..e5873a8fded60 100644 --- a/README-zh-CN.md +++ b/README-zh-CN.md @@ -7,11 +7,10 @@ [![Join the community on Spectrum](https://withspectrum.github.io/badge/badge.svg)](https://spectrum.chat/next-js) Next.js 是一个轻量级的 React 服务端渲染应用框架。 -翻译版本为 7.0.0-canary.8。 **可访问 [nextjs.org/learn](https://nextjs.org/learn) 开始学习 Next.js.** -[README in English](readme.md) +[README in English](README.md) --- From b89a7dee117454fe010d7abd9d7bc9c5dfa86a47 Mon Sep 17 00:00:00 2001 From: qqnewtouch Date: Mon, 3 Sep 2018 00:16:37 +0800 Subject: [PATCH 4/4] anchor bugfix --- README-zh-CN.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README-zh-CN.md b/README-zh-CN.md index e5873a8fded60..2e3a7a3783e70 100644 --- a/README-zh-CN.md +++ b/README-zh-CN.md @@ -82,11 +82,11 @@ Next.js 是一个轻量级的 React 服务端渲染应用框架。 -## 怎么使用
+## 怎么使用 -### 安装 +### 安装 安装它: @@ -141,6 +141,7 @@ export default () => ``` + ### CSS @@ -407,7 +408,7 @@ import Link from 'next/link' export default () =>
Click{' '} - + here {' '} to read more @@ -1780,7 +1781,7 @@ PHP 的易用性也是个很好的灵感来源,我们觉得 Next.js 可以替 可查看 [contributing.md](./contributing.md) - + ## 作者 - Arunoda Susiripala ([@arunoda](https://twitter.com/arunoda)) – [ZEIT](https://zeit.co)