news 2026/5/8 15:35:40

Next.js 14 完整指南:App Router 深度实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Next.js 14 完整指南:App Router 深度实践

Next.js 14 完整指南:App Router 深度实践

嗨,我是欧阳瑞。今天来聊聊 Next.js 14,特别是全新的 App Router。作为一个全栈开发者,我最近把几个项目都迁移到了 App Router,体验真的很棒!

为什么升级到 App Router?

Next.js 14 的 App Router 带来了很多令人兴奋的特性:

  • 服务端组件(Server Components)默认启用
  • 内置数据获取(fetch 自动缓存)
  • 简化的路由系统
  • 更好的 TypeScript 支持

项目初始化

npx create-next-app@14.0.0 my-app --typescript --tailwind --app cd my-app

App Router 核心概念

1. 路由结构

App Router 采用文件系统路由,目录结构就是路由结构:

app/ ├── layout.tsx # 根布局 ├── page.tsx # 首页 ├── about/ │ └── page.tsx # /about ├── blog/ │ ├── [slug]/ │ │ └── page.tsx # /blog/xxx │ └── page.tsx # /blog � └── layout.tsx # blog 目录的布局

2. 服务端组件 vs 客户端组件

服务端组件(默认)

// app/page.tsx - 默认是服务端组件 async function fetchPosts() { const res = await fetch('https://api.example.com/posts', { cache: 'force-cache', // 默认缓存 }); return res.json(); } export default async function Home() { const posts = await fetchPosts(); return ( <div> {posts.map((post) => ( <div key={post.id}>{post.title}</div> ))} </div> ); }

客户端组件:需要显式声明

// app/components/InteractiveComponent.tsx 'use client'; import { useState } from 'react'; export default function InteractiveComponent() { const [count, setCount] = useState(0); return ( <button onClick={() => setCount(c => c + 1)}> Clicked {count} times </button> ); }

3. Layout 布局系统

根布局app/layout.tsx

import type { Metadata } from 'next'; import { Inter } from 'next/font/google'; import './globals.css'; const inter = Inter({ subsets: ['latin'] }); export const metadata: Metadata = { title: 'My App', description: 'A Next.js 14 App', }; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="zh-CN"> <body className={inter.className}> <header className="bg-cyan-500 text-white p-4"> <h1 className="text-xl">My Awesome App</h1> </header> {children} </body> </html> ); }

4. 数据获取策略

Next.js 14 提供了多种数据缓存策略:

// 静态生成(默认) const res = await fetch('https://api.example.com/data', { cache: 'force-cache', }); // 动态获取(每次请求都重新获取) const res = await fetch('https://api.example.com/data', { cache: 'no-store', }); // 增量静态重新生成 const res = await fetch('https://api.example.com/data', { next: { revalidate: 60 }, // 60秒重新验证 });

5. 动态路由

创建app/blog/[slug]/page.tsx

interface Params { slug: string; } async function getPost(slug: string) { const res = await fetch(`https://api.example.com/posts/${slug}`); return res.json(); } export default async function PostPage({ params }: { params: Params }) { const post = await getPost(params.slug); return ( <article> <h1 className="text-3xl font-bold mb-4">{post.title}</h1> <p className="text-gray-600">{post.content}</p> </article> ); } // 生成静态路径(可选) export async function generateStaticParams() { const posts = await fetch('https://api.example.com/posts').then(res => res.json()); return posts.map((post) => ({ slug: post.slug, })); }

6. 错误处理

创建app/blog/[slug]/error.tsx

'use client'; export default function Error({ error, reset, }: { error: Error & { digest?: string }; reset: () => void; }) { return ( <div className="text-red-500"> <p>Something went wrong: {error.message}</p> <button onClick={() => reset()}>Try again</button> </div> ); }

7. 加载状态

创建app/blog/loading.tsx

export default function Loading() { return ( <div className="animate-pulse"> <div className="h-8 bg-cyan-200 w-32 mb-4" /> <div className="h-4 bg-cyan-100 w-full mb-2" /> <div className="h-4 bg-cyan-100 w-3/4" /> </div> ); }

8. 服务端 Actions

app/actions.ts中定义:

'use server'; export async function createPost(formData: FormData) { const title = formData.get('title') as string; const content = formData.get('content') as string; const res = await fetch('https://api.example.com/posts', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title, content }), }); if (!res.ok) { throw new Error('Failed to create post'); } return res.json(); }

在组件中使用:

'use client'; import { createPost } from '@/app/actions'; export default function CreatePostForm() { async function handleSubmit(formData: FormData) { await createPost(formData); // 成功后的处理 } return ( <form action={handleSubmit}> <input type="text" name="title" placeholder="Title" /> <textarea name="content" placeholder="Content" /> <button type="submit">Create</button> </form> ); }

性能优化技巧

1. 图片优化

import Image from 'next/image'; export default function MyImage() { return ( <Image src="/hero.jpg" alt="Hero" width={1200} height={600} priority // 首屏图片优先加载 placeholder="blur" /> ); }

2. 字体优化

import { Inter, Roboto_Mono } from 'next/font/google'; const inter = Inter({ subsets: ['latin'], display: 'swap', }); const mono = Roboto_Mono({ subsets: ['latin'], display: 'swap', });

3. 代码分割

Next.js 自动进行代码分割,但你也可以手动控制:

import dynamic from 'next/dynamic'; const HeavyComponent = dynamic(() => import('./HeavyComponent'), { loading: () => <p>Loading...</p>, ssr: false, // 只在客户端渲染 });

部署到 Vercel

vercel

一键部署,Vercel 会自动配置好所有优化。

总结

Next.js 14 的 App Router 让全栈开发变得更简单、更高效。我的鬃狮蜥 Hash 看着我用 Next.js 快速构建项目,似乎也想学习编程了——不过它现在更专注于晒太阳。

有问题欢迎留言交流,我是欧阳瑞,极客之路,永无止境!


技术栈:Next.js 14 · App Router · React · TypeScript · Tailwind CSS

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/8 15:35:17

百度地图Web API进阶:模块化封装、性能优化与工程化实践

1. 项目概述&#xff1a;从“能用”到“好用”的百度地图Web API进阶之路如果你在项目中用过百度地图的JavaScript API&#xff0c;那你大概率经历过这样的场景&#xff1a;照着官方文档&#xff0c;把地图显示出来&#xff0c;加几个标记点&#xff0c;实现个简单的点击弹窗&a…

作者头像 李华
网站建设 2026/5/8 15:34:25

从科幻预言到技术现实:能源、物联网与信任的未来挑战

1. 从“毛球”到未来&#xff1a;一位科幻大师的技术预言与我们的现实挑战如果你和我一样&#xff0c;是个老派的科幻迷&#xff0c;那么“大卫杰罗德”这个名字一定不会陌生。他最广为人知的成就&#xff0c;无疑是《星际迷航》里那集让人又爱又恨的《毛球危机》。那些毛茸茸、…

作者头像 李华
网站建设 2026/5/8 15:34:00

为你的Claude Code编程助手配置Taotoken密钥以突破使用限制

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 为你的Claude Code编程助手配置Taotoken密钥以突破使用限制 对于依赖Claude Code进行日常开发的工程师而言&#xff0c;遇到服务中…

作者头像 李华
网站建设 2026/5/8 15:33:45

英雄联盟R3nzSkin国服版:5分钟免费体验所有皮肤的神奇工具

英雄联盟R3nzSkin国服版&#xff1a;5分钟免费体验所有皮肤的神奇工具 【免费下载链接】R3nzSkin-For-China-Server Skin changer for League of Legends (LOL) 项目地址: https://gitcode.com/gh_mirrors/r3/R3nzSkin-For-China-Server 你是否曾羡慕别人拥有炫酷的英雄…

作者头像 李华
网站建设 2026/5/8 15:33:10

Flutter 智能相册:基于逆地址解析实现「旅行记忆检测」

前言最近在做一个 AI 原生相册项目 Memoria / 智能影记。项目本身已经具备相册扫描、事件聚类、AI 打标、地点解析、照片图谱等能力。在一次真机调试中&#xff0c;我发现一个很有价值的方向&#xff1a; 既然照片已经能通过 GPS 和高德逆地址解析得到城市、区县、地点名&#…

作者头像 李华