Next.js
Naoyuki Kanezawa (@nkzawa), Guillermo Rauch (@rauchg) 和 Tony Kovanen (@tonykovanen)
周二,2016年10月25日
我们非常骄傲的开源了Next.js,他是一个玲珑的基于React、Webpack、Babel的客户端衬着universal JavasScript web app框架。
要最先运用Next.js,只需在一个有package.json
的文件夹里实行以下敕令:
$ npm install next --save
$ mkdir pages
天生pages/index.js
:
import React from 'react'
export default () => <div>Hello world!</div>
然后在package.json
里增加一个script:
{
"scripts": {
"dev": "next"
}
}
然后实行:
$ npm run dev
本文主要论述该项目的设想理念和它背地的哲学思想。
假如想进修怎样运用Next.js,请移步README,在那你只需花几分钟就能够进修完统统功用。
起首我们会深切该项目的后端并一一形貌以下6个准绳:
零设置,运用文件体系作为API
只要JavaScript,统统都是函数
自动服务端衬着和代码支解
完全可定制的数据猎取体式格局
展望是进步机能的症结
布置简朴
背景
从许多年之前,我们就一向寻求universal JavaScript applications的途径。
Node.js展现了这类可能性,客户端服务端代码同享,也扩大了开辟者的视野。
为了能在Node上开辟app和网页,开辟者做了许多许多尝试。无数的模板语言和框架应运而生……然则手艺一直被支解为前端和后端。
假定你挑选Express和Jade开辟,HTML会起首被服务端衬着,然后别的一个项目(jQuery或是其他相似库)才会接受过去。
如许的状况实在一点也不比传统的PHP体式格局好若干。从许多方面来讲,PHP都更适合服务端衬着HTML如许的事情。在涌现async
/await
之前,在JS中查询数据并不轻易。捕捉和处置惩罚request/response的非常也非常贫苦。
但是,一些值得关注的观点的涌现,使得我们能够弥补这个空缺。个中最主要的就是能够依据数据返回对应UI的纯函数。
这个模子(因React而盛行)非常主要,不过仅仅有他还不能从浩瀚的模板体系中脱颖而出。别的一个主要的观点就是组件生命周期。
生命周期的钩子函数许可我们在前端接受某些之前由服务端衬着的的页面。比方说,你能够在一最先只衬着静态数据,监听服务端的更新,并依据数据转变页面。或许什么也不做,让这个页面坚持静态。
Next.js是我们在这条路上更近一步的效果。
零设置,运用文件体系作为API
东西假定你的项目具有特定的文件构造。
一般来讲,我们最先一个新项目时,都邑新建一个文件夹,在里面放一个package.json
,在./node_modules
中装置模块。
Next.js扩大了这类构造,引入了一个安排顶级组件的文件夹叫pages
。
比方,你能够新建pages/index.js
,它会自动映射到/
路由:
import React from 'react'
export default () => <marquee>Hello world</marquee>
然后新建pages/about.js
,它会映射到/about
路由:
import React from 'react'
export default () => <h1>About us</h1>
我们置信这是一个很好的起步默许设置,而且非常便于项目阅读。当须要更庞杂的路由时,我们也许可开辟人员自行掌握[#25]。
启动一个项目所须要的统统操纵仅仅是运转:
$ next
除非必要,没有分外的设置。自动代码热替代,自动错误报告,自动source maps,自动为老旧阅读器编译代码。
只要JavaScript,统统都是函数
每一个Next.js的路由都是一个仅仅是一个export
一个函数或一个继续自React.Component
的子类所组成的ES6模块。
这个体式格局和其他相似模子比拟的优点是,全部体系都能坚持高可组合性和可测试性。一个组件能够被直接衬着也能够被其他顶级组件导入并衬着。
组件也能够转变全部page的<head>
:
import React from 'react'
import Head from 'next/head'
export default () => (
<div>
<Head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</Head>
<h1>Hi. I'm mobile-ready!</h1>
</div>
)
而且,不须要任何包装或修改就能够对全部体系举行测试。只需在你的测试集合导入并shallow-render
你的路由。
拥抱CSS-in-JS
。经由过程运用glamor使得我们能在完全不剖析CSS剖析和编译的情况下具有完全的CSS功用:
import React from 'react'
import css from 'next/css'
export default () => <p className={style}>Hi there!</p>
const style = css({
color: 'red',
':hover': {
color: 'blue'
},
'@media (max-width: 500px)': {
color: 'rebeccapurple'
}
})
我们以为这类体式格局供应了无与伦比的机能,可组合性以及和服务器端衬着流程的优越集成。我们在FAQ中会议论更多关于这个决议的统统。
自动服务端衬着和代码支解
有两个非常想完成同时又非常难题的使命:
服务端衬着
代码支解
在Next.js中,每一个pages/
下面的组件都邑自动的连同内联的剧本一同被服务端衬着。
当组件是经由过程<Link />
或路由自动加载时,我们会猎取一个基于JSON的页面,这个页面同样会包括他本身的剧本。
这意味着一个页面能够有许多的imports:
import React from 'react'
import d3 from 'd3'
import jQuery from 'jquery'
… 这并不会对其他的页面有任何影响。
这点关于那些须要手艺营业需求差别的团队互相合作的场景下迥殊有用。一个组件的机能题目不会影响到全部体系。
完全可定制的数据猎取体式格局
服务端衬着的静态JSX确切非常了不得,但实际天下的运用每每须要处置惩罚来自差别API挪用的数据。
Next.js给React的组件增加了一个主要的扩大:getInitialProps
。
import React from 'react'
import 'isomorphic-fetch'
export default class extends React.Component {
static async getInitialProps () {
const res = await fetch('https://api.company.com/user/123')
const data = await res.json()
return { username: data.profile.username }
}
}
我们关于转换哪些功用的态度简朴来讲就是:我们牢牢追随V8。由于我们的目的是服务端和客户端的代码同享,当我们用Chrome或许Brave开辟,并在Node上实行代码时,这类做法给了我们极好的体验。
正如你所见,我们的扩大非常简朴:getInitialProps
必需返回一个能resolve
为一个JavaScript对象的Promise
,该对象会被用来天生组件的props
。
这使得Next.js能很好的和REST APIs、GraphQL,以至是全局状况治理Redux等很好的合作,这有一个示例在我们的wiki上。
不管组件是服务端衬着的照样经由过程客户端路由动态加载的,都能够运用同一个要领取得数据:
static async getInitialProps ({ res }) {
return res
? { userAgent: res.headers['user-agent'] }
: { userAgent: navigator.userAgent }
}
展望是进步机能的症结
我们以为纵然没有收集也能赋予用户立即相应的才能使得完全服务端衬着倾向“单页运用”或“完全没有服务端衬着”两个极度。
在www.zeit.co我们在Next.js上完成了一种手艺,让我们能同时享用两种体式格局各自的优点:每一个<Link />
标签都邑在背景经由过程一个ServiceWorker提早猎取组件的JSON表现。
一旦预加载完成,假如你在页面上随便跳转,你点击的某个链接或路由已提早加载好了。
更好的是,由于数据也经由过程一个专用的要领getInitialProps
,我们能提早加载而不必怕激发不必要的服务端负载和数据加载。这比之前的web 1.0预加载机制强多了。
布置简朴
我们建立Next.js是由于我们置信同构的运用是将来web运用的主要组成部分。
提早绑定和编译(展望)是一个非常有用的布置体式格局。
布置一个Next.js运用只须要运转next build
和next start
。
你的package.json
文件和以下相似:
{
"name": "my-app",
"dependencies": {
"next": "*"
},
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
}
}
如许,你就简朴的布置胜利了。
末了,这是我们关于这个特定题目的孝敬。我们以为他在灵活性和好用的默许设置之间取得了不错的均衡,不过这一定不是处理统统题目的要领。
在接下来的几周里,我们希望能更多的议论和思索其他处理方案,比方Vue.JS, Gatsby, Ember+Fastboot等等。
假如你有兴致到场我们的社区,做出本身的孝敬,请一定要到场zeit.chat, 检察issues,介入将来方向的议论。