对 TouchGal 网站开源项目的介绍以及如何部署项目上线

Webtouchgal部署网站
浏览数 - 402发布于 - 2025-06-21 - 07:26
鲲

5988

基本情况

本文旨在介绍 TouchGal 的技术架构,部署方式,常见问题,需要注意的使用事项

这对有建站想法,打算使用这个项目作为模板的朋友很有帮助

如果有朋友要使用该项目建站,我会提供直到项目成功被启动程度的支持

我不是 TouchGal 的站长,与 TouchGal 团队无关,我是 TouchGal 这个开源项目的贡献者

  1. 该项目目前的 GitHub 地址为 https://github.com/KUN1007/kun-touchgal-next ,该项目所有权属于 TouchGal
  2. TouchGal 项目目前部署于 www.touchgal.io
  3. 项目可以改动,更改项目需要一定的 React 和 Node.js server 基础
  4. 项目遵循 AGPL 3.0 开源协议,进行任何的二次更改分发需注明原作者和仓库,并开源
  5. 项目为 Node.js 技术栈,使用的框架为 Next.js,建议使用的 Node.js 版本为 Node 22
  6. 建议在服务器安装 NVM 以管理 Node.js 的版本,必须使用 pnpm
  7. 项目使用 PostgreSQL 作为数据库,性能完爆 MySQL,服务器需要安装 PostgreSQL 环境
  8. 项目使用 PM2 作为部署手段,需要安装 PM2
  9. 项目使用 Redis 作为缓存,需要安装 Redis
  10. 项目的 /posts 文件夹为 /doc 目录的文档,需要查看如何编写 matter 和 MDX
  11. 第一次初始化完成后,项目部署时理论上只需要执行一个指令 pnpm deploy:build

下面的所有文章都围绕项目的部署展开,下面的安装假设您使用 Linux,如果是本地开发您可以随意选择操作系统

我需要学习,如果有朋友了解网站运维相关的知识,也可以指出我的错误或者可以改进的地方,提出更好的建议

环境准备

目前来说,TouchGal 是一个由 Next.js 编写的网站项目,因此在开始之前需要安装 Node.js,Redis,PostgreSQL,PM2 的环境,如果已有环境可以直接跳过

Node.js

要安装 Node.js,这里我们首先推荐安装 NVM,NVM 是 Node.js 版本管理工具

由于 Node.js 版本很多,有些版本之间不兼容,使用 NVM 是一个很好的选择

由于 NVM 存在一些问题,比如硬链接的问题,这里放出一个新的 Rust 编写的 Node.js 版本管理工具,由于我的电脑中已经有 NVM,所以并没有尝试过,感兴趣的朋友可以试试

https://github.com/Schniz/fnm

安装过程不赘述因为网上都有,安装完成后是这样的,版本号可能不一样

202501191309905.png接着使用 nvm install 22 命令,安装 Node.js 22 版本,安装完成后会自动使用 Node.js 22,可以使用 node -v 命令查看当前 Node.js 的版本

202501191311575.png严重注意,对于目前的项目来说,这里一定要确保 Node.js 的版本为 22,后面的 13.0 不重要,这会影响到项目的构建

使用 npm i -g pnpm 来安装 pnpm,然后使用 pnpm add -g pnpm 来将 pnpm 更新到最新版,然后可以使用 pnpm --version 来查看 pnpm 的版本,只要是大版本 9 以上都可以

202501191313220.png截止到这里,服务器已经具备了 Node.js 环境

Redis

redis 一般被用作缓存,这在存储一些具有 TTL 需求的数据时非常有用,它还可以被用来做网站的数据缓存,速率限制等等一系列功能

网上有大量的 redis 的安装过程,这里不再叙述,这不是本文的目的

安装完成后可以使用 redis-server --version 命令查看当前 redis 的版本,版本可能不同

使用 systemctl status redis 查看当前 redis 的运行状态,应该为 Active

202501201414172.png此时已经完成 Redis 的安装

PM2

PM2 的一个 Node.js 的进程管理器,它是用来托管处理项目构建好的 server.js 文件的,它有一系列良好的特性比如查看进程状态,启动和停止进程等等

PM2 较为轻量,按照目前 TouchGal 的需求,应该用不到 docker / k8s ,所以一个轻量的 PM2 server 就可以了

如果您本地有 Docker 环境,可以自行编写一个 compose 文件后启动,入口文件为 ./.next/standalone/server.js

前面我们安装了 Node.js + pnpm 环境,现在安装 pm2 只需要运行 pnpm i -g pm2 即可

安装完成后使用 pm2 -v 来查看当前 pm2 的版本,版本可能不同

image.png此时 PM2 安装完成

PostgreSQL

安装过程不再赘述,网上都有,密码复杂程度可以根据自己的情况设置,简单一点纯数字都可以(倘若你使用 gpg private key 来访问 server 而不是使用密码)

使用 psql -U postgres,然后输入密码,可以进入 PostgreSQL,版本号可能不同。输入 CREATE DATABASE touchgal; 按下回车以创建 touchgal 数据库

使用 \l 命令来查看当前服务器中所有的数据库,以确认 touchgal 数据库存在(\l 命令使用后按下 q 键退出)。 也可以使用 \c touchgal 切换到 touchgal 数据库,因为项目使用的数据库名为 touchgal,以确认 touchgal 数据库被创建成功

使用 \q 命令退出 PostgreSQL

202501201429420.png此时已经完成 PostgreSQL 配置

初始化项目

环境配置我们已经完成了,现在我们要做的工作是让项目在我们配好的环境中运行起来

从 GitHub clone 项目并初始化

使用 git clone https://github.com/KUN1007/kun-touchgal-next 来将 GitHub 仓库 clone 到服务器的当前文件夹,然后 cd kun-touchgal-next 进入项目根目录,运行 pnpm i 安装项目依赖

202501191400355.png配置项目环境变量,在项目根目录有一个 .env.example 文件,根据这个文件的变量名,在项目根目录新建一个 .env 文件,然后按照 .env.example 的格式编写 .env 文件

// 前面我们已经创建了 touchgal 数据库,这里填写你的数据库密码
KUN_DATABASE_URL = "postgresql://postgres:<你的数据库密码>@localhost:5432/touchgal?schema=public"

// 你的网站带 https 的域名
KUN_VISUAL_NOVEL_SITE_URL = "https://www.touchgal.io"

// 这里两个都填你的网站带 https 的域名
// 如果是开发环境,应该将 NEXT_PUBLIC_KUN_PATCH_ADDRESS_DEV 改为 http://127.0.0.1:3000
NEXT_PUBLIC_KUN_PATCH_ADDRESS_DEV = "https://www.touchgal.io"
NEXT_PUBLIC_KUN_PATCH_ADDRESS_PROD = "https://www.touchgal.io"

// redis 的默认地址和端口, 一般不用改动
REDIS_HOST = '127.0.0.1'
REDIS_PORT = '6379'

// JWT 的签发和 JWT 的私钥(JWT_SECRET),签发不用管,私钥应该尽可能复杂
JWT_ISS = 'touchgal'
JWT_AUD = 'touchgal_admin'
JWT_SECRET = 'KUFJ6:?./lD@P?IKP:IE$^FL.Y%WS2~_)7123'

// Node.js 环境,这里应该改为 NODE_ENV = "production"
NODE_ENV = "development"

// 邮箱功能配置
KUN_VISUAL_NOVEL_EMAIL_FROM = "TouchGal"
KUN_VISUAL_NOVEL_EMAIL_HOST = "mail.moyu.moe"
KUN_VISUAL_NOVEL_EMAIL_PORT = '587'
KUN_VISUAL_NOVEL_EMAIL_ACCOUNT = "[email protected]"
KUN_VISUAL_NOVEL_EMAIL_PASSWORD = "jyf?>FDm莲最可爱!"

// S3 相关配置,需要改为你自己的
// 目前来讲,这个项目的图片和上传的文件都在同一个服务商,这里可以根据自己的需求填写
// access key id
KUN_VISUAL_NOVEL_S3_STORAGE_ACCESS_KEY_ID = "005axxxxxxxxxxxxxx0000000006"
// secret key
KUN_VISUAL_NOVEL_S3_STORAGE_SECRET_ACCESS_KEY = "K005JYED./YEDIY%DCT/xdc6dc"
// 存储桶名
KUN_VISUAL_NOVEL_S3_STORAGE_BUCKET_NAME = "touchgal"
// endpoint
KUN_VISUAL_NOVEL_S3_STORAGE_ENDPOINT = "https://s3.us-east-005.backblazeb2.com"
// region
KUN_VISUAL_NOVEL_S3_STORAGE_REGION = "us-east-005"
// 项目可以不使用 S3 API,但是相应的用户将无法传文件
// s3 的URL,比如 static.touchgal.io
KUN_VISUAL_NOVEL_S3_STORAGE_URL = "https://touchgal-patch.moyu.moe"

// reCAPTCHA 网站 key
NEXT_PUBLIC_KUN_RECAPTCHA_SITE_KEY = "6LfI-7UqAAAAAF_mAyYnkLtP9IO6bEo7VvjlreSI"
// reCAPTCHA secret key
KUN_RECAPTCHA_SECRET_KEY = "6LfI-7UqAAAAANzJalyOVYMzhfcfL8Z_rrLyOuva"

// 图床域名,不带 https
KUN_VISUAL_NOVEL_IMAGE_BED_HOST = "touchgal-image.moyu.moe"
// 图床域名,带 url
KUN_VISUAL_NOVEL_IMAGE_BED_URL = "https://touchgal-image.moyu.moe"

// 如果你使用 Cloudflare 的 cache control,不使用则留空
KUN_CF_CACHE_ZONE_ID = ""
// 这个 Token 用来清除图片缓存,可以自行创建一个,权限只给 purge cache 即可
KUN_CF_CACHE_PURGE_API_TOKEN = ""

// 这里要再生成一个 32 位的字符串,仅能含有数字和英文字符
// 生成后将项目 public/a7xmyp2ob6kst9bkkdt2hnhj04rpctzd.txt 文件改为你自己的字符串
// 这个文件中的内容也改为这个值
KUN_VISUAL_NOVEL_INDEX_NOW_KEY = "a7xmyp2ob6kst9bkkdt2hnhj04rpctzd"

// 测试网站配置,用于测试环境,生产环境建议此项为空字符串
// 如果值为 noindex 则全站不会被任何搜索引擎索引
KUN_VISUAL_NOVEL_TEST_SITE_LABEL = ""

填写完成 .env 文件后保存 .env 文件,此时,项目根目录应该有一个 .env 文件

202501201401772.png确认 .env 文件存在后,使用 pnpm deploy:install 命令运行一个项目初始化脚本

202501201408999.png此时项目初始化完成

连接 PostgreSQL

使用 psql -U postgres,然后输入密码,可以进入 PostgreSQL

输入 \c touchgal 切换到 touchgal 数据库。使用 \dt 查看数据库 touchgal 中有哪些表,确认刚才运行项目的时候已经将表创建成功了

使用 \q 命令退出 PostgreSQL

202501201427983.png此时已经连接完成

部署网站上线

使用 pnpm deploy:build 来运行生产环境的构建脚本,构建完成后项目会运行在服务器本地的 127.0.0.1:3000 端口,可以将这个端口部署到域名

部署过程这里不再赘述,部署网站的手段太多了

这里建议使用 Tunnel、Nginx、Caddy、Pingora 等工具部署,本网站涉及到 fs 操作,因此类似于 Vercel,Netlify 这样的部署供应商是没有办法部署这个项目的

可能必需需要一个服务器,但是或许会有支持 fs 的部署供应商,这一点我不明确

部署完成后,此时理论可以从你的域名中访问网站

创建用户并设置超级管理员

访问网站,到网站的注册页面注册一个用户,建议给 UID 为 1 的用户超级管理员

切换到服务器中,使用 psql -U postgres,然后输入密码,可以进入 PostgreSQL

输入 \c touchgal 切换到 touchgal 数据库

使用 UPDATE "user" SET role = 4 WHERE id = 1; 这个 SQL 语句将 ID 为 1 的用户设置为超级管理员

系统规定,role 字段为 1 的用户是普通用户,2 为创作者,3 为管理员,4 超级管理员

注意,这里的 UID 为 1 的用户就是上面注册的那个用户

202501191325666.png重新进入网站刷新页面,应该已经可以在用户 1 的主页看到用户 1 变为了超级管理员

注意事项

我们已经将网站部署完成,现在开始我们需要深刻讲解一些注意事项,请在维护时务必注意这些注意事项,这涉及到项目的安全和稳定运行

确保项目符合规定

您运行的项目需要遵守您服务提供商、域名提供商等的规定,否则极有可能会导致服务被下架

您运行的项目需要遵守 Google 以及 Bing 等搜索引擎提供的 Guidelines,否则整个网站可能会被取消索引

您运行的项目需要符合您当地的法律法规,在不同地区运行和维护本项目有可能导致不良的法律效应

如果您对项目进行二次改动,需要遵守 AGPL 3.0 开源协议,需注明原作者和仓库,并开源

编写项目 /doc 目录的 MDX 文件

本项目使用 MDX 作为网站 Blog 编写格式,区别于 Markdown 的地方就是可以在 MDX 文件里面写 tsx / jsx,如果用不到这些高级功能可以不用管

本项目目前的 matter 属性是这样的

---
title: 鲲 Galgame 补丁开发文档
banner: '/posts/dev/documentation/banner.avif'
description: '鲲 Galgame 补丁的开发技术栈为 Next.js 15 + Prisma + PostgreSQL'
date: 2024-12-08
authorUid: 2
authorName: '鲲'
authorAvatar: 'https://image.moyu.moe/user/avatar/user_2/avatar-mini.avif'
authorHomepage: 'https://github.com/KUN1007'
pin: false
---

banner 属性的文章的头图,可以使用 https url 的链接,也可以使用相对路径静态文件资源的链接,将图片文件托管在项目的目录中。我这里,会将项目的 public 目录解析为文章中静态资源的根目录,这里的 '/posts/dev/documentation/banner.avif' 的位置就在项目的 public 文件夹下对应的位置

description 属性严重影响到 /doc 目录的 SEO,建议填写 170 字左右

date 是文字发布的日期,authorUid 就是文章发布者的 UID,就是用户主页路径里的数字,一般填写自己的就可以,下面两个也是一样的

pin 属性指明了这个文章是否会被在主页的走马灯(轮播图)组件中置顶

项目的 posts 目录存放了当前所有的文章,posts 目录的结构就对应着 /doc 页面的目录结构

202501201516697.png然后页面的路径就会是这样的

202501201516857.png页面中的目录映射了 posts 文件夹的目录结构

202501201521601.png目录的名称映射文件在项目的 contants/doc.ts 文件中,当你新建目录的时候应该同步更新这个文件的目录名称映射

202501201520917.png默认这些目录都是折叠的,如果要使这些目录默认展开,请更改项目 /components/doc/SideTreeItem.tsx 文件

const [isOpen, setIsOpen] = useState(false)

将这一行更改为

const [isOpen, setIsOpen] = useState(true)

如何添加友情链接

在项目的 config/friend.json 文件中编写对应的信息即可

202501201523203.png填好之后运行 pnpm deploy:build 来重新构建项目以生效

如何配置网站的信息

网站的信息目前已经配置好,如果需要更改,则必须更改 config/moyu-moe.ts 文件

import { SUPPORTED_TYPE_MAP } from '~/constants/resource'
import type { KunSiteConfig } from './config'

const KUN_SITE_NAME = 'TouchGal'
const KUN_SITE_MENTION = '@touchgal'
const KUN_SITE_TITLE = 'TouchGal - 一站式Galgame文化社区!'
const KUN_SITE_IMAGE =
  'https://img.touchgalstatic.org/uploads/20241217174250074.avif'
// description 涉及到网站 SEO,建议编写 170 字左右
const KUN_SITE_DESCRIPTION =
  'TouchGal 是一个一站式 Galgame 文化社区'
const KUN_SITE_URL = 'https://www.touchgal.io'
const KUN_SITE_ARCHIVE = 'https://archive.touchgal.co/'
const KUN_SITE_FORUM = 'https://bbs.touchgal.co/'
const KUN_SITE_NAV = 'https://gal.red'
const KUN_SITE_TELEGRAM_GROUP = 'https://s.miku.cyou/2'
const KUN_SITE_DISCORD_GROUP = 'https://discord.gg/e4QePvPQTB'
const KUN_SITE_LIST = [
  { name: KUN_SITE_NAME, url: 'https://www.touchgal.net' },
  { name: KUN_SITE_NAME, url: 'https://www.touchgal.moe' },
  { name: KUN_SITE_NAME, url: 'https://www.touchgal.one' },
  { name: KUN_SITE_NAME, url: 'https://www.touchgal.com' },
  { name: KUN_SITE_NAME, url: 'https://www.touchgal.org' },
  { name: KUN_SITE_NAME, url: 'https://www.touchgal.me' },
  { name: KUN_SITE_NAME, url: 'https://www.touchgal.co' }
]
const KUN_SITE_KEYWORDS = [
  'TouchGAL',
  'Gal',
  'Galgame',
  '论坛',
  '网站',
  'Galgame 下载',
  'Galgame 资源',
  'Galgame wiki',
  'Galgame 评测',
  'Galgame 数据分析',
  'Galgame 新作动态',
  'Galgame 汉化 / 国际化',
  'Galgame 制作',
  'Galgame 讨论',
  '游戏交流',
  '其他交流',
  ...Object.values(SUPPORTED_TYPE_MAP)
]

export const kunMoyuMoe: KunSiteConfig = {
  title: KUN_SITE_TITLE,
  titleShort: KUN_SITE_NAME,
  template: `%s - ${KUN_SITE_NAME}`,
  description: KUN_SITE_DESCRIPTION,
  keywords: KUN_SITE_KEYWORDS,
  canonical: KUN_SITE_URL,
  author: [
    { name: KUN_SITE_TITLE, url: KUN_SITE_URL },
    { name: KUN_SITE_NAME, url: KUN_SITE_NAV },
    ...KUN_SITE_LIST
  ],
  creator: {
    name: KUN_SITE_NAME,
    mention: KUN_SITE_MENTION,
    url: KUN_SITE_URL
  },
  publisher: {
    name: KUN_SITE_NAME,
    mention: KUN_SITE_MENTION,
    url: KUN_SITE_URL
  },
  domain: {
    main: KUN_SITE_URL,
    imageBed: 'https://img.touchgalstatic.org',
    storage: KUN_SITE_URL,
    kungal: KUN_SITE_URL,
    telegram_group: KUN_SITE_TELEGRAM_GROUP,
    discord_group: KUN_SITE_DISCORD_GROUP,
    archive: KUN_SITE_ARCHIVE,
    forum: KUN_SITE_FORUM,
    nav: KUN_SITE_NAV
  },
  og: {
    title: KUN_SITE_TITLE,
    description: KUN_SITE_DESCRIPTION,
    image: KUN_SITE_IMAGE,
    url: KUN_SITE_URL
  },
  images: [
    {
      url: KUN_SITE_IMAGE,
      width: 1000,
      height: 800,
      alt: KUN_SITE_TITLE
    }
  ]
}

暂时仅建议更改这里的信息,不要更改 config 下除了 friend.json 与 moyu-moe.ts 之外的其它文件

由于最初的设计问题,没有为这个文件中所有的网站 URL 统一 trailing slash,因此不要更改 URL 后面的 /,例如去掉所有 URL 后面的 /

网站数据库备份

仅需备份网站的数据库即可,如果你本地有 GUI 的数据库软件可以使用 ssh 连接到服务器的数据库备份,没有的话可以按照下面的步骤进行操作

  1. 在服务器上运行

    pg_dump -h localhost -p 5432 -U postgres -d touchgal -n public
    > -F c -b -v -f touchgal_backup.dump
    

    这会在当前目录生成一个 touchgal_backup.dump 文件,这就是你数据库的 dump 文件

    PostgreSQL 在安装时会自动安装 pg_dump 工具,一般不需要你手动安装

  2. 将这个文件 clone 到你本地的机器上,我假设你使用 scp 命令,或者其它的手段

    scp -i C:\Users\kun.ssh\kungalgame_rsa -P 22 -r
    > root@<你的服务器 ip>:/home/kun/kun-galgame/kun-touchgal-next/backup/touchgal_backup.dump
    > E:\backup\touchgal
    
  3. 然后可以使用这个 dump 文件在任何地方恢复数据库

  4. 项目目前没有自动备份的脚本,未来可能会有

关于项目的构建

每次当你对项目做了任何更改,必须重新在服务器的项目根目录运行一遍 pnpm deploy:build 命令,这会将你的更改应用到项目中,并重新构建项目

构建过程一般在 1 ~ 2 分钟,这个期间网站会有部分功能不可用,正在访问网站的用户不会受到影响

构建完毕之后服务器需要将新生成的文件读取到到内存,CDN 和用户浏览器的缓存也需要刷新,网站速度会短暂变慢直到 CDN 和用户浏览器的缓存与服务器同步

严重警告

如果你在运行 pnpm deploy:build 或者运行任何其它命令的时候,看到下面的提示消息

⚠️ We found changes that cannot be executed:
× To apply this change we need to reset the database, do you want to continue? 
All data will be lost. ... no

202501201608708.png这时,必须连按两下 Ctrl + c 中断操作,或者输入 n 以取消操作

千万不要按 y 或者回车,否则,数据库中的所有数据会被全部重置,不可能还原,如果没有备份将会倾家荡产,非常严重

这个是使用 prisma 造成了对数据库不可逆的更改造成的,一般不会有这种情况,如果有的话请联系我

一些重要的地方说明

  1. 自行修改项目代码造成的任何不良后果需要自行承担

  2. 网站的 NSFW 文章,用户主页等已经彻底阻止搜索引擎索引,这些文章将会 0 SEO 甚至反 SEO,不会对其它页面产生影响

  3. 项目占用服务器磁盘空间很少,目前算上依赖大约在 1.6g 左右

  4. 项目的 uploads 文件夹是用户上传的临时文件,因为怕有的用户上传一半不传了或者传了不发布产生死文件。项目每过 1h 会自动扫描一遍项目中的 uploads 文件夹,删除超过 1 天的死文件

  5. 项目占用服务器的内存取决于网站的访问量以及项目的实例数,理论上 300k ~ 400k 月独立 ip 数的网站,使用 pm2 部署,按照目前的配置可以流畅运行,内存占用在 700MB 左右

    注意我们目前的配置是单实例运行的,支撑一个 20k 日独立 ip 小网站应该绰绰有余了

  6. 如果觉得网站速度还是不够,可以多开几个实例,实例数取决于服务器的核数,pm2 会利用服务器的核数自动负载均衡,目前只开了一个实例。例如 16 核服务器可建议开 16 个实例,项目会自动进行负载均衡,但是同时项目对服务器的内存占用也会变成 700MB * 16

    可以自己开,不过需要做好相关的风险准备,因为可能需要重启一下 pm2,如果自己开遇到问题可以联系我

    开多实例的方法就是更改项目根目录的 ecosystem.config.js 文件

    module.exports = {
      apps: [
        {
          name: 'kun-touchgal-next',
          port: 3000,
          cwd: '.',
          instances: 1,
          autorestart: true,
          watch: false,
          max_memory_restart: '1G',
          script: './.next/standalone/server.js'
        }
      ]
    }
    

    可以把这里的 instances 数量改为对应您服务器核数的数字,比如您划出了一个 4c8g 的小鸡,可以把 instances 改为 4,6c12g 则可以把 instances 改为 6

  7. PM2 的性能在单服务是完美碾压 docker 的,如果感觉性能不够,可以自行迁移到 docker 进行集群部署。docker 会损失一些性能,但是项目理论上可以做到无畏并发,就目前的人数来讲远远用不到集群部署

  8. 如果遇到任何网站问题,可以前往 GitHub 仓库 发 issue 或者直接联系我,项目虽然已经经历了半年以上的、多个网站的实际运行,找到了很多 BUG,但是未知的 BUG 肯定还是存在的

对于本项目特性的一些说明

本项目的开发技术栈为

核心: Next.js + Prisma + PostgreSQL + PM2 + Cloudflare Tunnel + S3 Object Storage

详细

Next.js 15, React 19, Node.js, AWS S3 API, S3 Object Storage, HeroUI, Prisma ORM, Argon2, BLAKE3, Framer Motion, Redis, Sharp, Unified.js, Milkdown, Zod, Zustand, PM2, Cloudflare Worker, Cloudflare CDN, Cloudflare Tunnel

由于有很多技术栈都有自己的特性,在这里需要进行解释以免引起误会

Next.js

Next.js 并不是特别高大上的技术,但是就目前实际使用的情况来讲,性能肯定是比 WordPress 好一大截的

目前的实际情况是 1c 2g 的机器可以轻松运行一个月活 50w 的网站

Next.js 是第一个大规模、生产级落地并深度集成 React Server Components (RSC) 的框架,并且目前仍然是 RSC 框架中最成熟、最知名的实现,其它的还有 waku 等,Remix 好像还没支持(不是因为支持不了,可能是它比 RSC 性能更好 ,不过这个文章写的时候是 21 年, RSC  It's still experimental! I'm just saying they aren't compelling for Remix right now.)

在日常的网站请求中,您或许会看到这样的请求

image.png这不是项目的 BUG,这是 Next.js 的特性

项目构建后的产物文件夹为 ./next/standalone 这个文件夹,理论上可以将这个文件夹拿出来单独部署

本项目几乎都用了 fetch 而不是 server actions,这有些不符合 Next.js 的设计理念和最佳实践,这是本项目最大的缺点之一,期待迎来重构的那一天

Next.js 学习曲线比较陡峭,请尽可能多的阅读官方文档再进行开发,否则非常容易被坑就像上面这种情况一样

S3 Object Storage

对象存储在本项目中被用来作为文件服务和图床,这里的 S3 并非真的去买 AWS S3,那能把你家房吞掉的

S3 是一种 API 设计规范,大概是用来定义 Web 和对象存储交互的方法的,不是只有 AWS 一家 S3

这里推荐采用 BackBlaze(B2)的对象存储,如果你觉得 R2 更好也可以用 R2 或者其它对象存储

B2 使用 Cloudflare 的 CDN 是可以免去流量的,因为有带宽联盟,前不久阿里云也接入了带宽联盟,具体的操作细节可以查看

使用 Cloudflare Workers 实现 B2 私有存储桶文件下载

Redis

本项目依赖于 Redis,但是不是持久化数据依赖

这也就是说,如果您需要迁移服务器,可以不迁移 Redis 中的 key-value(但是 PostgreSQL 必须迁移)

不迁移的后果是网站的所有用户都需要重新登录,并且网站的被封禁用户黑名单失效

如果您在意这些后果,也可以迁移 Redis

LLM

如果您使用 Claude、Gemini、GPT 等 LLM 来更改代码,请务必关注下面几个文件

  1. schema.prisma。这是本项目的数据库 schema 文件,更改数据库的后果是比较严重的,尤其是更改和删除字段,需要让 LLM 再三思考,真的可以改吗,否则极易阵亡。
  2. verifyKunCaptcha.ts。与验证有关的文件,captcha、jwt、redis 等。这些验证的逻辑都较为综合并且无处不在,更改时需要注意更改之后对网站整体行为造成的影响,否则会产生安全漏洞甚至网站瘫痪。
  3. milkdown。Milkdown 是编辑器,在网站进行任何富文本渲染时,都需要进行两到三次的 xss 过滤,对 Milkdown 的任何更改务必小心,如果要自己造编辑器就更加小心。LLM 是写不了编辑器的,功能估计会很蹩脚,如果要大改建议换为 TipTap 等参考案例较多的编辑器,便于 LLM 生成结果,换为 TipTap 这样的 HTML 编辑器后需要重写所有的渲染逻辑。
  4. next.config.ts。Next.js 坑点很多,目前来说改这个文件之后需要经过细致的测试,以免出现意料之外的问题。

这之外应该没有什么大问题,至多可能会造成性能损失和极低的代码可读性,这些都不是大问题。

重新编辑于 - 2025-06-21 - 07:28

#1

肥肠滴详细啊,赞Sticker

2025-06-21 - 07:45
鲲

5988

#2

Sticker

2025-06-21 - 08:26

评论

银发教主
银发教主评论

话说论坛(不是补丁站)进入后,首页里显示的帖子列表,刷新上是不是出了什么问题? 感觉新回复的帖子不会被刷新上来,最后回复是两天前的帖子却一直在首页上,第一印象就感觉论坛回帖人很少的错觉。 然后要看最新回复的贴,还要手动点最新话题>查看更多 >才能看得到,稍稍有些麻烦?

鲲
评论银发教主

因为前一段时间改了一下逻辑,只有一个月内发布的话题才会出现在首页 emmm,现在来看确实效果不是很好,感谢反馈!明天我去修一下

鲲
评论银发教主

已经变更了首页话题的展示行为,现在首页的话题满足任意一点即可 1. 发布时间小于三个月 2. 话题内容更新时间小于三个月 这两种类型的话题收到回复、评论、推时,会在首页置顶

#3

虽然是Web低手,但是先star+fork了先Sticker

2025-06-21 - 09:05 (已编辑于 2025-06-21 - 09:05)
kohaku