nextjs学习2:app router

本文是基于 nextjs v14 版本进行展示。

最快捷的创建 Next.js 项目的方式是使用 create-next-app脚手架,你只需要运行:

js 复制代码
npx create-next-app@14

推荐使用 tailwindcss ,这也是 Next.js 推荐的 CSS 方案,很多 example 都会用它。

运行项目

查看项目根目录 package.json 文件的代码:

js 复制代码
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  }

开发的时候使用 npm run dev。部署的时候先使用 npm run build 构建生产代码,再执行 npm run start 运行生产项目。运行 npm run lint 则会执行 ESLint 语法检查。

next build

执行 next build 将会创建项目的生产优化版本:

从上图可以看出,构建时会输出每条路由的信息,比如 Size 和 First Load JS。注意这些值指的都是 gzip 压缩后的大小。其中 First Load JS 会用绿色、黄色、红色表示,绿色表示高性能,黄色或红色表示需要优化。

这里要解释一下 Size 和 First Load JS 的含义。

正常我们开发的 Next.js 项目,其页面表现类似于单页应用,即路由跳转(我们称之为"导航")的时候,页面不会刷新,而会加载目标路由所需的资源然后展示,所以:

js 复制代码
加载目标路由一共所需的 JS 大小 = 每个路由都需要依赖的 JS 大小(shared by all) + 目标路由单独依赖的 JS 大小

其中:

  • 加载目标路由一共所需的 JS 大小就是 First Load JS
  • 目标路由单独依赖的 JS 大小就是 Size
  • 每个路由都需要依赖的 JS 大小就是图中单独列出来的 First load JS shared by all

以上图中的 / 路由地址为例,87.6 kB(First Load JS)= 533 B(Size) + 87.1 kB(First load JS shared by all)

next start

生产模式下,使用 next start运行程序。不过要先执行 next build构建出生产代码。运行的时候,跟开发模式相同,程序默认开启在 http://localhost:3000。如果你想更改端口号:

js 复制代码
npx next start -p 4000

app Router

app router 的目录结构类似于:

js 复制代码
src/
└── app
    ├── page.js 
    ├── layout.js
    ├── template.js
    ├── loading.js
    ├── error.js
    └── not-found.js
    ├── about
    │   └── page.js
    └── more
        └── page.js

定义路由(Routes)

首先是定义路由,文件夹被用来定义路由。

每个文件夹都代表一个对应到 URL 片段的路由片段。创建嵌套的路由,只需要创建嵌套的文件夹。举个例子,下图的 app/dashboard/settings目录对应的路由地址就是 /dashboard/settings

定义页面(Pages)

那如何保证这个路由可以被访问呢?你需要创建一个特殊的名为 page.js 的文件。至于为什么叫 page.js呢?除了 page 有"页面"这个含义之外,你可以理解为这是一种约定或者规范。

  • app/page.js 对应路由 /
  • app/dashboard/page.js 对应路由 /dashboard
  • app/dashboard/settings/page.js 对应路由/dashboard/settings
  • analytics 目录下因为没有 page.js 文件,所以没有对应的路由。这个文件可以被用于存放组件、样式表、图片或者其他文件。

page.js 的代码该如何写呢?最常见的是展示 UI,比如:

js 复制代码
// app/page.js
export default function Page() {
  return <h1>Hello, Next.js!</h1>
}

定义布局(Layouts)

布局是指多个页面共享的 UI。

在导航的时候,布局会保留状态、保持可交互性并且不会重新渲染,比如用来实现后台管理系统的侧边导航栏。

定义一个布局,你需要新建一个名为 layout.js的文件,该文件默认导出一个 React 组件,该组件应接收一个 children prop,chidren 表示子布局(如果有的话)或者子页面。

举个例子,我们新建目录和文件如下图所示:

相关代码如下:

js 复制代码
// app/dashboard/layout.js
export default function DashboardLayout({
  children,
}) {
  return (
    <section>
      <nav>nav</nav>
      {children}
    </section>
  )
}

// app/dashboard/page.js
export default function Page() {
  return <h1>Hello, Dashboard!</h1>
}

同一文件夹下如果有 layout.js 和 page.js,page 会作为 children 参数传入 layout。换句话说,layout 会包裹同层级的 page。

定义加载界面(Loading UI)

dashboard 目录下我们新建一个 loading.js

loading.js的代码如下:

js 复制代码
// app/dashboard/loading.js
export default function DashboardLoading() {
  return <>Loading dashboard...</>
}

同级的 page.js 代码如下:

js 复制代码
// app/dashboard/page.js
async function getData() {
  await new Promise((resolve) => setTimeout(resolve, 3000))
  return {
    message: 'Hello, Dashboard!',
  }
}

# 一定要是async定义的组件,不然loading.js不会生效
export default async function DashboardPage(props) {
  const { message } = await getData()
  return <h1>{message}</h1>
}

不再需要其他的代码,loading 的效果就实现了。

就是这么简单。其关键在于 page.js导出了一个 async 函数

loading.js 的实现原理是将 page.js和下面的 children 用 <Suspense> 包裹。因为page.js导出一个 async 函数,Suspense 得以捕获数据加载的 promise,借此实现了 loading 组件的关闭。

定义 404 页面

顾名思义,当该路由不存在的时候展示的内容。

Next.js 项目默认的 not-found 效果如下:

如果你要替换这个效果,只需要在 app 目录下新建一个 not-found.js,代码示例如下:

相关推荐
倾颜2 天前
从本地 Ollama 到线上多模型 Runtime:接入 DeepSeek / Qwen 的实战复盘
langchain·next.js·deepseek
濮水大叔4 天前
浅论CabloyJS全栈框架提供的“两级页签”机制
typescript·node.js·next.js
IVEN_5 天前
本地正常,Docker 怎么就空白:Next.js SSR 的 Alpine musl DNS 陷阱
前端·docker·next.js
Patrick_Wilson7 天前
K8s 探针避坑:Next.js 不同部署模式下的健康检查实践
kubernetes·node.js·next.js
戈德斯文12 天前
我做了一面互联网摸鱼墙:从无限 Canvas 到本地生产环境
react.js·canvas·next.js
三木檾13 天前
从 5 个文件读完一个生产级 AI Chatbot——Vercel AI Chatbot 源码拆解
ai编程·源码阅读·next.js
喵个咪15 天前
基于 Next.js 的 Headless CMS 前端架构:技术解析与二次开发导引
前端·react.js·next.js
倾颜15 天前
React 自定义 Hook 实战:把 AI Chat 的会话流和滚动体验从组件中拆出来
前端·react.js·next.js
竹林81825 天前
用 wagmi v2 + Next.js App Router 踩坑三天,我终于搞定了 NFT 交易市场的跨链签名与上架逻辑
next.js
明月_清风25 天前
全面了解 Vercel:前端开发者的高效武器库与实战指南
前端·next.js