banner
banner
banner
NEWS LETTER

Next --- React 开发框架

Scroll down

优点:

  • 直观的、 基于页面的路由系统(并支持动态路由
  • 预渲染。支持在页面级的静态生成 (SSG) 和服务器端渲染 (SSR)
  • 自动代码拆分,提升页面加载速度
  • 具有经过优化的预取功能的客户端路由
  • 内置 CSS 和 Sass 的支持,并支持任何CSS-in-JS
  • 开发环境支持快速刷新
  • 利用 Serverless Functions 及 API 路由构建 API 功能
  • 完全可扩展

安装

  • 前提:node 版本需要12.22.0 及更高
  • 创建:npx create-next-app@latest –typescript
  • 运行:npm run dev启动服务器,访问http://localhost:3000
  • 安装:npm install next react react-dom
  • 配置:在package.json文件添加scripts配置
    1
    2
    3
    4
    5
    6
    "scripts": {
    "dev": "next dev", // 开发模式启动
    "build": "next build", // 构建生产环境
    "start": "next start", // 启动生产环境服务器
    "lint": "next lint" // 设置内置ESLint配置
    }

页面(Pages)

  • 在next.js中,page就是React组件,文件存放在pages目录下,每个page都使用其文件名作为路由,通过/文件名访问
    • 支持有动态路由的pages,如文件名为pages/posts/[id].js,通过posts/1访问
  • 预渲染

  • 默认情况下将预渲染每个page,即预先为每个page生成HTML文件
  • 水合:当浏览器加载一个page时,其Javascript代码将运行并使页面完全具有交互性的过程。
  • 两种形式的预渲染:
    • 静态生成(推荐):HTML在构建时生成,并在每次页面请求时重用
    • 服务端渲染:在每次页面请求时重新生成HTML
  • 允许每个页面选择渲染方式,CDN可以在没有额外配置的情况下缓存静态生成的页面提高性能
  • 静态生成 — 生成带有或不带有数据的页面

    • 生成不带有数据的静态页面:不涉及获取外部数据,只需构建时为页面生成HTML文件
    • 生成带有数据的页面:
      • 页面内容取决于外部数据: 使用getStaticProps
      • 页面paths取决于外部数据:使用getStaticPaths + getStaticProps
    • 尽可能使用静态生成如:营销页面,博客文章、简历、产品列表、帮助文档
    • 静态生成不满足使用的解决方案:静态生成+客户端渲染服务端渲染
  • 服务端渲染 — 也被称为SSR或动态渲染

    • 使用:getServerSideProps

数据获取

  • getStaticProps(静态生成):仅在构建时获取数据。
  • getStaticPaths(静态生成):根据数据指定预渲染页面的动态路由。
  • getServerSideProps(服务器端渲染):获取每个请求的数据。
  • getStaticProps

    • 返回一个对象
    • context包含:
      • params: 使用动态路由页面的路由参数
      • preview:是否处于预览模式。true/undefined
      • previewData:setPreviewData设置的预览数据集
      • locale:活动区域设置(前提:启用国际路由)
      • locales:所有支持的区域设置(前提:启用国际路由)
      • defaultLocale:配置的默认区域设置(前提:启用国际路由)
    • props:可选对象,包含页面组件将接受的props
    • revalidate:可选的次数,单位秒,默认false,具体看增量静态生成
    • notFound:可选的布尔值,允许页面返回404和页面
    • redirect:可选的重定向值,允许重定向到内部和外部资源,构建时不允许重定向
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      // js
      export async function getStaticProps(context) {
      return {
      props: {}
      }
      }

      // ts
      import { GetStaticProps } from 'next'
      export const getStaticProps: GetStaticProps = async (context) => {}
  • 增量静态再生(ISR)

    基于每个页面使用静态生成,而无需重新构建整个站点。

    • 使用revalidate:number启用,当对在生成时预呈现的页面发出请求时,它最初将显示缓存的页面。过程如下:
      • 初始请求之后和10秒之前对页面的任何请求也会被缓存并即时缓存
      • number秒窗口之后,下一个请求仍将显示缓存(过时)页面
      • next会在后台触发页面重新生成
      • 生成成功后,next使缓存失效并显示更新的产品页面;失败则页面保持不变
  • 读取文件:process.cwd()

    • 文件可以直接从getStaticProps中的文件系统中读取。即必须获取文件的完整路径
    • next将代码编译到一个单独的目录中
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      import path from 'path'
      export async function getStaticProps() {
      const postsDirectory = path.join(process.cwd(),'posts')
      // 使用 fs.readdir(postsDirectory)来读取这个目录
      const filenames = await fs.readdir(postsDirectory)
      const posts = filenames.map(async (filename) => {
      const filePath = path.join(postsDirectory, filename)
      const fileContents = await fs.readFile(filePath, 'utf8')
      return {
      filename,
      content: fileContents,
      }
      })
      return {
      props: {
      posts: await Promise.all(posts),
      },
      }
      }
  • getStaticPaths

    • 静态预呈现使用动态路由的页面时使用
    • paths键(必选)
      • 如果页面使用可选的捕获所有路由,使用null、[]、undefined或 false来呈现最根路径,如果在page/[[...slug]],使用slug:false,则静态生成页面”/“
    • fallback键(必选)
      • fallback:false:则任何未返回的路径都将导致404,不经常添加新页面可用
      • fallback: true:返回的路径将在构建时由getStaticProps呈现为HTML,在生成时未生成的路径不会生成404,提供回退版本,从用户角度看,页面将从回退页面交换到整个页面。有大量依赖于数据的静态页面可用。
      • fallback:blocking:阻塞原因,每条路径只发生一次。构建时尚未生成的路径不会导致404。相反Next将对第一个请求进行SSR,并返回生成的HTML。完成后,浏览器将接收生成路径的 HTML。Next将此路径添加到预呈现页面的列表中。
    • 回退页面

      • 页面的props将为空。使用router.isFallback可以检测是否正在渲染回退,如果只为true的话
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        // js
        export async function getStaticPaths() {
        return {
        paths: [
        { params: { ... }}
        ],
        fallback: true,false,or 'blocking'
        }
        }
        // ts
        import { GetStaticPaths } from 'next'
        export const getStaticPaths: GetStaticPaths = async () => {}
  • getServerSideProps

    • 仅当需要预呈现其数据必须在请求时提取的页面时,才应使用。getStaticProps到第一个字节的时间(TTFB)将比慢,因为服务器必须计算每个请求的结果,并且如果没有额外的配置,CDN就无法缓存结果。
    • 返回一个对象
    • context包含:
      • params: 使用动态路由页面的路由参数
      • req: http 传入信息对象,以及其它内置的解析助手
      • res: http返回对象
      • query: 查询字符串的对象
      • preview:是否处于预览模式。true/undefined
      • previewData:setPreviewData设置的预览数据集
      • resolvedUrl: 请求URL的规范化版本,去掉客户端转换的前缀并包括原始查询值
      • locale:活动区域设置(前提:启用国际路由)
      • locales:所有支持的区域设置(前提:启用国际路由)
      • defaultLocale:配置的默认区域设置(前提:启用国际路由)
    • props:可选对象,包含页面组件将接受的props
    • notFound:可选的布尔值,允许页面返回404和页面
    • redirect:可选的重定向值,允许重定向到内部和外部资源,构建时不允许重定向
    • 在getServerSideProps中提供req中间件:req
      • req.cookies: 一个包含请求发送的cookie的对象。默认为{}
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        //js
        export async function getServerSideProps(context) {
        return {
        props: {}
        }
        }

        // ts
        import { GetServerSideProps } from 'next'
        export const getServerSideProps: GetServerSideProps = async (context) => {
        // ...
        }
  • 在客户端获取数据

    • 使用场景:如果页面包含频繁更新的数据,并且不需要预呈现数据。用户面板页面。
    • 首先,立即显示没有数据的页面。页面的部分内容可以使用静态生成进行预渲染。您可以显示丢失数据的加载状态。然后,在客户端获取数据,并在准备好后显示。
  • SWR

    • next团队创建的React数据获取挂钩
    • 处理缓存、重新验证、焦点跟踪、间隔重新蚀刻等
      1
      2
      3
      4
      5
      6
      7
      8
      import useSWR from 'swr'
      const fetcher = (url) => fetch(url).then((res) => res.json())
      function Profile() {
      const { data, error } = useSWR('/api/user', fetcher)
      if (error) return <div>failed to load</div>
      if (!data) return <div>loading...</div>
      return <div>hello {data.name}!</div>
      }

内置对 CSS 的支持

  • 允许在js文件import css文件
  • 添加全局样式表

    • 创建一个pages/_app.js文件,然后import css文件
  • node_modules目录import样式

    • 可以在应用程序的任何位置导入
    • 全局样式表还是要在pages/_app.js导入
    • 其它的对应组件页面导入
  • 添加组件级CSS

    • CSS模块支持的文件命名格式:[name].module.css
    • CSS模块时一项可选功能,仅对带有.module.css扩展名的文件启用
  • 对Sass的支持

    • 文件后缀必须为:.module.scss.module.sass
    • 记得安装sass:npm i sass
    • 自定义Sass参数:使用next.config.js文件中的sassOptions属性进行配置
    • Sass变量
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      // xxx.module.scss
      $primary-color: #64FF00
      :export {
      primaryColor: $primary-color
      }
      // pages/_app.js
      import variables from "../xxx.module.scss"
      export default function MyApp({Component, pageProps}) {
      return (
      <Layout color={variables.primaryColor}>
      <Component {...pageProps} />
      </Layout>
      )
      }
  • CSS-in-JS
    • 内联样式:<p style={{ color: 'red' }}>内联</p>
    • 引入styled-jsx以支持作用于隔离的css,支持类似于Web组件的shadow css单不支持服务端渲染且仅支持js

布局

  • 自定义单个共享布局:自己封装想要的布局组件然后应用在全局中

  • 多个布局 | 嵌套布局:自己定义多个布局组件,然后使用getLayout实现,

    • 这种布局支持状态持久性,因为React组件书在页面转换之间保持,这个过程叫协调
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      // pages/index.js
      import Layout from '../component/layout'
      import NestedLayout from '../component/nested-layout'
      // ts引入import type { ReactElement } from 'react'

      export default function Page() {
      return {/*...*/}
      }
      // ts模式给page添加类型ReactElement
      Page.getLayout = function getLayout(page) {
      return (<Layout>
      <NestedLayout>{page}</NestedLayout>
      </Layout>)
      }
      // page/_app.js
      // ts模式下需要定义布局类型
      export default function MyApp({Component, pageProps}) {
      const getLayout = Component.getLayout || (page => page)
      return getLayout(<Component {...pageProps} />)
      }

图片优化

  • Image组件next/image是HTML元素<img/>的扩展
  • 使用图像组件:import Image from ‘next/image’, <Image src={} />

本地图像

  • 要先引入,使用import,next将根据导入的文件自动确定图像的width和height

远程映像:需要提供src、width、height、alt

域名:

  • 访问远程映像单仍使用内置的next Image Optimization API,则src保留为默认设置
    1
    2
    3
    4
    5
    6
    7
    // next.config.js
    module.exports = {
    images: {
    // 这个地址是远程映像的图片的绝对地址
    domains: ['examplae.com', 'example2.com']
    }
    }

优先权:’priority’添加到图像中,成为每个页面的最大内容绘制(LCP)元素

  • LCP 元素通常是页面视口中可见的最大图像或文本块

图像大小调整

  • 自动: 使用静态导入
  • 显式地:通过包含heightwidth
  • 隐式地:通过使用layout=”fill”,使图像展开填充父元素
  • 不知道图像大小的情况下调整

    • 使用layout="fill",使用fill、contain或cover的objectFit属性以及objectPosition属性来定义
    • 规范化图像:自己做的图,自己规范图像大小
    • 修改API调用
    • 如果以上都不适用,则将按照<img />元素的标准在页面上运行

样式

  • 建议对内部<img>设置样式的方法是将Image组件上的className设置为导入的CSS模块的值。className的值将自动应用于基础的<img>元素。
  • 当使用layout=’fill’>时,父元素必须具有position:relative(必要的)
  • 当使用layout=’responsive’时,父元素必须具有display:block(div的默认值,应另行指定)

字体优化

  • 第一内容绘制(FCP)和最大内容绘制(LCP)
  • 使用:import Head from ‘next/head’
  • 要添加web字体,使用<Head></Head>包裹
  • 如果不想要优化,在next.config.js中设置optimizeFonts: false

脚本组件

  • 脚本组件next/script是HTML元素<script>的扩展
  • 使用:import Script from ‘next/script’<Script src="第三方路径" strategy="策略属性" />

strategy:决定何时加载第三方脚本

  • beforeInteractive:在页面交互之前加载
  • afterInteractive:(默认):在页面变成交互式后立即加载
  • lazyOnload:在空闲时间加载
  • beforeInteractive

    • 从服务器注入到初始HTML中,并在执行自绑定JavaScript之前运行。
    • 此策略应用于在页面交互之前需要获取和执行的任何关键脚本
  • afterInteractive

    • 被注入客户端,并将在Next.js对页面进行水合后运行。
    • 这种策略应该用于不需要尽快加载的脚本,并且可以在页面交互后立即获取和执行
    • lazyOnload

      • 在获取所有资源后以及空闲时间内加载较晚。
      • 此策略应用于后台或低优先级脚本,这些脚本不需要在页面交互之前或之后立即加载。

内联脚本

  • 使用:将javascript放在{}中编写 或者在标签上使用dangerouslySetInnerHTML属性,但必须定义id属性
  • 只能策略属性不为beforeInteractive时才能使用

加载后执行代码(onLoad)

  • 策略属性不为lazyOnload,都可以在加载后在标签上使用onLoad属性来执行代码

基本特性

静态文件服务

  • 将静态文件存放到根目录下的public目录中,并对外提供访问。public目录下的存放的静态文件对外访问路径yi/为起始路径,如”/xxx.png”
  • 要确保pages/下的文件于静态文件无重名

快速刷新

  • 尝试在两次编辑之间保留零部件的状态。只要不更改参数或Hook调用的顺序,useState和useRef就会保留以前的值。
  • 具有依赖关系的钩子将始终在快速刷新期间更新。在进行快速刷新时,依赖项列表将被忽略。
  • 即使是空依赖项数组的useEffect,在快速刷新期间仍会重新运行一次。

ESLint

  • 安装:npm run lint
  • 然后配置

路由 next version 13+

基础篇

  • App 路由
    • app目录和pages目录一起工作,也兼容pages页面的路由,但主要在app页面的路由
    • App Router的优先级高于Pages Router。
    • 默认情况下, app内的组件是React服务器组件。性能优化之一
  • 路由片段
    • 路径的每个文件夹代表一个路由片段。每个路线段都映射到网址路径中相应的片段。
  • 嵌套路由: 就是文件夹相互嵌套
  • 主机托管
    • app目录中可以放自己的文件和特殊文件等,因为只有page.js或route.js返回的内容是可公开寻址的
    • 特殊文件:.js、.jsx、.tsx文件扩展名可用于特殊文件
    • 私有文件:文件夹名:_folderName,表示该目录下的文件退出路由
  • 高级路由模式
    • 并行路由:允许在同一视图中显示两个会多个可以独立导航的页面
    • 拦截路由:允许拦截一条路线并将其显示在另一条路线的上下文中。
    • 布局更React差不多,template.js文件用来定义模板,layout.js用来定义布局, 嵌套要使用到children
  • 修改<head>
    • 通过到处layout.js或page.js文件中的metadata对象或generateMetadata功能来定义元数据

链接和导航

  • 导航的两种方式:
    • 使用<Link href="">组件, Link来自"next/link", 动态可以使用模板字符串语法
      • 相当于vue的声明式导航
      • usePathname:检查链接是否处于活动状态,用于className判断
      • 滚动到id:在url链接添加#id
      • 禁用滚动恢复:添加属性scroll={false},默认滚动
    • 使用useRouter 钩子
      • 相当于vue的编程式导航,
        1
        2
        3
        import { useRouter, usePathname } from "next/navigation"
        const router = useRouter()
        router.push('/dashboard', { scroll: false })
  • 工作原理
    • 预请求: 用户访问路由之前在后台预加载路由的方法
      • <Link>组件:自动预取。静态prefetch默认为true,动态prefetch默认自动,只有共享布局向下直到为30s,预取并缓存第一个loading.js文件。可以显示即时加载状态。
      • router.prefetch(): useRouter钩子编程式预取路由
      • 预取在开发中不启用,仅在生产中启用
    • 缓存:Next有一个内存中客户端缓存,称为路由缓存。 当用户在app中导航时,prefetched路线段和访问过的路线的React Server组件有效负载将存储在缓存中。
    • 部分渲染:仅在客户端上重新渲染导航时发生变化的路线段,并且保留所有共享段。就是在同一文件夹下的不同文件不同路径,切换只渲染对应文件而不影响整体的文件
    • 软导航:仅渲染已更改的片段,同时保留 React 和浏览器状态,并且不会重新加载整个页面。默认,浏览器执行硬导航
    • 后退和前进导航
      • 默认,将保持向后和向前导航的滚动位置,并重用路由缓存中的路线段。

动态路由

  • 在文件名称括上方括号([folderName])
  • 动态端作为params属性将传递给layout、page、route和generateMetadata函数
  • 生成静态参数
    • generateStaticParams在构建时预动态路线段至静态生成路由结合起来
    • 优点:智能检索数据
  • 捕获所有片段: 通过在方括号使用[…folderName]
  • 可选的包罗万象的段:[[…folderName]],
    • 与捕获所有片段的区别:如果带可选参数,则不带参数的路由也会被匹配

加载 UI 和流式传输

  • 即时加载状态(后备UI)
    • 在导航时立即显示
    • 在文件加中创建loading.js,并嵌套在统一文件夹中的layout.js内。会自动将page.js文件和下面的所有子文件封装在<Suspense>边界中。
    • 即使使用 以服务器为中心的路由,导航也是即时的。
  • 使用 Suspense 的流式: 自己看文档

错误处理error.js 文件

  • 自动创建 React 误差边界、wraps 嵌套子段或 page.js 组件。
  • 从 error.js 文件导出的 React 组件用作 fallback 组件。
  • 如果在错误边界内抛出错误,则错误为 contained,回退组件为 rendered。
  • 当回退错误组件处于活动状态时,布局 above 错误边界 maintain 其状态和 remain 交互,并且错误组件可以显示从错误中恢复的功能。
  • 从错误中恢复
    • 重试
    • 使用reset()函数
  • 处理布局中的错误
    • error.js边界不捕获同一段的layout.js或template.js组件中抛出的错误
    • 处理特定布局或模板的错误:将error.js文件放置在布局的父段
    • 处理根布局或模板的错误:使用global-error.js
  • 处理根布局中的错误
    • 根app/error.js边界不捕获根app/layout.js或app/template.js组件中抛出的错误
    • 处理: 使用文娱根app目录中的global-error.js
    • global-error.js错误边界封装entire应用,并且其后被组件在活动时替换根布局
    • 即使定义了global-error.js,仍建议定义一个根error.js其后背组件将渲染within根布局

并行路由

  • 允许同时或有条件地在同一布局中渲染一个或多个页面。允许根据条件渲染插槽
  • 插槽:使用slots创建并行路由,按照@folder约定定义的,并作为props传递到同一级别的布局
  • children属性是一个隐式插槽,不需要映射到文件夹。即app/page.js === app/@children/page.js
  • 未匹配的路由 default.js
    • 默认情况下槽内渲染的内容将于当前URL匹配
    • 在插槽文件夹下在新建default.js作为后备渲染
  • useSelectedLayoutSegment(s)
    • 都接收 parallelRoutesKey,它允许你读取该槽内的活动航路段。
    • 当用户导航到 URL 栏中的 @auth/login 或 /login 时,loginSegments 将等于字符串 “login”

拦截路由

  • 允许从当前布局内应用的其他部分加载路由。
  • 使用(...)来定义,在文件夹的名称哪里添加,类似于相对路径../,约定基于路由段
    • (.): 匹配同一水平上的段
    • (..): 匹配高一级的段
    • (..)(..): 匹配上面两级的段
    • (...): 匹配root app目录中的段

路由处理程序

  • 使用 Web 请求 和 响应 API 为给定路由创建自定义请求处理程序
  • 仅在 app 目录中可用,相当于 pages 目录中的 API 路由,
    在app目录内的route.js|ts文件中定义
    1
    2
    export const dynamic = "force-dynamic"
    export async function GET(request: Request){}
  • 支持的HTTP方法:GET、POST、PUT、PATCH、DELETE、HEAD 和 OPTIONS
  • 扩展API:NextRequestNextResponse
  • 行为
    • 缓存
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      export async function GET() {
      const {searchParams} = new URL(request.url)// 将Request对象与GET方法一起使用时存在
      const id = searchParams.get('id') // 将Request对象与GET方法一起使用时存在
      const res = await fetch(`https://data.mogodb.api.com/product/${id}` {
      methods: 'POST' // post方法的情况存在
      headers: {
      'Content-Type': 'application/json',
      'API-Key': process.env.DATA_API_KEY
      },
      body: JSON.stringify({ time: new Data().toISOString() }) // post方法的情况存在
      })
      const data = await res.json(
      return Response.json({data})
      )
      }
  • 选择退出缓存
    • 将Request对象与GET方法一起使用
    • 使用任何其它HTTP方法
    • 像使用cookies和headers一样使用动态函数
    • 片段配置选项手动指定动态模式

中间件

  • 在缓存内容和路由匹配之前运行
  • 使用项目根目录中的文件middleware.ts|js来定义中间件

数据获取

数据获取、缓存和重新验证

  • 四种方式获取数据
    • 在服务器上,使用fetch
    • 在服务器上,带有第三方库
    • 在客户端上,通过路由处理程序
    • 在客户端,使用第三方库
  • 在服务器上,使用fetch
    • 可以在服务器组件、路由处理程序 和 服务器操作 中将 fetch 与 async/await 一起使用
    • 在路由处理程序中,fetch 请求不会被记忆,因为路由处理程序不是 React 组件树的一部分。
  • 缓存数据
    • 默认情况下, 会自动将fetch的返回值缓存到服务器上的数据缓存
    • 数据缓存是持久的HTTP缓存。根据你的平台,缓存可以自动扩展并达到跨多个区域共享
  • 重新验证数据
    • 是清除数据缓存并重新获取最新数据的过程。当数据变化时要确保显示最新数据时非常有用
    • 两种方式:
      • 基于时间的重新验证:定时更新。用于不经常更改且不重要的数据
        • 使用fetch的next.revalidate选项来设置资源的缓存生命周期
        • fetch("heeps://...",{ next: { revalidate: 3600}})
      • 按需重新验证:根据时间手动重新验证数据。
    • 数据可以通过路径(revalidatePath)或通过服务器动作或路由处理程序内的缓存标签 (revalidateTag)按需重新验证
    • next 有一个缓存标记系统,用于使跨路由的fetch请求无效
      • 使用fetch时,可以选择使用一个或多个标签来标记缓存条目
        • fetch(‘https://…’, {next: {tags: [‘collection’]}})
      • 然后,调用revalidateTag来重新验证与改标签关联的条目
        1
        2
        import { revalidateTag } from 'next/cache'
        export default async function action() { revalidateTag('collection')}
  • 选择退出数据缓存
    • 满足以下条件,则 fetch 请求将被缓存 not
    • cache: ‘no-store’ 添加到 fetch 请求中。个人
    • revalidate: 0 选项添加到各个 fetch 请求中。
    • fetch 请求位于使用 POST 方法的路由处理程序内部。
    • fetch 请求在使用 headers 或 cookies 之后出现。
    • 使用 const dynamic = ‘force-dynamic’ 航路段选项。
    • fetchCache 路由段选项默认配置为跳过缓存。
    • fetch 请求使用 Authorization 或 Cookie 标头,并且组件树中其上方有一个未缓存的请求。

数据获取模式

  1. 在服务器上获取数据
  2. 在需要的地方获取数据: 在在数据组件使用fetch或react cache。因为fetch会自动记忆
  3. 流式(Streaming)和 悬念(Suspense) :逐步渲染UI并将其增量流式传输到客户端
  4. 并行和顺序数据获取
    • 使用顺序数据获取,路由中的请求相互依赖,因此会创建瀑布。当因为一次提取取决于另一次提取的结果,或者希望在下一次提取之前满足某个条件以节省资源的情况使用。类似于react从布局中单独拎其中一个布局渲染完在回到原布局。
    • 使用并行数据获取,路由中的请求会立即发起,同时加载数据。就是两个函数同时请求完然后布局在调用
  5. 预加载数据
    • 创建preload函数。不必将Promise作为props传递下去。preload函数是一种模式,名字可自定义
      1
      2
      3
      export const preload= (id: string) => {
      void getItem(id) // 预加载的函数API
      }
    • 然后在正常请求这个API(getItem),最后页面函数直接调用preload即可
  6. 使用 React cache、server-only 和预加载模式
    • 通过这种方法,可以与获取数据,缓存响应,并保证此数据获取只发生在服务器上
      1
      2
      3
      4
      5
      import { cache } from 'react'
      import 'server-only'

      export const preload = (id: string) => { void getItem(id) }
      export const getItem = cache(async(id: string) => {})

形式和突变

  • 仅服务器表单
    • 在函数顶部使用”use server”
  • 重新验证数据
    • 使用revalidatePath(‘/‘)使整个路线段失效或使用revalidateTag()使带有缓存标记的特定数据失效
  • 重定向
    • 使用redirect(url)
  • 表单验证
    • 使用required和type=”email”等HTML验证进行基本表单验证
  • 显示加载状态
    • 当表单在服务器上提交时,使用useFormStatus()显示加载状态,只能用作服务器操作的form元素的子元素
  • 错误处理
    • 请求时一起返回
  • 乐观的更新
    • 使用useOptimistic(messages,(state,newMessage) => […state, {message:newMessage}])在服务器操作完成之前乐观地更新 UI
  • 设置cookie
    • cookies().set(key,val)
  • 读取cookie
    • cookies().get(key)?.value
  • 删除cookie
    • cookies().delete(key)

渲染

服务器组件

  • 三种不同的服务器渲染策略
    • 静态渲染
    • 动态渲染
    • 流式
  • 优点
    • 数据获取:减少渲染所用时间及客户端发出的请求量
    • 安全
    • 缓存:可以重用
    • 打包尺寸:对网速慢或设备差的用户有益
    • 初始页面加载和首次内容绘制FCP:可以生成用户立即查看的页面
    • 搜索引擎优化和社交网络共享性
    • 流式:渲染分多块,按块渲染

服务器组件是如何渲染的?

  • 渲染工作被分成几个块:按个别路线段悬念边界,每个块都分两步渲染:
  • React将服务器组件渲染为一种称为React服务器组件有效负载(RSC 有效负载)的特殊数据格式。
  • Next.js 使用 RSC 有效负载和客户端组件 JavaScript 指令在服务器上呈现 HTML。
  • 然后,在客户端:
    • HTML用于立即显示路线的快速非交互式预览
    • React服务器组件有效负载用于协调客户端和服务器组件树,并更新DOM
    • JavaScript指令用于hydrate客户端组件并使应用具有交互性
  • 静态渲染(默认)
    • 路线在构建时间渲染或在数据重新验证之后在后台验证。结果被缓存并可以推送到内容分发网络CDN
    • 适用:已知内容
  • 动态渲染
    • 在请求时间处为每个用户渲染路线
    • 适用:个性化数据和仅在请求时才能直到的信息

客户端组件

  • 在请求时在客户端上渲染交互式UI
  • 优点:
    • 互动性: 客户端组件可以适用状态、效果和事件监听器,意味着可以向用户踢狗即时反馈并更新UI
    • 浏览器API:客户端组件可以访问浏览器API
  • 使用: 在文件顶部添加"use client",声明服务器和客户端组件模块之间的boundary
  • 客户端组件时如何渲染的?
    • 整页加载
      • 在服务器上:
        1. React 将服务器组件渲染为一种称为 React 服务器组件有效负载(RSC 有效负载) 的特殊数据格式,其中包括对客户端组件的引用。
        2. Next.js 使用 RSC 有效负载和客户端组件 JavaScript 指令在服务器上呈现路由的 HTML。
      • 然后,在客户端:
        1. HTML 用于立即显示路线的快速非交互式初始预览。
        2. React 服务器组件有效负载用于协调客户端和服务器组件树,并更新 DOM。
        3. JavaScript 指令用于 hydrate 客户端组件并使其 UI 具有交互性。
    • 后续导航
      • 在后续导航中,客户端组件完全在客户端上渲染,而不需要服务器渲染的 HTML。
  • 这意味着客户端组件 JavaScript 包已下载并解析。 一旦包准备好,React 将使用 RSC Payload 来协调客户端和服务器组件树,并更新 DOM。

服务器和客户端组合模式

  • 服务器组件模式
    • 组件之间共享数据
    • 将仅服务器代码排除在客户端环境之外
    • 使用第三方软件包和提供商
  • 客户端组件
    • 将客户端组件移至树下
    • 将属性从服务器传递到客户端组件(序列化)
  • 交错服务器和客户端组件
    • 不支持的模式:将服务器组件导入客户端组件
    • 支持的模式:将服务器组件作为 Props 传递给客户端组件
      • 使用 React children 属性在客户端组件中创建 “slot”。

Edge 和 Node.js 运行时

  • Node.js 运行时(默认)可以访问生态系统中的所有 Node.js API 和兼容包。
  • Edge 运行时 是基于 网络 API 的。
其他文章
cover
Vite --- 新一代前端构建工具
  • 24/11/01
  • 16:52
  • 前端工程化工具
cover
Mobx库
  • 24/11/01
  • 16:52
  • 前端工程化工具
目录导航 置顶
  1. 1. 优点:
  2. 2. 安装
  3. 3. 页面(Pages)
    1. 3.1. 预渲染
    2. 3.2. 静态生成 — 生成带有或不带有数据的页面
    3. 3.3. 服务端渲染 — 也被称为SSR或动态渲染
  4. 4. 数据获取
    1. 4.1. getStaticProps
    2. 4.2. 增量静态再生(ISR) – 基于每个页面使用静态生成,而无需重新构建整个站点。
    3. 4.3. 读取文件:process.cwd()
    4. 4.4. getStaticPaths
    5. 4.5. getServerSideProps
    6. 4.6. 在客户端获取数据
    7. 4.7. SWR
  5. 5. 内置对 CSS 的支持
    1. 5.1. 添加全局样式表
    2. 5.2. 从node_modules目录import样式
    3. 5.3. 添加组件级CSS
    4. 5.4. 对Sass的支持
  6. 6. 布局
    1. 6.1. 自定义单个共享布局:自己封装想要的布局组件然后应用在全局中
    2. 6.2. 多个布局 | 嵌套布局:自己定义多个布局组件,然后使用getLayout实现,
  7. 7. 图片优化
    1. 7.1. 本地图像
    2. 7.2. 远程映像:需要提供src、width、height、alt
    3. 7.3. 域名:
    4. 7.4. 优先权:’priority’添加到图像中,成为每个页面的最大内容绘制(LCP)元素
    5. 7.5. 图像大小调整
    6. 7.6. 不知道图像大小的情况下调整
    7. 7.7. 样式
  8. 8. 字体优化
  9. 9. 脚本组件
    1. 9.1. strategy:决定何时加载第三方脚本
    2. 9.2. beforeInteractive
    3. 9.3. afterInteractive
    4. 9.4. lazyOnload
    5. 9.5. 内联脚本
    6. 9.6. 加载后执行代码(onLoad)
  10. 10. 基本特性
    1. 10.1. 静态文件服务
    2. 10.2. 快速刷新
    3. 10.3. ESLint
  11. 11. 路由 next version 13+
    1. 11.1. 基础篇
    2. 11.2. 链接和导航
    3. 11.3. 动态路由
    4. 11.4. 加载 UI 和流式传输
    5. 11.5. 错误处理error.js 文件
    6. 11.6. 并行路由
    7. 11.7. 拦截路由
    8. 11.8. 路由处理程序
    9. 11.9. 中间件
  12. 12. 数据获取
    1. 12.1. 数据获取、缓存和重新验证
    2. 12.2. 数据获取模式
    3. 12.3. 形式和突变
  13. 13. 渲染
    1. 13.1. 服务器组件
    2. 13.2. 服务器组件是如何渲染的?
    3. 13.3. 客户端组件
    4. 13.4. 服务器和客户端组合模式
    5. 13.5. Edge 和 Node.js 运行时
请输入关键词进行搜索