Next.js
创建项目
- 使用命令
npm init next-app [your app name]
页面路由系统
-
创建页面:
-
页面:放置在pages文件夹中的React组件,需要被默认导出
-
组件文件中不需要手动引入React
-
页面的URL地址与文件地址一一对应
-
-
-
页面跳转
-
Link组件:默认使用JavaScript进行跳转,即SPA形式,如果禁用了JavaScript,则使用
<a>
进行跳转-
引入:
import Link from 'next/link'
-
Link组件内添加
<a>
作为子元素<Link href={}><a>跳转</a></Link>
-
不应添加除了href属性外的其他属性,其他属性添加到
<a>
上 -
Link组件在生产环境中,通过预取(prefetch或者preload)来自动优化应用程序(在空闲时间加载跳转后要加载的组件或者页面)
-
-
静态资源访问:
-
根目录的public文件夹用于提供静态资源
-
通过以下形式访问
-
访问路径:
/images/1.jpg
-
对应资源:
public/images/1.jpg
-
修改页面元数据<head>
标签内的元数据标签
-
通过
<Head>
组件修改元数据 -
引入:
import Head from 'next/head'
-
在
<Head>
组件中传递要修改的元数据标签,如修改页面的title<> <Head> <title>自定义页面标题</title> </Head> </>
添加样式
第一种方案:内置styled-jsx
在Next.js中内置了styled-jsx,一个CSS-in-JS的库,允许在React组件中编写CSS样式代码,该样式仅作用于该组件
使用方式如下
<Link href="/list">
<a className="demo">跳转</a>
</Link>
<style jsx>{`
.demo {
color: red;
}
`}
</style>
第二种方案:CSS模块
CSS模块即module css方案
添加全局样式:通常这一步已经由创建项目时自动生成了
-
在pages文件夹中新建_app.js(文件名是固定的)文件并加入下列代码
-
在项目根目录下创建styles文件夹,并创建globals.css文件
-
在_app.js中引入该globals.css文件
-
重新启动开发服务器
import '../styles/globals.css' function MyApp({ Component, pageProps }) { return <Component {...pageProps} /> } export default MyApp
预渲染
定义
在服务端将数据与HTML模板拼接
开发环境下,不会生成HTML文件,只有在生产环境下才会生成HTML文件。
.next文件夹为构建结果文件夹,其中pages为页面的静态文件所在路径
优势
- SEO友好
- 页面加载速度快
两种形式:生成HTML文件的时机不同
静态生成
- 在项目构建时生成HTML文件,客户端的每个请求都共用已经生成好的HTML文件
- 适用场景
- 数据变化不频繁(写操作远少于读操作)
服务器端渲染
-
在客户端请求时生成HTML发送给客户端,每个请求都会生成HTML。
-
适用场景:
- 数据频繁更新的页面
- 页面随请求而变化
静态生成SSG
无数据的静态生成
组件不需要在其他地方获取数据,直接进行静态生成
有数据的静态生成
组件需要在其他地方获取数据,Next.js在构建时,会预先获取组件需要的数据,再对组件进行静态生成
getStaticProps
获取组件静态生成所需要的数据,将数据通过props传给组件
-
该方法是一个异步函数,需要在组件中进行导出
-
该方法是在构建时执行,因此是在服务器端在node.js中运行
-
在开发模式下,该方法在每个请求时都会执行
export async function getStaticProps() {
// 从文件系统、数据库等数据源来获取数据
const data = await ...
// 将数据data放到props中返回
return {
props: ...
}
}
基于动态路由参数的静态生成
路由中有动态参数的情况下,要根据动态参数来生成页面组件,有多少参数就要生成多少页面组件。
在构建应用时,先获取用户可以访问的所有路由参数,再根据路由参数获取具体数据,然后根据数据生成静态HTML页面。
实现方式
-
创建基于动态路由的页面组件文件,命名时在文件名称加上
[]
,比如[id].js
,id为动态路由参数 -
在组件中导出异步函数
getStaticPaths
,用于获取用户可以访问的所有路由参数,Next.js会调用该函数得到所有路由参数后,循环路由参数并调用getStaticProps来得到不同的路由参数对应的不同数据export async function getStaticPaths () { // 此处获取用户可以访问的所有路由参数,实际上这可以从我们的文件路由系统中得到 return { // 返回固定格式的路由参数, paths为数组,数组元素为每个路由对象,其中params为路由对象中的参数,其中的id与我们在定义动态路由组件文件的文件名有关 paths: [ { params: { id: 1 } }, { params: { id: 2 } } ... ], // 当用户访问的路由参数没有在当前函数中返回时,是否显示404页面 // false显示,true不显示 fallback: false } }
-
在组件中导出异步函数
getStaticProps
,用于根据路由参数获取具体数据export async function getStaticProps ({ params }) { // params参数对应着匹配到该组件时的路由参数,如该组件如果是[1].js,则params为{ id: 1} // 此处根据路由参数获取具体数据 return { // 将数据传递给组件使用 props: {} } }
注意:
getStaticPaths
和getStaticProps
只运行在服务器端,不会被打包到客户端,这里的代码都是服务器端代码,可以查询数据库等数据源
fallback的作用
当用户传递的路由参数不在范围内,应该展示什么
-
false:表示给用户展示404页面
-
true:表示获取客户端传递的路由参数,根据该参数获取数据,将该数据传递给组件生成页面,再发送给客户端
-
在构建该页面期间,要给客户端展示一个等待的页面,否则构建不会通过
-
在组件内使用钩子函数useRouter来判断服务端是否在构建该页面
- useRouter()返回一个router对象,router.isFallback属性表示是否正在构建页面
- true表示正在构建期间
- false表示没有构建
import useRouter from 'next/router'; export default function Post ({ data }) { const router = useRouter(); if (router.isFallback) { return <div>正在构建页面中</div> } return <div> 页面内容 </div> }
- useRouter()返回一个router对象,router.isFallback属性表示是否正在构建页面
-
服务器端渲染SSR
getServerSideProps
获取组件所需的数据,将数据通过props传递给组件使用
export async function getServerSideProps(context) {
//context:上下文对象,会包含特定的请求参数,如context.query是请求中的查询参数
return {
props: {
// 组件所需数据
...
}
}
}
自定义404页面
自定义404页面来替换Next.js默认提供的404页面
创建
在pages文件夹中创建404.js文件
API Routes
可以认为是服务端响应客户端数据请求的API接口
Next.js允许开发者编写服务器代码来创建数据接口
创建
-
在pages/api文件夹中创建API Routes文件,如user.js,用来响应对user的数据请求
-
在文件中默认导出请求处理函数,函数有两个参数
- req:请求对象
- res:响应对象
export default function user (req, res) { res.status(200).send({ id: 1, username: 'Tom' }) }
注意:当前API Routes可以接收任何HTTP请求方法
-
访问API接口:
localhost:3000/api/user
注意:不要在getStaticPaths和getStaticProps函数中访问API Routes,这两个方法是在服务器端运行,而访问API Routes是在客户端进行