Nextjs App Router 模式新的能力

1,083 阅读9分钟

nextjs 13.4 的发布,宣布 App Router 稳定版本的到来,一起围观下带来了哪些变化!

image-20231004170531857

​ 上图是 next 的下载量,可以看到 遥遥领先 其他框架,vercel 公司的新一代 React 框架,为什么如此好用?下面我们看一下 13.4 版本的新功能吧!

App Router

​ Next.js 13.4 是第一个将新的应用程序目录和应用程序路由器功能从测试版中剔除的版本!这就代表着 App Router 正式成为稳定版,可以用于生产环境,相比较之前的 pages/ 下文件路由,App Router更加的自由,具体优势有:

  • 更灵活的路由规则:使用 "app route" 可以更自由地定义路由,不再仅依赖于文件的相对路径。这样可以更好地组织和管理路由结构,特别是对于复杂的应用程序而言。
  • 更好的代码分离:在 "app route" 中,可以将路由定义和页面逻辑分离到不同的文件或模块中。这样可以提高代码的可读性和可维护性。
  • 更好的代码重用:"app route" 支持模块化的路由定义和组合,使得页面的复用更加便利。您可以将一些共享的路由规则封装成模块,便于在不同的页面或应用中共享和复用。

app route 使 Next 的开发体验变得更好,此外,Next.js 文档站点进行了重大更新,将 App Router 设为默认值,这也许象征着此版本的重要性!您现在可以在新的 App Router 和之前的 Pages Router 之间切换文档。

image-20231005165320746

App 文件下的路由

新应用程序目录中的路由就像添加导出 React 函数组件的 page.tsx 文件一样简单。应用程序的路由由应用程序目录中文件夹的层次结构定义。例如,在 / 路由上创建页面就像在应用程序目录的根目录中添加 page.tsx 文件一样简单

1)新的路由规范

接下来,让我们展示如何使用新的应用程序路由器创建更复杂的应用程序路由:

image-20231007124732252

正如您在上面看到的,我们能够创建一个简单的路由,例如 /about ,以及使用 Next.js 的动态路由创建更复杂的路由,例如 /articles/article/12345

新的路由规范通过为布局、页面、模板等强制使用特殊文件名,解决了之前版本中所有文件都作为路由,无法在pages/ 下声明不作为路由的文件,使开发体验变得更好。

2)获取数据方式更简洁

借助新的 App Router,我们的页面可以使用 React Server 组件,这使我们能够使用熟悉的 async/await 语法来简化数据获取。

// app/page.tsx
export default async function Page() {
  const res = await fetch('https://api.example.com/...');
  const data = res.json();
  return '...';
}

在 12 的时候,我们想要获取数据需要:

// pages/example.js

import React from 'react';

export async function getServerSideProps() {
  // 在此处获取服务端数据
  const response = await fetch('https://api.example.com/data');
  const data = await response.json();
  
  return {
    props: {
      data // 将数据作为 props 返回
    }
  };
}

function Example({ data }) {
  // 在客户端使用获取到的数据进行渲染
  return (
    <div>
      <h1>Server-side rendering example</h1>
      <p>{data}</p>
    </div>
  );
}

export default Example;

相比较更加符合之前的开发习惯!

3)新的概念:服务器组件

在 Next.js 13 中,文件默认是服务器组件。您可以通过在模块顶部包含 'use client' 指令来选择使用客户端组件。如果您还不了解客户端组件 和 服务器组件的区别,强烈推荐文章:理解React服务器组件,这篇文章详细解释了为什么需要引入新的概念:服务器组件,以及客户端组件和服务端组件的边界问题,开发中容易混淆的概念等等,非常值得一看

4)路由段配置

我们的页面还可以导出路由段,使我们能够控制页面的渲染方式。 Next.js 中的一种常见做法是静态生成页面。但是,当我们使用动态参数时,我们遇到了一个问题,Next.js 如何知道要静态生成哪些页面?我们可以利用 generateStaticParams 来解决这个问题。这在做 seo 中非常有用

// app/articles/article/[id]/page.tsx
type ArticleProps = Pick<Article, 'id'>

export default async function Page({ id }: ArticleProps) {
  const article = await(await fetchArticleById(id)).json();
  return <BlogArticle article={article} />
}

export async function generateStaticParams(): ArticleProps[] {
  const articles = await(await fetchArticles()).json();
  return articles.map(article => ({ id: article.id }))
}

在上面的示例中,我们导出一个名为 generateStaticParams 的异步函数,该函数加载我们的所有博客文章并返回一个对象数组,该数组的属性与动态路线段的名称相匹配,在本例中为 id 。 Next.js 将使用它为我们的每篇博客文章静态生成页面。

5)路由段配置

Next.js 13 为我们提供了几个路由段配置选项来控制 Next.js 渲染页面的方式。除了 generateStaticParams 之外,最常用的路线段配置是 revalidate 。当与静态站点生成 (SSG) 结合使用时,重新验证允许您控制页面重新生成的频率。例如我在 page.tsx | route.ts | layout.ts 中,添加如下代码:

export const revalidate = 60

那么我们的当前页面就会每 60 秒重建一次页面,请注意,它比这更微妙,因此请务必阅读 Next.js 文档网站上的 ISR

我们还可以通过使用 dynamicParams 路由段配置来告诉 next.js 不要渲染 generateStaticParams 中未返回的 ID 的页面,

如果我们有一个使用查询参数的页面,我们可能希望在使用动态路由段请求该页面时动态服务器呈现它,那么我们可以根据我们的用例强制页面静态或动态生成

export dynamic = 'force-dynamic'
// or: 'auto' | 'force-dynamic' | 'error' | 'force-static'
6)布局和模版

布局

除了页面之外,Next.js 13 还引入了布局模板的特殊文件。在上面的示例中,您可能已经注意到,我们在文件夹层次结构的各个级别包含了多个 layout.tsx 文件。我们创建了一个根级 layout.tsx,这是 Next.js 13 中的典型做法。

在根布局中,我们可以创建 HTML 文档,向头部添加脚本和其他内容,提供语义结构,并将应用程序包裹在供应器中。我们不再需要使用 Next.js 早期版本中的特殊 <Head><Script> 组件。我们也可以在这里添加元数据

请注意,layout.tsxpage.tsx通常应该是服务器组件,因为我们应该让布局组件在服务器渲染,这样用户可以下载更少的 js,让用户更快看到一些内容。

// app/layout.tsx
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <head>
        <script>//...</script>
      </head>
      <body>
        <main>
           <AppProvider>{children}</AppProvider>
        </main>      
      </body>
    </html>
  );
}

// app/page.tsx
export default function Page() {
  return //...;
}

我们还可以在应用程序目录层次结构的每个级别添加布局文件,以将更具体的布局应用于应用程序的不同部分。例如,假设我们想要围绕我们的博客文章添加一个特定的 AppWrapper。我们可以将新的 layout.tsx 文件添加到 page.tsx 文件旁边的 /app/articles/article/[id] 目录中。

// app/articles/article/[id]/layout.tsx
export default function RootLayout({ children }) {
  return (
    <AppWrapper>{children}</AppWrapper>
  );
}

模版

模版和布局类似,但是区别在于,模版在不同路由之间切换的时候,模版的内容是销毁和重新新建,但是布局是对应路由下 共享这个 DOM 元素,路由切换不会销毁再新建DOM,

更多请看:路由之排版

自动代码分割

Next.js 13.4 让代码分割动态加载内容变得比以往更容易。在 之前版本中,您必须使用 next/dynamic 。现在,整个应用程序可以通过使用 Suspense 选择代码分割和动态加载。事实上,您可以在客户端组件中使用简单的条件进行代码分割。查看 Next.js 博客中的以下示例,该示例根据用户是否登录返回完全不同的包:

// app/layout.tsx
import { getUser } from './auth';
import { Dashboard, Landing } from './components';

export default async function Layout() {
  const isLoggedIn = await getUser();
  return isLoggedIn ? <Dashboard /> : <Landing />;
}

BETA 功能

1)服务器操作

Next.js 13.4 引入了服务器操作(目前处于 alpha 版本),它为您的应用程序带来了更多的灵活性和强大功能。服务器操作允许您直接在应用程序中处理服务器端逻辑,例如获取数据或与 API 交互。此功能不仅简化了您的应用程序架构,还使您能够创建更快、更高效的应用程序。

2)Turbopack

随着 Next.js 13.4 的发布,Turbopack 已进入测试阶段,提供功能更完整、更稳定的体验。 Turbopack 是 Next.js 基于 Rust 的新捆绑器,旨在加速开发中的本地迭代以及很快的生产构建。由于社区在测试和报告错误方面的支持,Turbopack 的采用率不断提高,为未来更快、更高效的开发体验铺平了道路。

3)草稿模式:轻松获取和渲染草稿内容

Next.js 13.4 引入了草稿模式,该功能允许您轻松地从无头 CMS 中获取和渲染草稿内容。与现有的预览模式 API 相比,草稿模式提供了更简化和增强的体验,新应用程序目录不支持现有预览模式 API。

通过草稿模式,您现在可以在发布内容之前无缝预览和迭代内容,确保为用户提供最高质量的输出。

什么是 CMS ?

答:CMS 是 Content Management System(内容管理系统)的缩写。它是一种应用程序或一组相关的应用程序,用于创建、管理、分发、发布和更新内容。CMS 提供了一个集中化的仓库,使得你可以在其中收集,管理和发布信息。

在前端开发的上下文中,CMS 通常会提供 API(如 RESTful 或 GraphQL API),前端应用则通过这些 API 与 CMS 进行交互,获取或修改数据。而 CMS 的内容通常包括了网页的文本、图片、视频等。

有许多常见的 CMS,例如 Wordpress, Drupal, Joomla 等等。近年来,所谓的 "headless CMS" 也变得越来越流行,例如 Contentful, Prismic, Strapi 等。所谓 "headless",是指在 CMS 不再负责内容的呈现,只通过 API 提供内容,因此可以更灵活地与各种前端框架和技术(例如React,Vue,Angular,或者静态网站生成器)结合使用。

总结

个人觉得 Next.js 是一种新的前端开发范式,通过使用 Next.js 13 ,学习到了很多新的概念,同时也觉得使用 Next.js 开发,没有之前流畅,需要学习的还有很多