Next.js
一.介绍
- Next.js是React服务端渲染应用框架.用于构建SEO友好的SPA应用
- 支持两种预渲染方式,静态生成和服务器端渲染
- 基于页面的路由系统,路由零配置
- 自动代码拆分,优化页面加载速度
- 支持静态导出,可将应用导出为静态网站
- 内置CSS-in-JS库styled-jsx
- 方案成熟,可用于生产环境,世界许多公司都在使用
- 应用部署简单,拥有专属部署环境Vercel,也可以部署在其他环境
二.创建 Next.js 项目
- 创建:
npm init next-app next-guide
- 运行:
npm run dev
- 访问:
localhost:3000
- 临时安装
create-next-app
用于创建Next.js
项目。
三.基于页面的路由系统
创建页面
- 在Next.js中,页面是被放置在pages文件夹中的React组件
- 组件需要被默认导出
- 组件文件中不需要引入React
- 页面地址与文件地址是对应的关系
- index页面可以直接通过
/
访问
页面跳转
- Link 组件
默认使用 JavaScript 进行页面跳转
.即 SPA 形式的跳转 - 如果浏览器中 JavaScript 被禁用.则使用链接跳转
- Link 组件中只能添加 href 属性,其余属性添加到 a 标签上
- Link 组件通过预取(在生产中)功能自动优化应用程序以获得最佳性能
import Link from 'next/link'
export default function Home() {
return <div>
index page works
<Link href="/list">
<a>jump to list page</a>
</Link>
</div>
}
四.静态资源、元数据和 CSS
静态资源
- 应用程序根目录中的 public 文件夹用于提供静态资源。
public/images/1.jpg
直接用/images/1.jpg
访问public/css/base.jpg
直接用/css/base.css
访问
通过 Head 组件修改元数据
import Head from 'next/head'
function List() {
return (
<>
<Head>
<title>list page</title>
</Head>
<div>这是list页面</div>
</>
)
}
export default List
在Next应用中添加样式的方式
内置 styled-jsx
<>
<Link href="/list">
<a className="demo">jump to list page</a>
</Link>
<style jsx>{`
.demo {
color : red
}
`}
</style>
</>
CSS 模块
- 通过使用 CSS 模块功能,允许将组件的 CSS 样式编写在单独的 CSS 文件中
- CSS 模块约定样式文件的名称必须为
"组件文件名称.module.css"
// pages/list.js
import Head from "next/head";
import style from './list.module.css'
export default function List () {
return (
<>
<Head>
<title>List Page</title>
</Head>
<div className={style.demo}>List Page</div>
</>
)
}
/* page/list.module.css */
.demo {
color: green;
font-size: xx-large;
}
添加全局样式文件
- 在 pages 文件夹中新建
_app.js
文件并加入如下代码 - 在项目根目录下创建 styles 文件夹,并在其中创建 global.css
- 在 _app.js 中通过 import 引入 global.css.
- 重新启动开发服务器
import '../styles/globals.css'
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
export default MyApp
五.预渲染
概述
- 预渲染是指
数据和 HTML 的拼接在服务器端提前完成
- 预渲染可以使
SEO
更加友好 - 预渲染会
带来更好的用户体验
,可以无需运行 JavaScript 即可查看应用程序 UI
预渲染的两种形式
- 在 Next.js 中支持两种形式的预渲染:
静态生成
和服务器端渲染
- 静态生成和服务器端渲染是
生成 HTML
的时机不同
- 静态生成:静态生成是在
构建时
生成 HTML 。以后的每个请求都共用构建时生成好的 HTML - 服务器端渲染:服务器端渲染是在
请求时
生成 HTML 。每个请求都会重新生成 HTML
如何选择
- Next.js 允许开发者为每个页面选择不同的预渲染方式,不同的预渲染方式拥有不同的特点,应根据场景进行渲染
但建议大多数页面建议使用静态生成
- 静态生成一次构建,反复使用,访问速度快,因为页面都是事先生成好的
- 适用场景:营销页面、博客文章、电子商务产品列表、帮助和文档
- 服务器端渲染访问速度不如静态生成快,但是由于每次请求都会重新渲染,所以适用数据频繁更新的页面或页面内容随请求变化而变化的页面
无数据静态生成
- next默认使用的是静态生成
npm run build
之后在.next
下生成的pages
和static
就是无数据生成
- 如果组件不需要外部数据,直接进行静态生成。
有数据静态生成getStaticProps
-
有数据静态生成是在组件需要外部数据时,在构建过程中 Next.js 会预先获取组件需要的数据,然后再对组件进行静态生成。
-
getStaticProps 方法的作用是
获取组件静态生成需要的数据
。并通过返回props
的方式将数据传递给组件。 -
该方法是一个
异步函数
,需要在组件内部进行导出
。 -
在
开发模式
下, getStaticProps在每个请求上运行
。 -
在
生产模式
下, getStaticProps 只会在构建的时候执行
,而每次访问 /list 页面时不会再执行 getStaticProps 方法。
import Head from 'next/head'
import styles from './list.module.css'
import { readFile } from 'fs'
import { promisify } from 'util'
import { join } from 'path'
const read = promisify(readFile)
function List({data}) {
return (
<>
<Head>
<title>list page</title>
</Head>
<div className={styles.demo}>这是list页面</div>
<div>{data}</div>
</>
)
}
export default List
export async function getStaticProps () {
let data = await read(join(process.cwd(),'pages','_app.js'),'utf-8')
console.log(data)
return {
props : {
data
}
}
}
服务器端渲染 getServerSideProps
-
如果采用
服务器端渲染
,需要在组件中导出 getServerSideProps
方法- 将 list.js 中的 getStaticProps 方法 改成 getServerSideProps 方法,其中 getServerSideProps 还有个参数为
context
. context.query
能拿到客户端向服务端的请求参数,比如在浏览器url中的参数
- 将 list.js 中的 getStaticProps 方法 改成 getServerSideProps 方法,其中 getServerSideProps 还有个参数为
-
开发模式下每次访问都会执行
getServerSideProps 方法。 -
生产模式下每次访问都会执行
getServerSideProps 方法:- 运行npm run build生成 .next 文件夹,可以看到 list 页面不会生成 HTML 页面(说明不是静态生成)。
- 然后运行npm start 启动生产环境的代码,访问 /list 页面, node 控制台会输出 getServerSideProps 方法中的打印语句。
- 因为使用了 getServerSideProps 则表示采用服务端渲染,而不是静态生成,所以每次访问都会执行 getServerSideProps 方法。
// export async function getStaticProps () {
export async function getServerSideProps (context) {
let data = await read(join(process.cwd(),'pages','_app.js'),'utf-8')
console.log(context.query) //能拿到客户端向服务端的请求参数,比如在浏览器url中的参数
console.log('hello')
return {
props : {
data
}
}
}
基于动态路由的静态生成
-
创建基于动态路由的页面组件文件,命名时在
文件名称外面加上 []
,比如 [id].js -
导出异步函数 getStaticPaths,
用于获取所有用户可以访问的路由参数
-
导出异步函数 getStaticProps,
用于根据路由参数获取具体的数据
-
npm run build 会根据getStaticPaths返回的paths 去生成对应的html静态文件
- 生成的html静态文件名就是
文件命名对应paths参数的值
- 如下会生成1.html 2.html
- 生成的html静态文件名就是
-
getStaticPaths 和 getStaticProps 只运行在服务器端,永远不会运行在客户端,甚至不会被打包到客户端 JavaScript 中,意味着这里可以随意写服务器端代码,比如查询数据库。
export default function Post ({data}) {
return <div>
<span>{data.id}</span>
<span>{data.title}</span>
</div>
}
// 1.创建[].js 文件,这里是[id].js
// 2.返回用户可以访问到的所有的路由参数
export async function getStaticPaths () {
return {
paths:[{params:{id:'1'}},{params:{id:'2'}}],
fallback:false
}
}
// 3.返回路由参数所对应的具体数据
// 4.npm run build 会根据getStaticPaths返回的paths 去生成对应的html文件
export async function getStaticProps (context) {
const id = context.params.id;
let data;
switch (id) {
case "1":
data = {id:"1",title:'hello'}
break;
case "2":
data = {id:"2",title:'world'}
break;
default:
data = {}
break;
}
return {
props : {
data
}
}
}
自定义 404 页面
-
要创建自定义 404 页面,需要在 pages 文件夹中创建 404.js 文件
export default function Error () { return <div>404 ~</div> }
六.API Routes
概念
- API Routes可以理解为
接口
,客户端向服务端发送请求获取数据的接口
- Next.js应用允许React开发者
编写服务器端代码创建数据接口
实现
-
在
pages/api
文件夹中创建 API Routes 文件。比如 user.js -
在文件中
默认导出请求处理函数
,函数有两个参数,req 为请求对象
,res 为响应对象
export default (req, res) => { res.send({name:'张三',age:20}) }
-
访问 API Routes: localhost:3000/api/user 页面上就能展示 {“name”:“张三”,“age”:20}
- 不要在 getStaticPaths 或 getStaticProps 函数中访问 API Routes, 因为这两个函数就是在服务器端运行的,可以直接写服务器端代码。
七.项目实战
学习了以上这些next相关概念即可实战了,这里贴一下实战项目的地址项目实战github地址