在 Next.js 中使用 App 目录

在使用最新版本的 Next.js 创建项目时,系统会提示我们选择使用 app/ 目录还是 pages/ 目录,并且推荐使用 app/ 目录作为创建应用的优选方式。

通过本文的学习,我们将充分了解并掌握 app 目录强大而丰富的功能,利用其最大限度地发挥 Next.js 在 Web 开发方面的潜力。

相较于 pages/ 目录,Next.js 的 app/ 目录提供了更高的灵活性和更丰富的功能。接下来,我们将逐一探讨这些功能:

布局(Layout)

app/ 目录下,利用 布局(Layout) 可以更高效地构建复杂界面,它支持嵌套布局,从而有效避免不必要的重复渲染,并在不同的页面之间保持用户界面的一致性。

我们可以通过在 app/ 目录的根目录下创建一个 layout.jsx 文件来定义一个全局布局组件。此布局组件能够在所有页面中复用,实现一致的用户界面。

向布局组件添加元数据

元数据用于向页面提供额外信息,这些信息不会直接显示在网页的内容区域,但可以被浏览器、搜索引擎或网络爬虫读取和使用。

app/ 目录中,我们可以通过 layout.js 文件向页面添加元数据(这些元数据将被所有页面所共享)。以下是一个示例代码片段,展示了如何从文件中导出元数据:

arduino 复制代码
export const metadata = {
  title: 'Keyword Title',
  description: 'Any Keyword,Another Keyword, More Keywords ',
};

如果需要为不同页面设置特定的元数据,我们可以在目标页面文件中导出一个名为 metadata 的变量,用于覆盖 layout.js 文件中的元数据。

没有 _app.js 文件

如你所见,原先位于 pages/ 目录下的 _app.jsx 文件在 app/ 目录下已经消失,所有基础布局逻辑统一整合至 layout.jsx 文件中。

例如,为了使用 Chakra UI 实现全局样式和组件配置的统一管理,推荐将 Chakra UI 的 Provider 组件放置在 layout.jsx 文件中。下面是 Chakra UI 官方文档中的代码示例,演示了如何在 layout.jsx 文件中引入并配置 Chakra Provider:

javascript 复制代码
// app/providers.tsx
'use client'

import { ChakraProvider } from '@chakra-ui/react'

export function Providers({ children }: { children: React.ReactNode }) {
  return <ChakraProvider>{children}</ChakraProvider>
}
javascript 复制代码
// app/layout.tsx
import { Providers } from './providers'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode,
}) {
  return (
    <html lang='en'>
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  )
}

路由(Routing)

pages/ 目录结构不同,app/ 被设计为严格基于文件夹结构来定义,前者既支持基于文件夹的路由(通过文件夹组织页面),也支持基于文件的路由(路由路径直接映射到文件名)。

app/ 目录中创建路由需要首先创建一个文件夹,该文件夹的名称将直接映射为路由路径的一部分。然后在该文件夹内创建一个 page.js 文件,该文件负责实现路由具体逻辑。

例如,如果我们创建一个名为 about 的文件夹,并在该文件夹中创建一个 page.js 文件,运行开发服务器,访问 localhost:3000/about 将会加载该 page.js 文件中定义的内容。

app/ 目录中的任何位置创建的任何文件夹都将遵循此模式。

嵌套路由(Nested routing )

app/ 目录下,通过在其他文件夹中创建文件夹的方式构建嵌套路由。每个文件夹对应一个路由,其中包含的 page.js 文件用于实现该文件夹的路由逻辑。

例如,对于 /dashboard/analytics 这样的 URL ,其对应的文件夹结构为 app/dashboard/analytics ,在 analytics 文件夹中,应该存在一个 page.js 文件,该文件负责 /dashboard/analytics 路由的显示逻辑和组件渲染,从而使得该路由可以通过 URL 公开访问。

路由组(Route group )

app/ 目录中,文件夹通常映射到 URL 路径中。但是,我们可以将文件夹标记为路由组(Route group),以防止该文件夹包含在 URL 路径中。

这样,我们就可以在不影响 URL 路径的前提下,更好的组织和管理项目文件。

我们可以通过将文件夹名称括在括号中来创建路由组,例如 (name_of_folder) ,这样可以有效地将路由分组到该文件夹下,同时文件夹名称不会出现在路由中。

字体用法

在 Next.js 12 中,要在 pages/ 目录下使用字体,需将字体样式表的链接复制到项目的 CSS 文件中。

但在 Next.js 13 中,我们可以在 app/ 目录下通过使用 import 关键字从 next/font/google 导入所需的字体。

javascript 复制代码
//importing the fonts 
import { Inter } from 'next/font/google';

//initialising a variable 
const inter = Inter({ subsets: ['latin'] });

export default function RootLayout({ children }) {

  return (
    <>
      <html lang="en">
        //Adding the variable as a class to the body tag
        <body className={inter.className}>
            {children}
        </body>
      </html>
    </>
  );
}

网站图标

为 Next.js 项目设置网站图标,需要使用选择图片替换位于项目根目录中的 favicon.ico 文件。请注意,如果图片格式为 JPG、 PNG或 SVG 等其他格式,需要先将其转换为 ICO 格式。

loading.jsx 文件

在 Next.js 中,利用加载组件(loading component)来展示数据加载状态是一种用户友好的做法。这种方式特别适用于需要从 API 获取数据并在数据加载过程中向用户展示加载状态的场景。

我们只需在 app/ 目录下指定文件夹中创建名为 loading.jsx 的文件即可自定义加载组件。

下面是 loading.jsx 文件的一个实现示例:

javascript 复制代码
// app/loading.jsx 
const loadingPage = ()=>{
    return (
        <div className="loader">
            <div id="loader-wrapper">
                <div id="loader">
                <img src="/img/Spinner-1s-120px.gif"/>
                </div>
                <div className="loader-section section-left">
                
                </div>
                <div className="loader-section section-right"></div>
        
    
      </div>
        </div>

    )
}

export default loadingPage

error.jsx 文件

error.jsx 文件是 Next.js 13.4 版本新增的错误处理专用文件,此文件旨在替换传统的 pages/error.jspages/_error.js 文件,以便以更集中的方式处理错误。

此文件一个显著优点是能够统一处理客户端和服务器端的错误。它通过接收 statusCode 属性来确定发生的错误类型,并据此显示相应的错误信息和应用特定的样式,从而提供更加用户友好的错误处理体验。

下面是一个 error.jsx 文件的示例,展示了其可能的代码结构:

javascript 复制代码
// app/error.jsx
function Error({ statusCode }) {
    return (
      <div>
        <h1>Error</h1>
        <p>An error {statusCode} occurred on server</p>
      </div>
    );
}
  
Error.getInitialProps = ({ res, err }) => {
    const statusCode = res ? res.statusCode : err ? err.statusCode :  404;
    return { statusCode };
};
  
export default Error;

在上面的示例中,Error 组件通过 getInitialProps 方法接受 statusCode 属性。此方法首先检查响应对象 (res) 和错误对象 (err) 是否存在。如果 res 存在,则从 res 中获取状态码;如果 err 存在,则尝试从 err 中获取状态码。如果两者都不存在,则默认状态码为 404。然后,这个状态码被用于在错误页面中显示相应的错误消息,为用户提供清晰的反馈。

not-found.jsx 文件

在 Next.js 中,not-found.jsx 是一种特殊页面组件,专门用于处理用户尝试访问应用程序中不存在的路由时的情况。当请求的路由不存在时,该文件被用来渲染一个自定义的"404未找到"页面。

下面是一个 not-found.jsx 文件的示例,展示了其可能的代码结构:

javascript 复制代码
// app/not-found.jsx
import Link from 'next/link';

export default function NotFound() {
  return (
    <div>
      <h2>Not Found</h2>
      <p>The page you were looking for does not exist.</p>
      <Link href="/">Go back home</Link>
    </div>
  );
}

服务器组件

在 Next.js 的 app/ 目录中默认启用服务器组件。这使得我们的组件可以自动实现服务器端渲染,而无需额外配置。

使用服务器组件可以带来多方面的好处:

  • 数据获取: 服务器组件可以直接在服务器上处理数据,如数据库查询、API 调用等,无需通过客户端发送请求。
  • 安全: 服务器组件允许将敏感的业务逻辑保留在服务器端,避免暴露给客户端,从而减少安全风险。
  • 缓存: 服务器组件可以在服务器端实现高效的数据缓存,对于重复请求可以快速响应,减少服务器负载。
  • 减少捆包尺寸: 可以根据需要动态打包服务器组件,从而显著减少发送到客户端的代码量。
  • 搜索引擎优化 服务器组件通过在服务器端执行渲染,能够为搜索引擎爬虫提供完整的内容,有利于提高页面的 SEO 排名。
  • 社交网络可分享性: 当页面内容通过服务器组件预渲染时,社交网络分享可以展示更丰富的预览信息。

服务器端渲染(SSR)与服务器组件的主要区别在于应用场景:服务器端渲染应用于 pages/ 目录,而服务器组件应用于 app/ 目录。

服务器组件巧妙地提供了一种利用服务器端逻辑的方式,从而避免了传统服务器端渲染(SSR)的负担,显著提升了现在 Web 应用程序的性能和可维护性。

尽管服务器端渲染(SSR)与服务器组件均在服务器端执行渲染,但服务器组件不支持与 JavaScript 的交互。因此,服务器组件无法进行事件处理以及使用 React 的状态管理功能(例如 useState、useEffect 和其他 DOM 操作)。

通过将 useClient 指令添加在代码的顶部,可以将默认的服务器组件转换为客户端组件,从而获得对这些功能的使用能力。

结语

Next.js 通过推出新的 app/ 目录结构提供了一系列强大的功能,帮助开发人员提升了开发体验。

通过本文的学习,我相信你将有足够的信心,在 Next.js 开发中利用 app/ 目录构建出功能强大、可扩展且可维护的应用程序。

相关推荐
小曲曲37 分钟前
接口上传视频和oss直传视频到阿里云组件
javascript·阿里云·音视频
学不会•2 小时前
css数据不固定情况下,循环加不同背景颜色
前端·javascript·html
EasyNTS3 小时前
H.264/H.265播放器EasyPlayer.js视频流媒体播放器关于websocket1006的异常断连
javascript·h.265·h.264
活宝小娜4 小时前
vue不刷新浏览器更新页面的方法
前端·javascript·vue.js
程序视点4 小时前
【Vue3新工具】Pinia.js:提升开发效率,更轻量、更高效的状态管理方案!
前端·javascript·vue.js·typescript·vue·ecmascript
coldriversnow4 小时前
在Vue中,vue document.onkeydown 无效
前端·javascript·vue.js
我开心就好o4 小时前
uniapp点左上角返回键, 重复来回跳转的问题 解决方案
前端·javascript·uni-app
刚刚好ā5 小时前
js作用域超全介绍--全局作用域、局部作用、块级作用域
前端·javascript·vue.js·vue
yqcoder7 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
会发光的猪。7 小时前
css使用弹性盒,让每个子元素平均等分父元素的4/1大小
前端·javascript·vue.js