Next.js 14 基础入门:从项目搭建到核心概念

news/2024/12/25 17:24:45/文章来源:https://www.cnblogs.com/yuanyanglu/p/18630998

Next.js 14 带来了许多激动人心的新特性,包括局部渲染、Server Actions 增强等。作为一名前端开发者,我最近在项目中升级到了 Next.js 14,今天就来分享一下从项目搭建到实际应用的完整过程。

项目初始化

首先,让我们创建一个全新的 Next.js 14 项目:

# 使用 create-next-app 创建项目
npx create-next-app@latest my-next-app

在初始化过程中,你会看到以下选项:

✔ Would you like to use TypeScript? Yes
✔ Would you like to use ESLint? Yes
✔ Would you like to use Tailwind CSS? Yes
✔ Would you like to use `src/` directory? Yes
✔ Would you like to use App Router? Yes
✔ Would you like to customize the default import alias? No

目录结构解析

创建完成后,我们来看看项目的核心目录结构:

my-next-app/
├── src/
│   ├── app/
│   │   ├── layout.tsx      # 根布局文件
│   │   ├── page.tsx        # 首页组件
│   │   ├── error.tsx       # 错误处理组件
│        ├── loading.tsx     # 加载状态组件
│   │   └── not-found.tsx   # 404页面组件
│   ├── components/         # 组件目录
│   └── lib/               # 工具函数目录
├── public/                # 静态资源目录
├── next.config.js        # Next.js 配置文件
└── package.json          # 项目依赖配置

App Router 基础

Next.js 14 推荐使用 App Router,它基于 React Server Components,提供了更好的性能和开发体验。

1. 基础路由

// src/app/page.tsx - 首页
export default function Home() {return (<main className="flex min-h-screen flex-col items-center justify-between p-24"><h1>Welcome to Next.js 14</h1></main>);
}// src/app/about/page.tsx - 关于页面
export default function About() {return (<div className="p-24"><h1>About Us</h1></div>);
}

2. 布局组件

// src/app/layout.tsx
export default function RootLayout({children,
}: {children: React.ReactNode;
}) {return (<html lang="en"><body><header><nav>{/* 导航栏组件 */}</nav></header><main>{children}</main><footer>{/* 页脚组件 */}</footer></body></html>);
}// src/app/blog/layout.tsx - 博客专属布局
export default function BlogLayout({children,
}: {children: React.ReactNode;
}) {return (<div className="blog-layout"><aside className="blog-sidebar">{/* 博客侧边栏 */}</aside><div className="blog-content">{children}</div></div>);
}

数据获取

Next.js 14 提供了多种数据获取方式,默认都是基于 Server Components:

1. 服务端获取数据

// src/app/posts/page.tsx
async function getPosts() {const res = await fetch('https://api.example.com/posts', {next: {revalidate: 3600 // 1小时重新验证一次}});if (!res.ok) {throw new Error('Failed to fetch posts');}return res.json();
}export default async function Posts() {const posts = await getPosts();return (<div className="posts-grid">{posts.map(post => (<PostCard key={post.id} post={post} />))}</div>);
}

2. 动态路由数据获取

// src/app/posts/[id]/page.tsx
async function getPost(id: string) {const res = await fetch(`https://api.example.com/posts/${id}`, {cache: 'no-store' // 禁用缓存,始终获取最新数据});if (!res.ok) {throw new Error('Failed to fetch post');}return res.json();
}export default async function Post({params: { id }
}: {params: { id: string }
}) {const post = await getPost(id);return (<article className="post-detail"><h1>{post.title}</h1><div>{post.content}</div></article>);
}

Server Actions

Next.js 14 增强了 Server Actions,让表单处理变得更简单:

// src/app/posts/new/page.tsx
export default function NewPost() {async function createPost(formData: FormData) {'use server';const title = formData.get('title');const content = formData.get('content');// 服务端验证if (!title || !content) {throw new Error('Title and content are required');}// 直接在服务端处理数据await db.post.create({data: {title: title as string,content: content as string,},});// 重定向到文章列表redirect('/posts');}return (<form action={createPost}><input type="text" name="title" placeholder="文章标题" /><textarea name="content" placeholder="文章内容" /><button type="submit">发布文章</button></form>);
}

客户端组件

虽然 Server Components 是默认的,但有时我们需要客户端交互:

// src/components/Counter.tsx
'use client';import { useState } from 'react';export default function Counter() {const [count, setCount] = useState(0);return (<div><p>Count: {count}</p><button onClick={() => setCount(count + 1)}>Increment</button></div>);
}

元数据配置

Next.js 14 提供了强大的元数据 API:

// src/app/layout.tsx
import { Metadata } from 'next';export const metadata: Metadata = {title: {template: '%s | My Next.js App',default: 'My Next.js App',},description: 'Built with Next.js 14',openGraph: {title: 'My Next.js App',description: 'Built with Next.js 14',images: ['/og-image.jpg'],},
};// src/app/blog/[slug]/page.tsx
export async function generateMetadata({params
}: {params: { slug: string }
}): Promise<Metadata> {const post = await getPost(params.slug);return {title: post.title,description: post.excerpt,openGraph: {title: post.title,description: post.excerpt,images: [post.coverImage],},};
}

静态资源处理

Next.js 14 优化了图片和字体的处理:

// src/components/ProfileImage.tsx
import Image from 'next/image';export default function ProfileImage() {return (<Imagesrc="/profile.jpg"alt="Profile"width={200}height={200}placeholder="blur"blurDataURL="data:image/jpeg;base64,..."priority/>);
}// src/app/layout.tsx
import { Inter } from 'next/font/google';const inter = Inter({subsets: ['latin'],display: 'swap',
});export default function RootLayout({children,
}: {children: React.ReactNode;
}) {return (<html lang="en" className={inter.className}><body>{children}</body></html>);
}

环境配置

Next.js 14 支持多环境配置:

# .env.local
DATABASE_URL="postgresql://..."
API_KEY="your-api-key"# .env.production
NEXT_PUBLIC_API_URL="https://api.production.com"# .env.development
NEXT_PUBLIC_API_URL="http://localhost:3000"

使用环境变量:

// src/lib/db.ts
const dbUrl = process.env.DATABASE_URL;
const apiKey = process.env.API_KEY;// 客户端也可以使用 NEXT_PUBLIC_ 前缀的环境变量
console.log(process.env.NEXT_PUBLIC_API_URL);

错误处理

Next.js 14 提供了完善的错误处理机制:

// src/app/error.tsx
'use client';export default function Error({error,reset,
}: {error: Error;reset: () => void;
}) {return (<div className="error-container"><h2>Something went wrong!</h2><p>{error.message}</p><button onClick={() => reset()}>Try again</button></div>);
}// src/app/not-found.tsx
export default function NotFound() {return (<div className="not-found"><h2>404 - Page Not Found</h2><p>Could not find requested resource</p></div>);
}

开发调试

Next.js 14 改进了开发体验:

// 使用 React Developer Tools
import { useDebugValue } from 'react';function useCustomHook() {const value = // ... 一些计算// 在 React DevTools 中显示自定义值useDebugValue(value, value => `Custom: ${value}`);return value;
}// 使用 next.config.js 配置开发环境
/** @type {import('next').NextConfig} */
const nextConfig = {reactStrictMode: true,// 启用详细的构建输出logging: {fetches: {fullUrl: true,},},// 配置重写规则rewrites: async () => {return [{source: '/api/:path*',destination: 'http://localhost:3001/api/:path*',},];},
};module.exports = nextConfig;

写在最后

Next.js 14 带来了许多激动人心的新特性,特别是在性能优化和开发体验方面有了显著提升。这篇文章介绍的只是基础功能,在实际项目中,你还可以:

  1. 使用 Middleware 进行路由控制
  2. 配置国际化路由
  3. 实现增量静态再生成(ISR)
  4. 使用 Edge Runtime 优化性能
  5. 集成各种第三方服务

在接下来的系列文章中,我们会深入探讨这些进阶主题。如果你对某个特定主题特别感兴趣,欢迎在评论区告诉我!

如果觉得这篇文章对你有帮助,别忘了点个赞 👍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/858728.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

优化大宽表查询性能,揭秘GaussDB(DWS) 谓词列analyze

谓词列通指于 WHERE 条件,join条件,group by中涉及到的列,更广义的是指所有需要用于计划生成需要统计信息列的列。本文分享自华为云社区《GaussDB(DWS) 谓词列analyze揭秘》,作者:SmithCoder。 1. 前言 适用版本:【9.1.0.100(及以上)】 ​当前GaussDB(DWS)中存在手动an…

指标管理+AI大模型深度融合,开启智能数据分析管理新时代

随着企业数字化转型的加速,数据管理和分析变得越来越重要。传统的指标管理平台虽然已经能够帮助企业有效地收集、计算、管理和展示关键指标,但在业务分析层面,面对日益复杂的数据环境和业务需求,单纯依靠人工分析已经难以满足高效、精准的管理要求。为此,将指标管理平台与…

nmon监控在linux环境下的安装

nmon下载官网: https://nmon.sourceforge.io/pmwiki.php?n=Site.Download一 、前言Nmon (Nigel’s Monitor)是由IBM 提供、免费监控 AIX 系统与 Linux 系统资源的工具。该工具可将服务器系统资源耗用情况收集起来并输出一个特定的文件,并可利用 excel 分析工具(nmon analyse…

项目管理系统 - 项目管理软件 | 禅道项目管理工具

引言在当今数字化时代,项目管理对于企业的成功至关重要。项目管理系统和软件层出不穷,其中禅道项目管理工具以其独特的优势脱颖而出。禅道作为一款开源的项目管理软件,涵盖了项目管理的各个方面,为企业提供了全面、高效的管理解决方案。无论是软件开发项目、工程建设项目还…

18款顶级在线项目管理网站分享,助你高效管理项目

在当今数字化时代,项目管理的效率和效果对于企业的成功至关重要。在线项目管理工具为企业提供了便捷、高效的解决方案,帮助团队更好地规划、执行和监控项目。本文将介绍18款顶级在线项目管理网站,涵盖不同类型的项目管理工具,希望能为读者带来启发,助力他们在项目管理中取…

大模型提示工程

大模型提示工程转:9 大模型提示词工程应用_哔哩哔哩_bilibili 1. 原则2. 清晰的指令2.1. 分隔符大模型基于概率生成,每次生成的话不一样 2.2. 结构化输出使用网页,直接复制文本 使用接口,就用代码 2.3. 参考示例2.4. 角色扮演3. 让模型思考3.1. 指定步骤大模型只是提供的便…

配置manage路由,实现嵌套路由

1、npm install vue-router 引入vue-router main.ts增加配置 import router from ./routes createApp(App).use(router) 2、src下新建目录routes,新建index.ts // index.ts import { createRouter, createWebHistory } from vue-router; // 引入Vue组件 import Home from ../p…

leetcode 1045

leetcode 1045select customer_id from (select customer_id,count(*) mfrom (select distinct * from Customer) a group by customer_id having count(*) in (select count(*) from Product))p ;日记 23号是周一,到今天圣诞节都没有去上班,请假了,主要是软工的课设要忙,事…

ThreadLocal与InheritableThreadLocal

ThreadLocal底层是个map每次set值的时候把当前线程与值放到里面ThreadLocal.ThreadLocalMap threadLocals = null; 这种结构在大数据量并发请求时会,会产生内存泄漏。 请求时set进去,正常退出move掉,来不及remove的数据会停留在内存中,外界还有引用,gc不会收就会泄露如果子…

mysql 127.0.0.1连接正常,使用ip无法连接

mysql 127.0.0.1连接正常,使用ip无法连接 1. 使用 127.0.0.1连接mysql mysql -uroot -p -h127.0.0.12. 使用ip连接mysql # 查看当前虚机的ip地址 ip a # 使用ip地址连接mysql mysql -uroot -p -h192.168.91.133错误信息: ERROR 1130 (HY000): Host 192.168.91.133 is not allow…

el-Pagination的pagerCount传参报错

◾呈现的问题 控制台一直警告,看着很不爽,内容如下 [Vue warn]: Invalid prop: custom validator check failed for prop "pagerCount". found in ---> <ElPagination> <Pagination> <PolicyInfo> at src/views/policy/policyI…

最小二乘法-直线拟合-C语言

‌最小二乘法是一种数学统计方法,它通过最小化误差的平方和来寻找数据的最佳函数匹配‌。具体来说,它用于解决曲线拟合问题,即找到一个函数,使得该函数在给定数据点上的误差(通常是垂直距离)的平方和最小。这种方法广泛应用于数据分析和机器学习等领域,特别是在处理线性…