Nextjs 学习笔记

Posted by CodingWithAlice on January 12, 2025

Nextjs 学习笔记

一、导航相关

1、客户端导航:Nextjs 的前端部分提供内置的「文件系统路由」+ Link

  • Nextjs 13.x 版本开始,<Link> 组件在使用时不用再写<a>标签,因为在渲染时会把 Link 标签解析为 a 标签
    • 实现了「客户端导航」的方式,浏览器不会重新加载整个页面(a标签会触发重新刷新整个页面
  • Nextjs 13.x 版本开始,「文件系统路由」从pages/index.js[旧方式]逐渐改为src/app/page.tsx[新app模式]
    • 旧方式缺点:旧方式容易上手,按文件路径即可推论路由,但复杂嵌套需要写赘余代码
    • 新方式优点:支持自定义共享布局,在 src/app/layout.tsx 可自定义共享的布局(导航栏等)

2、代码分割:Nextjs 会自动进行

3、页面预加载 prefetching:只要有 Link 标签出现在视口,Nextjs 会自动预取 Link 关联的页面代码 -> 点击跳转时后台已经加载好页面了 -> 秒切

二、静态资源加载

包括 css、image、public 文件

1、内置 css 、 sass、css-in-js

2、支持 css Module:

  • 解决的核心问题: nextjs 中 css 全局命名空间问题,将类名进行局部化处理,使得每个组件的样式只在组件内部生效 + 方便 code splitting 代码分割

  • 使用方式:很简单,把style.css 改写/标记为style.module.css即可,其中的类名会被转换为独一无二的标识符

3、全局变量

  • 旧方法:在 pages/_app.js中 import 引入全局 css 文件,利用 _app.js 是整个应用的顶层组件特性,_app.js包裹了所有页面的组件,引入的样式自然就应用到了全局
  • 新方法:src/global.css

三、预渲染

默认情况下,Nextjs 会预渲染每个 page(也就是 预先为每个 page 生成 HTML 文件,而不是由 客户端 js 来生成 - 所以下面说的方法都是在「服务端」执行的,都不会被打包进 js bundle 里面

  • 形式1:静态生成 - 生成 HTML 时机是「构建时」,并在每次页面请求时「重复使用」
    • 在生产环境中,运行 next build 为该页面生成一次 HTML,之后被 CDN 缓存(托管 - 快)
    • 在开发环境/本地环境中,getStaticProps runs on every request
  • 形式2:服务端渲染 - 生成时机是「每次页面请求时重新生成 HTML」
1、静态生成(static generation):别名SSG

这种静态生成的页面,分为「不带数据」(默认)的静态页面和「带数据」的静态页面。

需要获取外部数据的静态生成:

  • 页面内容 取决于数据 – getStaticProps
    • 该函数在「构建时」被调用,在预渲染时,将 props 作为参数传入页面
  • [动态路由]paths 路径取决于数据 – getStaticPaths
    • 例如使用 src/app/[id].tsx 来动态访问文件
    • 该函数在「构建时」被调用,指定要被与渲染的数据

nextjs 中 补丁 fetch 在客户端和服务端都可以执行,不需要再 import

// getStaticPaths、getStaticProps - 在同一文件,通过 export 导出 async 的异步函数
function Blog({posts}) {
    // part① A React Component to render this page
    return <ul>{posts.map((it) => (<li>{it.title}</li>))}</ul>
}
export async function getStaticPaths() {
    // part② getStaticPaths which returnsn an array of possible values for ids
    const res = await fetch('http://xxxx/posts'); // 外部查询
    const post = await res.json(); 
    const paths = posts.map(it => ({ params: { id: it.id } })); // 传递 params 数据,params 中的属性名和文档的 [id].tsx 的 key 相同
    return { paths , fallback: false } // 其他非 paths 的路由为 404
}
export async funciton getStaticProps({ params }){ // 入参来源于 getStaticPaths
    // part③ getStaticProps which fetches necessary data for the post with id
    const res = await fetch(`http://xxxx/posts/${params.id}`);
    const post = await res.json(); // 外部查询
    return { props: { posts } } // 向页面传递博文数据
}
export default Blog
2、服务端渲染(server-side rendering):别名SSR/动态渲染

服务端在页面被请求时,执行当前页面内导出的异步函数 getServerSideProps 后再进行预渲染

  • 写法类似于 getStaticProps,只是执行时机不同 - 构建时和请求时

四、客户端渲染

如果不需要预渲染,则可以采用客户端渲染 - 可以组合采用「静态生成(预渲染)不需要数据的部分 + 请求时,在客户端 js 请求拿到数据后再渲染」

五、API Routes - 在 Nextjs 中创建后端 API 的方式

  • 原理:Nextjs 的路由系统 API Routes,文件名就是路由路径的一部分
    • 客户端向服务端发起这个路径的请求时,Nextjs 就自动调取这个文件来处理请求
  • 语法:文件中导出一个默认函数,接收两个参数
    • req - 请求对象,包含方法、头部信息、查询参数、请求体等
    • res - 响应对象,可以设置请求状态码、头部信息、响应体等
  • 迭代:采用 src/app 的路由方式后,API Routes 的文件也从 pages/api 转移到 src/app/api
    • 常见:src/app/api/user/route.js 定义api/user/ 相关路由
export default function handler(req, res) {
    res.status(200).json({ msg: 'hello, nextjs' })
}
  • 注意事项:不要在 getStaticProps 和 getStaticPaths 中调用 API Route:以为这两个函数都是在预渲染 - 服务端直接执行的,所以可以直接写服务端代码,例如请求数据库等