首页 > 其他分享 >Next.js - App Router Vs. Pages Router 详细对比

Next.js - App Router Vs. Pages Router 详细对比

时间:2023-08-10 18:38:33浏览次数:50  
标签:App 应用程序 js 组件 Router 路由器 页面

多年来,我们将页面放置在 Next 的“pages”目录中。
现在这种情况即将改变。

不久前,Next.js 推出了新的 App Router,显着改变了我们创建页面的方式。 但不仅是我们存储应用程序页面的目录发生了变化,而且可用的功能也发生了变化。

我们的下一个项目过去是这样的:

└── pages
    ├── about.js
    ├── index.js
    └── team.js

使用 App Router,我们的应用程序的结构看起来类似于:

src/
└── app
    ├── about
    │   └── page.js
    ├── globals.css
    ├── layout.js
    ├── login
    │   └── page.js
    ├── page.js 
    └── team
        └── route.js

创建应用程序的约定如下:

  • 应用中的每个页面都有自己的目录。目录名称定义 URL 路径。
  • 浏览器中访问路径时渲染的组件是 page.js。
  • 我们可以将其他组件存储在路径的目录中。 如果它们没有命名为 page.js,则不会影响路由。
  • 每个页面的目录中可以放置几个具有保留名称的文件。 它们都具有特定的功能。 例如,有loading.js、template.js 和layout.js——我们稍后将讨论后者。

到目前为止,一切都很好; 我们已经介绍了这些约定。
正如您所知,现有应用程序需要进行轻微的重构。 但这样做的动机是什么? 以下是 App Router 中可用的新功能。

App Router 功能介绍

Vercel 最近宣布了一些很棒的功能。 其中大多数是 App Router 独有的 - 它们不能在经典的 Pages Router 中使用。
以下是我们现在可以做的令人兴奋的事情的列表。

客户端和服务器组件 (Client and server components)

默认情况下,应用程序目录中的任何组件现在都是服务器组件。 但是,这是什么意思? 下面是一个小回顾。

服务器组件在服务器上呈现。 他们的所有代码都保留在服务器上 - 这意味着我们无法使用客户端功能,例如窗口对象或 React 中的典型钩子。 服务器组件缺乏与客户端的交互性。 当仅仅定义一个钩子时,它们甚至会失败:

客户端组件与我们在 Next.js 中使用的先前类型的组件相反且相似。 他们可以使用浏览器、提供交互性并将其 JS 代码发送到客户端。
虽然 App Router 中的所有组件默认都是服务器组件,但可以通过在文件顶部声明“使用客户端”来声明客户端组件。
这种区别仅适用于新的应用程序路由器。 以下是一个快速概述:

客户端组件:

  • 浏览器API
  • 事件监听器
  • 所有 React 钩子
  • 非常适合在客户端生成一堆 HTML

服务器组件:

  • 非常适合隐藏代码和秘密
  • 不要传送大部分依赖项
  • 直接访问后台
  • 完全集成服务器操作

布局更简单(Easier layouting)

我已经提到了layout.js 文件,它可以位于每个路径的目录中。 该组件使布局变得简单,因为路径组件会自动应用于提供的布局。 让我们看一个例子。

在我们选择的路径目录中,我们创建一个 layout.js:

// layout.js

export default function LoginLayout({ children }) {
  return <div className='login-area'>{children}</div>
}

它所需要做的就是渲染一个自动传递的子组件 - 该子组件是 page.js 组件。
page.js 完全取决于我们。 由于布局是自动应用的,因此我们不需要在此文件中指定引用任何内容。

嵌套布局(Nested layouts)

新的布局文件还有更多内容。 布局组件可以应用于多个页面。 如果子目录没有单独指定布局,则使用顶级布局。
这是一个例子:

src/
└── app
    ├── market
    │   ├── buy
    │   │   └── page.js
    │   ├── sell
    │   │   └── page.js
    │   ├── layout.js

页面“/buy”和“/sell”具有相同的布局。

服务器动作(Server actions)

目前,服务器操作仍然是一个实验性功能。
它们可以根据客户端上的事件轻松执行服务器端代码:

export default function Home() {
 async function serverAction() {
  'use server'
  console.log('server action executed')
 }

 return (
  <form action={serverAction}>
   <button type="submit">
    Call server action
   </button>
  </form>
 )
}

按下按钮,serverAction 函数就会被执行。
这时,需要在config中启用服务器操作。

const nextConfig = {
 experimental: {
  serverActions: true,
 },
}

拦截路由(Intercepting routes)

拦截路由顾名思义:拦截路由请求。 此功能使我们能够构建根据其他一些因素表现不同的页面。
Vercel 自己实现了一个令人兴奋的示例:https://nextgram.vercel.app/
当您单击图库中的图像时,它会作为模式打开 - 而且路径也会发生变化,从而寻址到确切的图像。

如果刷新页面,它将呈现为独立页面。 然而,道路并没有改变。 由于路由被拦截,我们对同一路径收到不同的行为:

并行路由(Parallel routing)

平行路线与拦截路线结合使用时最为有效。 并行路由功能本身听起来并不太令人兴奋:

并行路由允许您同时或有条件地在同一布局中渲染一个或多个页面

  • 官方文档

该功能非常适合组合两个或多个可以独立查看的页面。 这些页面仍然是独立的 - 因此,即使在同一 URL 上呈现,它们也具有单独的代码。

页面路由器(Pages Router)

页面与应用程序路由器并不是一场平等的争论。 相反,应用程序路由器是下一步,并且应该成为构建应用程序的标准方式。
一些受人喜爱的功能与 Pages Router 绑定在一起,因此不会占上风:

  • getStaticProps
  • getServerSideProps
  • getStaticPaths
  • Custom document component(自定义文档组件)
  • Custom app component(自定义应用程序组件)
  • next/head

好消息是这两条路线可以同时使用。 Vercel 甚至建议在迁移时保留页面路由器,以免破坏任何内容。
我们的自定义文档和应用程序组件可以替换为根布局。
以 SEO 为中心的 next/head 组件是完全多余的。 新的应用程序路由器提供了对元数据的内置支持,如下所示:

import { Metadata } from 'next'
 
export const metadata: Metadata = {
  title: 'Hello World',
}
 
export default function Page() {
  return <></>
}

函数 getStaticPropsgetServerSidePropsgetStaticPaths 可以被新的服务器动作(Server Actions)替换。

性能(Performance)

当谈到页面与应用程序路由器的性能之争时,我们看到了一些有趣的事情。 应用程序路由器的性能较差。
为了进行简单的基准测试,我创建了两个执行相同操作的项目:渲染由 URL 传递的许多 HTML 标签。
结果如下:

特别是对于 100 个和 1000 个呈现的标签,百分比差异相当大。 令人着迷的是,随着标签的增多,两种表现似乎变得更加接近。
该基准测试的灵感来自 Jack Herrington,我建议您查看他的深入性能视频。
https://youtu.be/3Q2q2gs0nAI

总结(Summary)

久而久之,我们就要和新路由器交朋友了。
虽然从页面过渡到新方法需要一些工作,但新功能是值得的。 然而,如果您对其功能感到满意,现有的路由器可能仍然是新项目的解决方案。
对于潜在的弃用,我并没有压力。 对页面路由器的支持可能始终存在,因为 Next.js 已经为这两个模型提供了两份单独的文档。 然而,新功能可能会成为应用程序路由器独有的。

感谢您的阅读!
有关新 App Router 及其功能的更多信息:
https://louispetrik.medium.com/what-to-watch-out-for-when-using-nexts-new-server-actions-ffae2262b12a

ref:
https://javascript.plainenglish.io/next-jss-new-app-vs-pages-router-a-detailed-comparison-46f846963af5

标签:App,应用程序,js,组件,Router,路由器,页面
From: https://www.cnblogs.com/eddyz/p/17621208.html

相关文章

  • Ubuntu 22.04安装Node.JS和NPM
    sudoaptpurgenodejssudoaptautoremovesudoaptupdatesudoaptinstall-ycurlcurl-fsSLhttps://deb.nodesource.com/setup_18.x|sudo-Ebash-sudoaptinstallnodejsbuild-essential-y......
  • 借助Aspose.Html 将 HTML 模板与 XML 或 JSON 合并
    在现代网络开发中,内容和表示的分离是一个基本原则。HTML模板提供了一种定义网页结构和布局的便捷方法,而JSON和XML数据格式通常用于存储和传输结构化信息。结合这些技术,开发人员可以根据外部源的数据动态生成HTML内容。在这篇博文中,我们将探讨如何在Java中将HTML模板与JS......
  • reactnative ignite App + wordpress後台CMS 詳細案例
    1.0入門篇WordPress-Plugin-Boilerplate-Tutorial更为简洁的架构方案ReactNativeElements开发环境&生成项目&虚拟机调试&本地生成APK档&虚拟机运行APK档 2.0Ignite框架 Ignite是reactnative里最最齊全的軍火庫。https://github.com/infinitered/ignite 3......
  • java中table遍历td js遍历table中的tr
    一、获取每一个tr1、通过table的id获取id="tables"获取第一行tr,索引从0开始,用eq(),方法里面的索引可以手动更换,如第二行就是1,也可以循环tr,eq里面就是循环变量$("#tablestr").eq(0);//遍历每一行for(vari=0;i<$("#tablestr").length;i++){ $("#tablestr").eq(i);......
  • 8.利用Filebeat收集Nginx的Json格式访问日志和错误日志到Elasticsearch
    生产环境中经常需要获取Web访问用户的信息,比如:网站的PV,UV,状态码,用户来自哪个地区,访问时间等可以通过收集的Nginx的访问日志实现默认Nginx的每一次访问生成的访问日志是一行文本,ES没办法直接提取有效信息,不利于后续针对特定信息的分析可以将Nginx访问日志转换为JSON......
  • springboot~alibaba.fastjson2序列化时过滤字段
    当我们使用阿里的alibaba.fastjson2进行json序列化时,你可以通过方法参数PropertyFilter来实现对字段的获取,将需要序列化的字段写到PropertyFilter对象里,当然也可以将不进行序列化的写到这里,进行逻辑非操作即可实体classPerson{privateStringfirstName;privateStr......
  • 虚拟试衣间app开发
      虚拟试衣间app开发功能  随着科技的不断发展,虚拟试衣间app已经成为了越来越多人购物的选择。通过这些应用程序,用户可以在家中或任何地方轻松试穿衣服,而无需走出家门。虚拟试衣间app的开发可以帮助商家提高客户满意度,并为他们提供更多的销售机会。  虚拟试衣间app的......
  • 微信的 h5 支付和 jsapi 支付
    目录......
  • sqlite3 db "delete from apps where title='Typora';"&&killall Dock
    command+shift+G进入访达前往->输入/private/var/folders 搜索:com.apple.dock.launchpad  仔细看了下执行的命令就发现了sqlite3db这个东西,可以深入了解下  ......
  • [学习笔记] JS验证API相关知识
    checkValidity()会检查元素是否有任何输入约束条件,并且检查值是否符合约束条件。 如下所示,Input元素下限为4上限为20:···<inputid="password"type="number"min="4"max="20">···<script>functionmyFunction(){varx=document.getElementById(&quo......