概览
serverless function?
由Vercel开发的Next.js,长期以来都是服务器端渲染(SSR)的不二之选。凭借强大的社区支持、与React的紧密集成以及灵活的渲染选项,Next.js广受欢迎。
Next.js 仍然是SEO优先的应用程序和SSR密集型应用程序的绝佳选择
优点:
- SSR和静态生成: 通过直接从服务器提供静态HTML,非常适合SEO和快速初始加载。
- 自动代码拆分: 只加载当前页面所需的JavaScript代码,从而缩短加载时间。
- 基于文件的路由: 简单易用的路由系统,使用文件结构映射路由。
缺点:
- 构建时间: 尤其是对于大型项目,使用Webpack会随着项目规模的增长而减缓开发速度。
- 数据获取: Next.js在服务器端数据获取方面表现良好,但在客户端密集型应用程序中可能会变得更加复杂。
- SSR开销: 如果你不需要SSR,Next.js可能显得过于复杂,可能会增加不必要的复杂性。
目录
├─public ├─style ├─components │ ├─layout │ └─comp2 │─pages ├─_app.j └─page-1 └─page-2
渲染方式
水合(Hydration)过程
- Next.js 在服务端渲染时,会先在服务器上生成包含页面内容的 HTML 结构。
- 当这个 HTML 被发送到客户端浏览器后,React 对 HTML 文件进行解析,识别 HTML 中特点的标记和属性,然后与客户端的 React 组件进行关联激活
- 然后,React 会将客户端的 JavaScript 逻辑和事件处理程序附加到相应的 HTML 元素上,使得页面具备交互能力,比如可以响应用户的点击、输入等操作
Pre-rendering
默认所有的页面都会被 pre-rendering,Next.js 有两种 pre-rendering 形式,他们的区别在于生成 HTML 的时机。
Next.js has two forms of pre-rendering: Static Generation and Server-side Rendering.
一、 Static Generation is the pre-rendering method that generates the HTML at build time. The pre-rendered HTML is then reused on each request.
在用户请求之前生成页面,不涉及动态数据,无法使用仅在请求期间可用的数据,例如查询参数或HTTP标头。
API:getStaticProps,只在服务端执行
In development mode (when you run
npm run dev
oryarn dev
), every page is pre-rendered on each request — even for pages that use Static Generation.getStaticProps
runs only on the server-side. It will never run on the client-side. It won’t even be included in the JS bundle for the browser.
推荐使用 getStaticProps
而不是 getInitialProps
- getInitialProps 不能与 getStaticProps 或 getStaticPaths 同时用于任何给定页面。如果您有动态路由,则需要在 next.config.js 文件中配置 exportPathMap 参数,让输出程序知道应该输出哪些 HTML 文件,而不是使用 getStaticPaths。
- When
getInitialProps
is called during export, thereq
andres
fields of itscontext
parameter will be empty objects, since during export there is no server running. getInitialProps
will be called on every client-side navigation, if you'd like to only fetch data at build-time, switch togetStaticProps
.getInitialProps
should fetch from an API and cannot use Node.js-specific libraries or the file system likegetStaticProps
can.
二、 Server-side Rendering is the pre-rendering method that generates the HTML on each request.
每次请求时,获取数据,然后生成 HTML 文件
API:getServerSideProps,只在服务端执行
Serve-Side Rendering 的 TTFB 比 Static Generation 慢
Q:如何判断一个页面是静态生成的页面?
- A:如果没有阻塞数据要求,Next.js 就会自动判断页面是静态的。这意味着页面中没有 getServerSideProps 和 getInitialProps。
根据动态路由生成静态 HTML
Client-side Rendering
Client-side 请求数据推荐使用 Nextjs 内置的 swr
hook。
在 jsx
文件顶部添加 React 的 "use client"
指令,将文件转换为客户端组件。
通过添加 'use server'
,您将文件中的所有导出函数标记为服务器函数。然后可以将这些服务器函数导入到 Client 和 Server 组件中,使它们变得非常灵活。
Incremental Static Regeneration (ISR)
增量静态再生
服务端
A custom server cannot be deployed on Vercel.
Next
Next.js 是一个全栈式的 React 框架。它用途广泛,可以让你创建任意规模的 React 应用——可以是静态博客,也可以是复杂的动态应用。要创建一个新的 Next.js 项目,请在你的终端运行
介绍
用于React应用的极简的服务端渲染框架。
Next 创建的应用中只有初始页面采用服务端渲染,其他通过路由操作到达的页面均为客户端渲染。
pages:./pages 是一个保留路径,在 /pages 路径下任何js文件中导出的默认 React 组件都被视作一个页面;pages中的文件结构自动映射为对应的路由结构;
static:保留路径,存放静态资源;
package.json
{
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
}
}
- 使用了 Next.js 作为服务端渲染工具,切记仅使用 next/link 中的 Link 组件。
<Link href="/about">
<a style={{fontSize: 20}}>About Page</a>
</Link>
组件
Head
<Head>
<title>My page title</title>
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
</Head>
link
document
自定义自己的服务端渲染模板,创建 /_document.js
// pages/_document.js
import Document, { Head, Main, NextScript } from 'next/document'
export default
class MyDocument extends Document {
static async getInitialProps (ctx) {
const props = await Document.getInitialProps(ctx)
return { ...props, customValue: 'hi there!' }
}
render () {
return (
<html>
<Head>
<style>{`body { margin: 0 } /* custom! */`}</style>
</Head>
<body className="custom_class">
{this.props.customValue}
<Main />
<NextScript />
</body>
</html>
)
}
}
错误处理
Next中,有一个默认组件error.js,负责处理404或者500这种错误。当然,你也可以自定义一个_error.js组件覆盖默认的错误处理组件:
自定义服务器和路由
项目根目录下创建 server.js 文件:
// server.js
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) => {
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')
})
})
CSS
NEXT组件中声明CSS,目前主要有两种方式:
- 内嵌CSS:组件级的独立作用域,利用 styled-jsx 库
export default () => (
<div>
Hello world
<p>scoped!</p>
<style jsx>{`
p {
color: blue;
}
div {
background: red;
}
div:hover {
background: blue;
}
@media (max-width: 600px) {
div {
background: blue;
}
}
`}</style>
</div>
)
scope CSS
的作用范围,如果添加了 jsx
属性,则是不包括子组件的当前组件;如果添加了 global
和 jsx
属性,则是包括了子组件在内的当前组件;如果没添加任何属性,则作用与 添加了 global
和 jsx
的作用类似,只不过 next
不会对其进行额外的提取与优化打包。
- CSS-in-JS 内联样式
export default () => (
<div style={{color: red}}>
Hello world
</div>
)
服务端框架
next.js自带服务器,但是它可以做的事情很有限,只能处理 ssr 渲染。 我们可以将next.js作为 koa 的一个中间件来使用,当然您也可以选择 express 和 egg.js,使用方式都很类似。
部署
生产模式下,需要先使用生产模式构建代码,再启动服务器。因此,需要两条命令:
- npm run build
- npm run start
Next官方推荐使用now作为部署工具,只要在package.json文件中写入:
{
"name": "my-app",
"dependencies": {
"next": "latest"
},
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
}
}
接着运行now命令,就可以实现一键部署。