TBD.
在 generative AI 时代,因为有 GPT、Claude、Deepseek 这样的大语言模型,Cursor、Trae 这样的开发工具,无论是编写代码时使用 LLM,还是将 LLM 集成在 app 中,构建一个 app 的门槛被大大降低。而网页是一个极佳的 app 分发渠道,可以在几分钟内让全世界的用户用上自己的产品,因此,如何优雅地开发、部署一个网页 app,同时具备最低认知负荷 + 最佳实践,就变得很重要。
但真的,直到如今,还有独立开发者不知道 Vercel 和 Railway,在使用 EC2 这样的服务器部署,还有人没有用上 Tailwind + shadcn/ui 这样编写更流畅、灵活度非常高的组件库,还有很多初学者不明白后端是什么,没有发现或尝试 FastAPI 这样的框架,以为后端非常复杂非常难。
但显然事实不是这样,这些都只是信息差罢了,因此我想写一篇短短的文章为初学者提供一些参考。
在千万种组合中,我想这样推荐:
首先简短的介绍一下,Next.js 是如今最主流的前端框架之一,ChatGPT 和一众 AI web app 都是 Next.js 开发的,他提供了一个非常集成的开发框架和相应生态,可以开箱即用的启动一个完整的网页服务,出厂便自带了服务端渲染、SEO(搜索引擎优化)、路由系统等。Next.js 的背后是 React.js,使用 React 和 Vue 这样的前端 UI 引擎好处是他们极大简化了网页 UI 的开发模式,且生态非常丰富。
在有了 Next.js 的网页工程后,Vercel 只需要几次点击就可以帮你搞定剩下的一切,它会通过 git 仓库自动更新,搞定域名、CDN、SSL 证书、负载均衡、日志等,帮你把网页部署到全球各地的服务器上,让你的网页全球可见,且永不掉线。
后端和前端一样,也是一个萝卜青菜各有所爱的领域。Next.js 内置了一个 API 服务端,可以与服务端渲染非常好地结合在一起,我也有许多项目直接使用 Next.js 中的后端,但是 Next.js 中的后端对于初学者来说略微有些绕,不明白原理反而有点难上手。因此,这里更推荐使用 Python 中的 FastAPI 开始上手后端开发,这同样是一个设计得非常好的库,也是我入门了无数个不同语言的后端库后最喜欢的一个。FastAPI 可以以最简洁的方式,帮助初学者快速了解后端开发的基本原理。
后端的部署同样是一个难题,传统的解决方案,比如租服务器运维,用云函数等,都需要花费大量的开发主要业务逻辑意外的时间精力,而 Railway 恰是后端界的 Vercel,同样提供了一个非常简单易用的部署方式,同样可以持续集成 / 持续部署,将后端部署至全球。
以下是步骤与逐步解析。
安装包下载完成后,运行安装包
安装结束后在终端运行以下命令检查是否成功
# 验证安装结果
node -v # 应返回 v20.x.x 格式版本
npm -v # 应返回 9.x.x 以上版本
出现对应版本号说明 Node.js 已经成功安装
由于 npm 的依赖安装速度慢、进度现实不好等原因,市面上出现了 yarn / pnpm / bun 三个替代品,他们可能拥有更好的性能、有依赖安装的本地缓存。下表中更详细的进行了对比,可以根据自身开发需要进行选取
特性 | npm | Yarn | pnpm | Bun |
---|---|---|---|---|
安装速度 | ⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
磁盘效率 | ⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐ |
热更新速度 | ⭐⭐ | ⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ |
生态兼容性 | 原生支持 | 优秀 | 优秀 | 发展中 |
跨项目缓存 | 无 | 有 | 全局存储 | 内置缓存 |
越来越多的开发者选择使用这些第三方包管理工具,下面我们会使用 pnpm 作为样例。在已经成功安装 nodejs 的基础上,可以直接使用 npm 命令安装 pnpm,如图所示,在终端中运行
# 使用 npm 安装
npm install -g pnpm
# 如遇到权限问题,使用
sudo npm install -g pnpm
安装结束后在终端运行以下命令检查是否成功
# 验证安装
pnpm -v # 应返回 8.x.x 以上版本
出现对应版本号说明 pnpm 已经成功安装
首先,使用 Next.js 官方的脚手架创建一个项目:
# 进入目标目录
cd your-workspace-folder
# 使用官方脚手架创建项目(交互式配置)
npx create-next-app@latest
因为项目是使用 npm 作为包管理器,因此我们需要删除项目中的 package-lock.json
文件,然后使用 pnpm 安装依赖。
# 删除 npm 锁定文件
rm package-lock.json
# 使用 pnpm 重新安装依赖
pnpm install
也可以选择直接使用 pnpm 的脚手架直接创建项目,这将省去删除 package-lock.json
文件并重新安装依赖的步骤。
# 进入目标目录
cd your-workspace-folder
# 一步完成项目创建与依赖安装
pnpm create next-app
# 交互式配置流程与 npm 版本完全一致
待创建完成后,使用以下命令启动项目。
# 进入项目目录
cd my-app
pnpm dev
默认将会在 3000 端口处开启一个预览网页,在示例图片中 3000 端口被占用,因此开在 3001 端口处。浏览器访问 http://localhost:3000 (本示例中为 http://localhost:3001 ) 应显示 Next.js 欢迎页
同时,检查项目结构应包含以下核心文件:
├── app/
│ ├── layout.tsx
│ └── page.tsx
├── public/
├── package.json
└── next.config.js
说明项目创建与运行正常。
首先,如果没有 GitHub 账户,需要在 GitHub 官网 注册一个账户。同时,可以下载 GitHub Desktop 来方便地进行项目的同步和管理。
登录 GitHub Desktop: 在 GitHub Desktop 中,使用你的 GitHub 账户信息进行登录。
创建新仓库:
点击菜单栏中的 File
,然后选择 New Repository
来创建一个新的仓库。
设置仓库信息: 在弹出的窗口中,填写你的新仓库的相关信息:
发布项目:
设置完成后,点击 Publish repository
按钮,将你的项目上传至 GitHub。
你的 Next.js 项目应成功上传至 GitHub 了。其他人可以通过项目链接查看和参与你的项目。
Vercel 的优势:
创建新项目:
首先,在 Vercel 官网 注册一个账户,注册后登录你的账户,以便管理和部署项目。
登录后,点击页面中的 New Project
按钮来创建一个新的项目。
导入 GitHub 仓库:
在弹出的窗口中,选择 Import Git Repository
,然后找到并选择你刚才创建的 GitHub 仓库,点击 Import
将项目导入 Vercel。
打包前端工程: 导入项目完成后,Vercel 会开始自动打包你的前端工程。在此过程中,系统会构建你的 Next.js 应用并准备部署。Vercel 会自动优化你的项目,包括代码拆分和静态页面生成,以提升加载速度和性能。
设置域名:
打包完成后,Vercel 会自动为你分配一个域名。你可以在 Settings -> Domains
中修改域名,建议使用一个未被他人使用过的 .vercel.app
域名。
完成以上步骤后,你的 Next.js 项目就成功部署到了 Vercel,访问分配的域名即可查看你的应用。
我们将使用 Python + FastAPI 编写后端,而 uv 是一个新的高性能 Python 包管理器,它甚至可以帮我们下载并管理 Python 版本,所以我们使用 uv 来安装 Python。
根据 FastAPI 官网的指引进行安装。
启动 FastAPI 后,在浏览器中打开 http://localhost:3000,即可看到刚才 Python 文件中出现的 Hello, World!
,这是因为浏览器访问域名的本质就是向这个域名发送一个 GET 请求,FastAPI 在接收到请求后,返回了一个 JSON 对象,浏览器接收到 JSON 对象后,将其渲染为 Hello, World!
。
而为了能调试除了 GET 请求以外的 RESTFUL 请求,我们可以使用 Apifox 来测试 FastAPI 写的 API。
你还可以在 Apifox 里设置自动导入 FastAPI 的 /openapi.json,免去手动创建接口的步骤。
同理,将 FastAPI 项目上传至 GitHub,以便连接 Railway 部署。
Railway 提供了 Python + FastAPI 的模版,可以一键点击部署,但因为我们使用了 uv 和自定义的端口,所以还需要修改代码以使 Railway 能够正确部署、运行我们的后端代码。
有了本地 + 线上部署的后端,我们可以尝试在 Next.js 中调用后端接口,进行服务端数据渲染。
如果是偏向客户端的数据渲染,可以采用 swc 进行开发。
shadcn/ui 提供了一系列精心设计的 React UI 组件,这些组件可以直接复制到项目中使用,并方便进行二次开发和个性化定制。
Tailwind CSS 通过提供大量预定义的原子化类名,简化样式编写,减少代码冗余,提高开发效率。
v0.dev 是由 Vercel 推出的 AI 驱动的生成式 UI 工具,可以基于自然语言,截图和figma设计稿快速生成并迭代前端界面代码。 v0.dev 目前主要专注于 react 并基于 shadcn/ui 和 Tailwind CSS 的主流 UI 框架。
用户只需输入描述(例如“生成一个带滑动验证的登录页面”),v0 就能基于这些提示生成相应的 UI 组件代码(目前主要为 React 组件代码)。
v0 还支持导入 Figma 设计稿(付费)以及上传界面截图,自动解析设计中的组件、布局和样式信息之后生成高度还原的 React UI 组件代码。
生成初版后,开发者可以针对不满意的细节提出修改要求,v0 会在原有基础上迭代生成新版本(如 v1、v2 等)。
v0 生成的代码结合了 shadcn/ui 和 Tailwind CSS 的优势:前者提供了易用且便于二次开发的 UI 组件,而后者则以原子化 CSS 实现高效样式描述。
Cloudflare 不仅可以为你的网站提供 DNS 解析和 CDN 加速,还可以通过 Cloudflare Images 服务提供高性能的图床解决方案。
首先在 Cloudflare 注册账号,添加你的域名,按照指引修改域名的 NS 记录。完成后,你可以在 Cloudflare 的控制面板中管理域名的所有 DNS 记录。
对于 Vercel 和 Railway 的项目,只需要:
Cloudflare Images 提供了:
你可以通过以下方式使用:
https://imagedelivery.net/<YOUR_ACCOUNT_HASH>/<IMAGE_ID>/<VARIANT_NAME>
的 URL 访问图片官方文档提供了通过应用路由器(App Router)(包括是否使用 i8n 路由)和页面路由器(Page Router)进行配置的配置方法。
无论哪种配置方法,过程主要分为以下步骤:
# 使用 npm 安装
npm install next-intl
# 或者使用 pnpm
pnpm add next-intl
在 public/locales/
或 messages/
目录下创建不同语言的 JSON 文件。
实现自动检测用户的语言并进行语言重定向。
调用 useTranslations()
从 JSON 文件中获取翻译,并返回对应的翻译文本。
在 Next.js 中,通过配置 @next/mdx 插件,可以将 .mdx 文件自动转换为 React 组件。这些组件可直接作为页面路由或通过导入使用,同时保留 Markdown 的简洁语法和 React 的交互能力。
官方文档附有完整的教程:
Next.js 13+ 提供了强大的后端开发能力,通过 App Router 可以直接在前端项目中编写后端 API。这种方式的优势在于:
在 app/api
目录下创建路由处理器:
import { NextResponse } from 'next/server'
export async function GET() {
return NextResponse.json({ message: 'Hello, Next.js!' })
}
在组件中直接定义服务端函数:
'use server'
export async function submitForm(formData: FormData) {
const name = formData.get('name')
await saveToDatabase({ name })
}
使用 React Server Components 直接在组件中获取数据:
async function getData() {
const res = await fetch('https://api.example.com/data')
return res.json()
}
export default async function Page() {
const data = await getData()
return <main>{/* 使用数据渲染UI */}</main>
}
Vercel 提供了多种数据库集成方案,最推荐的是 Vercel Storage,它提供:
基于 Neon 的 Serverless SQL 数据库:
import { sql } from '@vercel/postgres'
export async function getData() {
const { rows } = await sql`SELECT * FROM users`
return rows
}
基于 Upstash 的 Redis 键值存储:
import { kv } from '@vercel/kv'
export async function cacheData(key: string, value: any) {
await kv.set(key, value)
await kv.expire(key, 3600) // 1小时后过期
}
对象存储服务,适合存储用户上传的文件:
import { put } from '@vercel/blob'
export async function uploadFile(formData: FormData) {
const file = formData.get('file') as File
const blob = await put(file.name, file, {
access: 'public',
})
return blob.url
}
Auth.js(原 NextAuth.js)是目前最流行的 Next.js 身份验证方案,提供了:
import NextAuth from 'next-auth'
import GithubProvider from 'next-auth/providers/github'
const handler = NextAuth({
providers: [
GithubProvider({
clientId: process.env.GITHUB_ID,
clientSecret: process.env.GITHUB_SECRET,
}),
],
})
export { handler as GET, handler as POST }
export { default } from 'next-auth/middleware'
export const config = {
matcher: ['/protected/:path*']
}
'use client'
import { useSession } from 'next-auth/react'
export default function AuthStatus() {
const { data: session } = useSession()
return <div>{session ? '已登录' : '未登录'}</div>
}
Vercel AI SDK 提供了一套完整的工具,用于在 Next.js 应用中集成 AI 功能:
pnpm add ai openai
import { Configuration, OpenAIApi } from 'openai-edge'
import { OpenAIStream, StreamingTextResponse } from 'ai'
const config = new Configuration({
apiKey: process.env.OPENAI_API_KEY,
})
const openai = new OpenAIApi(config)
export async function POST(req: Request) {
const { messages } = await req.json()
const response = await openai.createChatCompletion({
model: 'gpt-3.5-turbo',
stream: true,
messages,
})
const stream = OpenAIStream(response)
return new StreamingTextResponse(stream)
}
'use client'
import { useChat } from 'ai/react'
export default function Chat() {
const { messages, input, handleInputChange, handleSubmit } = useChat()
return (
<div>
{messages.map(m => (
<div key={m.id}>{m.content}</div>
))}
<form onSubmit={handleSubmit}>
<input
value={input}
onChange={handleInputChange}
placeholder="说点什么..."
/>
</form>
</div>
)
}