前言
博客是个人展示自我、分享知识的好地方。近年来,随着前端技术的不断发展,前端技术也开始广泛应用于博客的开发中。本文将介绍如何使用 Next.js + Typeorm + Prisma 技术栈,快速搭建一个高效的博客网站。并讨论常见的前端开发问题和解决方案。
技术栈介绍
Next.js
Next.js 是 React 的服务端渲染框架,为 React 应用提供开箱即用的服务端渲染、自动代码分割、静态文件服务、按需编译以及 CDN 缓存等功能。Next.js 能够让开发者专注于编写组件,而无需关注枯燥的构建配置。
Typeorm
Typeorm 是一个 ORM(Object-Relational Mapping)框架,用于将关系数据库转换为对象。它支持各种关系型数据库,如 MySQL、PostgreSQL、SQLite 和 Oracle 等。Typeorm 可以轻松处理数据建模、查询管理和数据库迁移等任务。
Prisma
Prisma 是一个类型化的数据访问库,可以用于构建现代 Web 应用程序。Prisma 通过自动生成类型化应用程序查询 API,为开发人员提供了更高的生产力和可靠性。它支持多个数据库,包括 Postgres、MySQL 和 SQLite。
项目实战
项目结构
我们的博客项目需要有以下基本结构:
// javascriptcn.com 代码示例 ├── components # 组件 │ ├── Header │ └── Layout ├── pages # 页面 │ ├── _app.tsx │ ├── index.tsx │ ├── posts │ │ ├── [slug].tsx │ │ └── index.tsx │ └── tagged │ └── [tag].tsx ├── prisma # 数据库模型 │ ├── schema.prisma │ └── seeds.ts ├── public # 公共资源 ├── src # 服务端渲染代码 │ ├── db.ts │ ├── index.ts │ ├── lib.ts │ ├── models # 数据库模型定义 │ └── utils.ts └── styles # 样式
数据库设计
我们需要用到三个数据库表:Posts
、Tags
和 PostTags
。
Posts 表
Posts
表用于存储博客文章的内容:
// javascriptcn.com 代码示例 model Post { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt title String slug String @unique content String summary String? tags PostTag[] }
Tags 表
Tags
表用于存储文章的标签:
model Tag { id Int @id @default(autoincrement()) name String posts PostTag[] }
PostTags 表
PostTags
表用于存储文章和标签的关联关系:
model PostTag { id Int @id @default(autoincrement()) postId Int tagId Int post Post @relation(fields: [postId], references: [id]) tag Tag @relation(fields: [tagId], references: [id]) @@unique([tagId, postId]) }
数据库操作
接下来,我们需要使用 Typeorm 和 Prisma 来操作数据库。
Typeorm 数据库连接
在 src/db.ts
中,我们需要配置 Typeorm 的数据库连接:
// javascriptcn.com 代码示例 import "reflect-metadata" import { createConnection, Connection } from "typeorm" let connection: Connection | null = null export async function connectDatabase(): Promise<Connection> { if (connection && connection.isConnected) { return connection } connection = await createConnection({ type: "postgres", host: process.env.DATABASE_HOST || "localhost", port: parseInt(process.env.DATABASE_PORT || "5432", 10), username: process.env.DATABASE_USERNAME || "postgres", password: process.env.DATABASE_PASSWORD || "postgres", database: process.env.DATABASE_NAME || "blog", entities: ["src/models/**/*.ts"], migrations: ["src/migration/**/*.ts"], migrationsRun: process.env.NODE_ENV === "production", synchronize: process.env.NODE_ENV !== "production", logging: process.env.NODE_ENV !== "production", }) return connection }
该函数会根据环境变量,连接到数据库并返回数据库连接实例对象。
Prisma 查询
在 src/index.ts
中,我们需要编写博客网站的首页和文章详情页。同时,我们需要嵌套查询,获取文章和标签的关联关系。
// javascriptcn.com 代码示例 import { NextApiRequest, NextApiResponse } from "next" import { PrismaClient, Post } from "@prisma/client" export default async function handler( req: NextApiRequest, res: NextApiResponse ) { if (req.method === "GET") { const prisma = new PrismaClient() const allPosts: Post[] = await prisma.post.findMany({ include: { tags: { select: { name: true }, }, }, orderBy: [{ createdAt: "desc" }], }) res.status(200).json({ posts: allPosts }) } else { res.setHeader("Allow", ["GET"]) res.status(405).json({ message: `Method ${req.method} is not allowed` }) } }
在该代码中,我们使用 Prisma 查询数据库,获取所有博客文章和对应的标签。最后,我们使用 JSON 格式返回数据给前端。
Prisma 修改
在 src/index.ts
中,我们还需要编写和修改文章的功能。我们先编写新增文章的功能。
// javascriptcn.com 代码示例 import { NextApiRequest, NextApiResponse } from "next" import { PrismaClient, Post } from "@prisma/client" const prisma = new PrismaClient() export default async function handler( req: NextApiRequest, res: NextApiResponse ) { if (req.method === "POST") { try { const { title, slug, content, summary, tags } = req.body const postData = await prisma.post.create({ data: { title, slug, content, summary, tags: { create: tags.map((tag: string) => { return { name: tag } }), }, }, include: { tags: { select: { name: true }, }, }, }) res.status(201).json({ post: postData }) } catch (error) { res.status(500).json({ message: error.message }) } finally { await prisma.$disconnect() } } else { res.setHeader("Allow", ["POST"]) res.status(405).json({ message: `Method ${req.method} is not allowed` }) } }
在该代码中,我们先从前端传递过来文章的基本信息和标签,然后使用 Prisma 在数据库中创建文章。同时,按照标签信息,在标签表中创建标签,并在文章表中关联标签。最后,我们使用 JSON 格式返回新的文章数据给前端。
简单实现了新增文章的功能后,接下来我们需要编写编辑文章的功能。
// javascriptcn.com 代码示例 import { NextApiRequest, NextApiResponse } from "next" import { PrismaClient, Post } from "@prisma/client" const prisma = new PrismaClient() export default async function handler( req: NextApiRequest, res: NextApiResponse ) { if (req.method === "PUT") { try { const { postId, title, slug, content, summary, tags, } = req.body as { postId: number title: string slug: string content: string summary: string tags: string[] } const postData = await prisma.post.update({ where: { id: postId }, data: { title, slug, content, summary, tags: { deleteMany: {}, create: tags.map((tag: string) => { return { name: tag } }), }, }, include: { tags: { select: { name: true }, }, }, }) res.status(200).json({ post: postData }) } catch (error) { res.status(500).json({ message: error.message }) } finally { await prisma.$disconnect() } } else { res.setHeader("Allow", ["PUT"]) res.status(405).json({ message: `Method ${req.method} is not allowed` }) } }
在该代码中,我们从前端传递来了文章的基本信息和标签,并按照事务方式处理了删除和新增标签。最后,我们使用 JSON 格式返回更新的文章数据给前端。
总结
本文介绍了如何使用 Next.js + Typeorm + Prisma 技术栈,快速搭建一个高效的博客网站,并详细讨论了常见的前端开发问题和解决方案。希望本文能够为大家的前端开发提供帮助和指导。完整的示例代码可以在我的 GitHub 仓库中找到:https://github.com/terryzql/today-i-learned/tree/main/nextjs-blog。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/654b17cc7d4982a6eb50eda2