Next.js第二课 - 项目结构详解 - 优栈

张开发
2026/4/5 20:31:32 15 分钟阅读

分享文章

Next.js第二课 - 项目结构详解 - 优栈
上节我们搭建好了 Next.js 开发环境本节就来详细了解一下 Next.js 的项目结构。很多初学者刚打开项目时会看到一堆文件和文件夹不知道每个都是干什么的。别担心本节会带你理清这些目录和文件的用途让你对项目结构有一个清晰的认识。项目结构概览my-nextjs-app/ ├── app/# App Router主要工作目录│ ├──(auth)/# 路由组不影响 URL│ │ ├── login/ │ │ │ └── page.tsx │ │ └── register/ │ │ └── page.tsx │ ├── api/# API 路由│ │ └── users/ │ │ └── route.ts │ ├── blog/# 应用路由│ │ ├──[slug]/# 动态路由│ │ │ └── page.tsx │ │ └── page.tsx │ ├── layout.tsx# 根布局│ ├── page.tsx# 首页│ ├── loading.tsx# 加载状态│ ├── error.tsx# 错误处理│ ├── not-found.tsx# 404 页面│ └── globals.css# 全局样式├── components/# 共享组件│ ├── ui/# UI 基础组件│ │ ├── Button.tsx │ │ ├── Input.tsx │ │ └── Card.tsx │ └── layout/# 布局组件│ ├── Header.tsx │ └── Footer.tsx ├── lib/# 工具函数│ ├── utils.ts │ ├── api.ts │ └── constants.ts ├── hooks/# 自定义 Hooks│ ├── useAuth.ts │ └── useData.ts ├── types/# TypeScript 类型│ └── index.ts ├── public/# 静态资源│ ├── images/ │ ├── fonts/ │ └── favicon.ico ├── styles/# 样式文件可选│ └── globals.css ├── .env.local# 环境变量├── .eslintrc.json# ESLint 配置├── .gitignore# Git 忽略文件├── next.config.js# Next.js 配置├── package.json# 项目配置├── tsconfig.json# TypeScript 配置└── README.md# 项目说明核心目录详解1. app/ 目录 - App Routerapp/目录是 Next.js 13 推荐的新路由系统基于 React Server Components 构建。这是你工作中最常打交道的目录绝大部分页面和路由都会放在这里。特殊文件文件用途必需layout.tsx定义布局和 UI可选page.tsx定义路由的独特 UI必需可访问路由loading.tsx加载时的 UI 替换可选error.tsx错误边界 UI可选not-found.tsx404 页面可选route.tsAPI 端点API 路由必需示例结构app/ ├──(marketing)/# 路由组│ ├── about/ │ │ └── page.tsx# /about│ ├── layout.tsx# 营销页面共享布局│ └── page.tsx# /├──(shop)/# 另一个路由组│ ├── account/ │ │ └── page.tsx# /account│ └── layout.tsx# 商店页面共享布局├── products/ │ ├──[id]/# 动态段│ │ └── page.tsx# /products/123│ └── page.tsx# /products├── api/ │ └── users/ │ └── route.ts# /api/users (API)├── layout.tsx# 根布局所有页面共享└── page.tsx# 首页2. components/ 目录这里存放可复用的 React 组件。当你发现一段 UI 代码在多个页面重复出现时就可以把它抽取成一个组件放到这里。随着项目变大良好的组件组织会让代码更容易维护。components/ ├── ui/# 基础 UI 组件│ ├── Button.tsx │ ├── Input.tsx │ ├── Modal.tsx │ └── Table.tsx ├── layout/# 布局组件│ ├── Header.tsx │ ├── Footer.tsx │ ├── Sidebar.tsx │ └── Navigation.tsx ├── features/# 功能组件│ ├── UserProfile.tsx │ ├── ProductCard.tsx │ └── CommentList.tsx └── forms/# 表单组件├── LoginForm.tsx └── ContactForm.tsx组件示例// components/ui/Button.tsx interface ButtonProps{children: React.ReactNode onClick?:()void variant?:primary|secondary}exportfunctionButton({children, onClick, variantprimary}: ButtonProps){return(buttononClick{onClick}className{px-4 py-2 rounded ${variantprimary?bg-blue-500 text-white:bg-gray-200 text-gray-800}}{children}/button)}3. lib/ 目录这里存放工具函数、API 客户端、常量等辅助代码。把不属于任何特定业务逻辑的通用代码放在这里是个好习惯。lib/ ├── utils/# 工具函数│ ├── format.ts# 格式化函数│ ├── validation.ts# 验证函数│ └── helpers.ts# 辅助函数├── api/# API 客户端│ ├── client.ts │ ├── users.ts │ └── products.ts ├── db/# 数据库相关│ ├── connect.ts │ └── queries.ts └── constants.ts# 常量定义工具函数示例// lib/utils/format.tsexportfunctionformatDate(date: Date): string{returnnew Intl.DateTimeFormat(zh-CN,{year:numeric, month:long, day:numeric,}).format(date)}exportfunctionformatCurrency(amount: number): string{returnnew Intl.NumberFormat(zh-CN,{style:currency, currency:CNY,}).format(amount)}4. hooks/ 目录存放自定义 React Hooks。如果你有一些状态逻辑需要在多个组件中复用就可以封装成自定义 Hook 放在这里。hooks/ ├── useAuth.ts# 认证相关├── useData.ts# 数据获取├── useForm.ts# 表单处理└── useLocalStorage.ts# 本地存储Hook 示例// hooks/useAuth.tsuse clientimport{useState, useEffect}fromreactexportfunctionuseAuth(){const[isAuthenticated, setIsAuthenticated]useState(false)const[user, setUser]useState(null)useEffect((){// 检查认证状态 const tokenlocalStorage.getItem(token)setIsAuthenticated(!!token)},[])return{isAuthenticated, user}}5. public/ 目录这里存放静态资源比如图片、字体、favicon 等。放在 public 目录下的文件可以直接通过 URL 访问不需要 import。public/ ├── images/ │ ├── logo.png │ └── banner.jpg ├── fonts/ │ └── custom-font.woff2 ├── favicon.ico └── robots.txt使用方式// 在组件中引用Imagesrc/images/logo.pngaltLogowidth{200}height{100}/6. 根配置文件next.config.js/** type{import(next).NextConfig}*/ const nextConfig{reactStrictMode: true, swcMinify: true, // 图片优化配置 images:{domains:[example.com], formats:[image/avif,image/webp],}, // 环境变量 env:{CUSTOM_KEY: process.env.CUSTOM_KEY,}, // 重定向 asyncredirects(){return[{source:/old-path, destination:/new-path, permanent: true,},]},}module.exportsnextConfigtsconfig.json{compilerOptions:{target:ES2017,lib:[dom,dom.iterable,esnext],allowJs:true,skipLibCheck:true,strict:true,forceConsistentCasingInFileNames:true,noEmit:true,esModuleInterop:true,module:esnext,moduleResolution:bundler,resolveJsonModule:true,isolatedModules:true,jsx:preserve,incremental:true,plugins:[{name:next}],paths:{/*:[./*]}},include:[next-env.d.ts,**/*.ts,**/*.tsx,.next/types/**/*.ts],exclude:[node_modules]}路由组织最佳实践1. 使用路由组路由组(group-name)是 Next.js 的一个很有用的特性它不会影响 URL 路径但可以帮助你更好地组织代码和共享布局。比如你想把某些页面放在一起管理但又不想改变 URL 结构就可以用路由组。app/ ├──(marketing)/# /about, /contact│ ├── about/ │ │ └── page.tsx │ ├── contact/ │ │ └── page.tsx │ └── layout.tsx# 营销页面共享布局├──(dashboard)/# /dashboard, /settings│ ├── dashboard/ │ │ └── page.tsx │ ├── settings/ │ │ └── page.tsx │ └── layout.tsx# 需要认证的布局└── page.tsx# 首页2. 动态路由动态路由在实际开发中非常常见比如博客文章页、用户详情页等。使用方括号[param]就可以创建动态路由段Next.js 会自动匹配并解析参数。app/ ├── blog/ │ ├──[slug]/# /blog/hello-world│ │ └── page.tsx │ └── page.tsx# /blog├── products/ │ ├──[category]/# /products/electronics│ │ └── page.tsx │ └── page.tsx# /products└── users/ └──[id]/# /users/123├──[action]/# /users/123/edit│ └── page.tsx └── page.tsx# /users/1233. 并行和拦截路由并行路由和拦截路由是 Next.js 的高级特性可以实现一些复杂的交互效果比如模态框、并行加载多个页面等。这些特性在实际项目中非常有用但理解起来可能需要一点时间。app/ ├── dashboard/# 并行路由槽│ └── page.tsx ├──(.)modal/# 拦截路由│ └── photo/[id]/page.tsx ├── dashboard/ │ └── page.tsx └── layout.tsx文件命名约定路由相关模式说明示例 URLfolder/page.tsx标准路由/folderfolder/[slug]/page.tsx动态路由/folder/valuefolder/[[...slug]]/page.tsx捕获所有路由/folder/a/b/c(group)/page.tsx路由组/pagefolder/(.)modal/...拦截路由-特殊文件文件说明_filename.tsx私有文件不创建路由filename.server.tsx仅在服务器运行filename.client.tsx仅在客户端运行代码组织建议1. 按功能组织按功能组织是一种常见的项目结构方式把相关的功能放在一起。这种方式适合中小型项目代码结构清晰易懂。app/ ├──(auth)/ │ ├── login/ │ ├── register/ │ └── forgot-password/ ├──(dashboard)/ │ ├── overview/ │ ├── analytics/ │ └── settings/ └──(public)/ ├── about/ ├── contact/ └── pricing/2. 按层级组织按层级组织适合大型项目比如有 API 版本管理、多级管理后台等场景。这种方式可以让结构更有层次感。app/ ├── api/ │ ├── v1/ │ │ ├── users/ │ │ └── posts/ │ └── v2/ │ └── users/ └── admin/ └── users/ ├──[id]/ └── new/3. 组件分层组件分层是一种借鉴原子设计的组织方式把组件按照复杂度分成原子、分子、组织、模板等层级。这种方式适合 UI 组件库或者设计系统比较完善的项目。components/ ├── atoms/# 最小单元│ ├── Button.tsx │ └── Input.tsx ├── molecules/# 组合原子│ ├── SearchBar.tsx │ └── FormField.tsx ├── organisms/# 复杂组件│ ├── Header.tsx │ └── ProductCard.tsx └── templates/# 页面模板└── BlogLayout.tsx环境变量环境变量用来存储一些敏感信息或者配置比如数据库连接字符串、API 密钥等。创建.env.local文件来存放这些信息记得把这个文件加到.gitignore里不要提交到代码仓库。# 数据库DATABASE_URLpostgresql://...# API 密钥API_KEYyour_api_keyAPI_SECRETyour_api_secret# 应用配置NEXT_PUBLIC_APP_URLhttp://localhost:3000访问方式// 服务器端 const dbUrlprocess.env.DATABASE_URL // 客户端必须以 NEXT_PUBLIC_ 开头 const appUrlprocess.env.NEXT_PUBLIC_APP_URL总结本节我们详细了解了 Next.js 的项目结构包括各个目录的用途、路由组织方式、以及一些最佳实践。掌握项目结构是学好 Next.js 的基础建议你多花点时间理解这些内容。如果你对本节内容有任何疑问欢迎在评论区提出来我们一起学习讨论。原文地址https://blog.uuhb.cn/archives/Next-js-02.html

更多文章