基于Next.js与Nest.js构建现代化个人CMS:Wipi全栈开发与部署实战
2026/5/6 11:43:08 网站建设 项目流程

1. 项目概述:从零构建一个现代化的个人内容管理系统

如果你和我一样,厌倦了臃肿的WordPress,又觉得静态博客生成器在内容管理上不够灵活,总想找一个既能自己掌控所有数据,又具备现代技术栈和良好开发体验的CMS,那么Wipi这个项目绝对值得你花时间研究一下。它是一个面向个人开发者的开源CMS系统,核心功能涵盖了文章发表、页面创建,甚至还有类似“知识小册”这样的专栏功能。技术选型上,它采用了Next.js作为前端,Nest.js构建后端服务,MySQL存储数据,再用阿里云OSS处理文件,算是一个相当“时髦”和“全栈”的组合拳。

我第一次在GitHub上看到Wipi时,就被它清晰的模块划分和完整的后台管理界面吸引了。它不像很多玩具项目只做个前端,而是从前台展示、后台管理到服务端API,一整套都给你搭好了。对于想深入学习全栈开发,或者希望拥有一个完全自定义、数据私有的内容发布平台的朋友来说,直接基于Wipi进行二次开发,比自己从零造轮子要高效得多。接下来,我会结合自己的部署和踩坑经验,带你深入拆解Wipi的架构设计、核心功能实现,并分享一套从本地开发到生产环境部署的完整实操指南。

2. 技术栈深度解析与选型逻辑

2.1 为什么是Next.js + Nest.js?

Wipi选择Next.js和Nest.js作为前后端框架,背后有非常务实的考量。这不是简单的技术堆砌,而是为了应对现代Web应用在开发效率、性能体验和架构清晰度上的综合需求。

Next.js:服务端渲染(SSR)与静态生成的平衡作为前端,Wipi需要良好的SEO和首屏加载速度。传统的React单页应用(SPA)在这两点上存在短板。Next.js的核心价值在于它提供了混合渲染能力。对于博客首页、文章详情页这类对SEO和打开速度要求高的页面,Wipi可以轻松配置为服务端渲染(SSR)或静态生成(SSG)。这意味着用户请求页面时,服务器直接返回渲染好的HTML,而不是一个空白的<div id=”root”>等待JavaScript加载并执行后再渲染。实测下来,这对博客的搜索引擎收录和用户感知速度的提升是立竿见影的。

此外,Next.js内置的路由、API Routes(虽然Wipi没用到,因为后端独立了)、图片优化等特性,极大地减少了前端工程的配置复杂度。它的文件即路由约定,也让项目结构非常清晰,对于内容型站点来说非常友好。

Nest.js:面向切面编程(AOP)的企业级后端如果说Next.js解决了前端的体验问题,那么Nest.js就是来解决后端架构的可持续性问题的。Nest.js深受Angular设计思想的影响,强制使用模块化、依赖注入和装饰器,这在一开始可能会觉得有点“重”,但对于一个可能长期维护、功能不断增多的CMS系统来说,这种约束是福音。

Wipi的后端需要处理用户认证、文章CRUD、评论管理、文件上传、邮件发送等一系列复杂且相互关联的业务。Nest.js的模块系统能让这些功能以ArticleModuleUserModuleCommentModule的形式清晰地组织起来。它的拦截器、过滤器、管道等特性,可以优雅地统一处理请求日志、异常响应、参数验证等横切关注点。例如,用一个全局的ValidationPipe就能自动校验所有接口的入参DTO,省去了大量重复的校验代码。这种结构化的开发模式,保证了即使项目规模增长,代码也不会变成难以维护的“意大利面条”。

MySQL:关系型数据的可靠选择对于CMS系统,数据之间的关系是明确的:用户撰写文章,文章拥有分类和标签,文章下有评论。这种强关系模型非常适合用关系型数据库来建模。MySQL的成熟度、稳定性和丰富的查询功能(如复杂的联表查询)使其成为不二之选。Wipi使用utf8mb4字符集创建数据库,这确保了可以完美存储Emoji表情和任何生僻字,避免了常见的乱码问题。

阿里云OSS:专业化的文件存储解耦将用户上传的图片、附件等静态资源直接存在应用服务器上,会带来磁盘空间管理、备份困难、访问速度慢等一系列问题。引入对象存储服务(如阿里云OSS)是必然选择。OSS不仅提供了海量、安全、高可用的存储空间,其配套的CDN加速能力更能让全国乃至全球的用户快速加载图片。Wipi将文件管理功能抽象出来,通过后端服务对接OSS,前端直接获取OSS的访问链接,实现了应用与静态资源的彻底解耦,架构上更加清晰和可扩展。

2.2 前端工程化:React与Sass的协作

Wipi的前端基于React构建,并使用了Sass作为CSS预处理器。这带来了组件化开发和样式管理上的巨大便利。

组件化开发与状态管理整个前台和后台界面都是由一个个React组件拼接而成。例如,文章列表页可能由ArticleList组件、Pagination分页组件、Sidebar侧边栏组件构成。这种开发模式复用性极高,维护起来也方便。虽然Wipi没有引入Redux或MobX这类重型状态管理库(对于CMS来说,React自身的状态和Context API可能已足够),但其组件设计为未来可能的复杂状态管理留出了清晰的接口。

Sass提升样式开发效率直接写CSS会遇到选择器嵌套复杂、变量无法复用、代码组织混乱等问题。Sass通过引入变量嵌套规则混入(Mixin)模块化导入等特性,极大地提升了样式代码的可维护性。在Wipi的源码中,你很可能看到类似_variables.scss的文件定义主题色、字体大小等变量,然后在各个组件样式中引用。这使得整个站点的视觉风格保持一致,并且调整起来只需修改一个变量值。

注意:在配置构建工具时,需要确保Sass编译器正确安装。Wipi使用pnpm作为包管理器,通常会在package.jsondevDependencies中声明sass包。如果运行时样式不生效,首先检查sass是否安装成功。

3. 核心功能模块拆解与实现原理

3.1 文章与页面管理系统

这是CMS的核心。Wipi将“文章”和“页面”做了区分,这是非常专业的设计。

文章管理文章通常具有时间属性,属于动态内容,会出现在文章列表、分类目录、时间归档中。Wipi的文章模型至少包含以下字段:标题内容(Markdown/富文本)摘要封面图分类ID标签数组作者ID发布时间状态(草稿/发布)等。 后端(Nest.js)会提供完整的RESTful API或GraphQL接口供前端(Next.js)调用,实现文章的增删改查。一个关键细节是内容存储格式。为了兼顾写作体验和渲染灵活性,很多现代CMS(包括Wipi)选择用Markdown格式存储原始内容,同时在数据库中保存一个由Markdown转换而来的HTML版本用于前端直接渲染,这样可以避免每次请求都进行实时转换,提升性能。

页面管理页面(如“关于我”、“友情链接”)通常是静态的、独立的,不参与文章流。它的模型更简单,主要是标题内容自定义路径(slug)等。Wipi为页面提供独立的管理入口和渲染路由,例如/about对应关于页面。在实现上,Next.js的动态路由功能(pages/[slug].js)可以很好地支持这种自定义页面的路由匹配。

3.2 知识小册:结构化内容组织

“知识小册”是Wipi的一个亮点功能,你可以把它理解为文章的合集或专栏。例如,你可以创建一个“React入门指南”小册,里面包含多篇系列文章。 其数据模型设计会包含小册表(记录标题、描述、封面等)和小册-文章关联表。前端界面需要提供小册的创建、文章拖拽排序、目录生成等功能。这对于创作系列教程或专题内容的博主来说,是一个非常实用的功能,能有效提升读者的阅读体验和内容的结构化程度。

3.3 评论与邮件子系统

评论管理一个完整的评论系统需要考虑多层嵌套回复、审核机制、反垃圾、通知作者等。Wipi的评论模块至少需要评论表,关联文章ID用户ID(或访客信息)、父评论ID(用于嵌套)、内容状态创建时间等。 在实现上,为了避免频繁查询数据库,常见的优化手段包括:

  1. 分层加载:首次只加载顶级评论,点击“查看回复”时再异步加载子评论。
  2. 缓存:对文章的评论总数、热门评论进行缓存。
  3. 防刷与审核:引入频率限制、敏感词过滤,并支持后台人工审核。

邮件通知当文章有新评论、用户注册时,系统需要发送邮件。Wipi的邮件管理模块通常会集成Nodemailer这样的库。配置关键在于.env文件中安全地设置SMTP服务商(如QQ邮箱、SendGrid、阿里云邮件推送)的服务器地址、端口、用户名和授权码(而非密码)。

实操心得:生产环境务必使用像SendGrid、Mailgun或国内各大云服务商的邮件推送服务,而不要直接用个人邮箱的SMTP。个人邮箱通常有日发送量限制,且容易被判为垃圾邮件。云邮件服务专为业务邮件设计,送达率和管理功能都强得多。

3.4 文件上传与OSS集成

这是涉及IO和安全的关键模块。流程通常是:

  1. 前端(如React组件)通过<input type=”file”>或拖拽上传获取文件对象。
  2. 前端将文件对象通过FormData发送到后端特定API(如POST /api/upload)。
  3. 后端(Nest.js)使用multer等中间件接收文件。
  4. 后端对文件进行安全检查(类型、大小、病毒扫描?),然后生成一个唯一文件名(防止覆盖)。
  5. 后端调用阿里云OSS的SDK,将文件流上传到指定的OSS Bucket。
  6. OSS返回文件的公开访问URL,后端将此URL存入数据库(关联到文章或用户),并返回给前端。

安全注意事项

  • 限制文件类型:只允许上传图片(image/jpeg, image/png)等安全类型。
  • 限制文件大小:防止超大文件攻击。
  • 重命名文件:不要使用用户上传的原文件名,避免脚本注入和覆盖攻击。
  • 图片处理:可以考虑在上传时或访问时,利用OSS的图片处理功能生成缩略图。

3.5 后台管理系统与权限控制

Wipi的后台管理是一个独立的Next.js应用(运行在3002端口)。它通过调用后端API来管理所有数据。其权限模型相对简单,从提供的默认账号(admin/admin)来看,初期可能主要区分“管理员”和“普通用户”(访客注册后可能只能管理自己的评论?)。更复杂的系统可以基于角色(RBAC)进行功能权限控制。 后台UI通常使用Ant Design或类似的企业级React UI组件库搭建,以快速实现表格、表单、模态框、图表等复杂交互界面。

4. 从零开始:本地开发环境搭建全记录

4.1 基础设施准备:MySQL与Node.js

假设你是在一台干净的Linux服务器或Mac/Windows本地进行开发。

1. 安装Docker并启动MySQL使用Docker是启动MySQL最快、最干净的方式,避免了本地安装的版本冲突和配置污染。

# 拉取MySQL 5.7镜像(兼容性好,Wipi已验证) docker pull mysql:5.7 # 运行MySQL容器 # -d: 后台运行 # --restart=always: 容器退出时自动重启 # --name wipi-db: 容器命名为wipi-db # -p 3306:3306: 将宿主机的3306端口映射到容器的3306端口 # -e MYSQL_ROOT_PASSWORD=your_strong_password: 设置root密码(务必修改!) # -v /your/local/path:/var/lib/mysql: 可选,将数据卷挂载到本地,防止容器删除后数据丢失 docker run -d --restart=always --name wipi-db -p 3306:3306 -e MYSQL_ROOT_PASSWORD=your_strong_password mysql:5.7 # 检查容器是否运行 docker ps | grep wipi-db

2. 创建数据库进入容器内的MySQL命令行,为Wipi创建专用的数据库和用户(出于安全,不建议直接用root)。

# 进入容器bash环境 docker exec -it wipi-db bash # 登录MySQL,密码是上面设置的your_strong_password mysql -u root -p # 在MySQL命令行中执行 CREATE DATABASE `wipi` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; # 创建一个专属用户,并授予其对wipi数据库的所有权限 CREATE USER 'wipi_user'@'%' IDENTIFIED BY 'another_strong_password'; GRANT ALL PRIVILEGES ON wipi.* TO 'wipi_user'@'%'; FLUSH PRIVILEGES; EXIT; # 退出容器bash exit

现在,你的MySQL已经就绪,地址是127.0.0.1:3306,数据库名wipi,用户wipi_user

3. 安装Node.js和pnpmWipi使用pnpm作为包管理器,它比npm/yarn更快,磁盘空间利用更高效。确保你的Node.js版本在16以上(推荐18 LTS)。

# 使用nvm管理Node.js版本(推荐) curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash # 重新打开终端或执行 source ~/.bashrc nvm install 18 nvm use 18 # 全局安装pnpm npm install -g pnpm # 验证安装 node -v pnpm -v

4.2 获取与配置Wipi源码

1. 克隆项目

git clone --depth=1 https://github.com/fantasticit/wipi.git my-wipi-blog cd my-wipi-blog

--depth=1只克隆最近一次提交,速度更快。

2. 安装依赖Wipi项目根目录下应该有一个package.json,它可能使用workspace管理前后端子项目。直接运行:

pnpm install

这个过程会安装前端(Next.js)、后端(Nest.js)的所有依赖。如果网络慢,可以配置淘宝镜像:pnpm config set registry https://registry.npmmirror.com

3. 配置环境变量项目根目录下找到.env.example或直接创建.env文件,填入你的配置。这是最关键的一步,配置错误会导致服务无法启动。

# .env 文件内容示例 # 客户端运行端口 CLIENT_PORT=3001 CLIENT_SITE_URL=http://localhost:3001 CLIENT_ASSET_PREFIX=/ # 管理后台运行端口 ADMIN_PORT=3002 ADMIN_ASSET_PREFIX=/ # 服务端运行端口 SERVER_PORT=3003 SERVER_API_URL=http://localhost:3003/api SERVER_API_PREFIX=/api # 默认管理员账户(首次启动后,请务必在后台修改!) ADMIN_USER=admin ADMIN_PASSWD=admin # 数据库配置(使用刚才创建的数据库和用户) DB_HOST=127.0.0.1 DB_PORT=3306 DB_USER=wipi_user # 改为你创建的用户名 DB_PASSWD=another_strong_password # 改为对应用户的密码 DB_DATABASE=wipi # Github OAuth登录(可选,初期可跳过) GITHUB_CLIENT_ID=0 GITHUB_CLIENT_SECRET=0 # 邮件服务配置(可选,用于评论通知等) # MAIL_HOST=smtp.qq.com # MAIL_PORT=465 # MAIL_USER=your_email@qq.com # MAIL_PASS=你的授权码 # MAIL_FROM=你的发件邮箱

4. 启动项目

pnpm run dev

这个命令通常会同时启动前端客户端、后台管理和服务端。根据控制台输出,访问以下地址:

  • 博客前台:http://localhost:3001
  • 后台管理:http://localhost:3002(使用默认账号admin/admin登录)
  • 服务端API:http://localhost:3003/api

如果启动失败,请首先检查:

  1. MySQL服务是否正常运行,.env中的数据库连接信息是否正确。
  2. 端口3001, 3002, 3003是否被其他程序占用。
  3. 查看终端报错信息,通常是依赖缺失或配置错误。

4.3 初始化与后台设置

首次成功登录后台后,你需要立即做以下几件事:

  1. 修改默认管理员密码:在用户管理或个人信息处,将默认的admin/admin密码修改为强密码。
  2. 进行系统设置:在系统设置页面,填写网站标题、描述、Logo、备案号等基本信息。这些信息会展示在前台页面上。
  3. 配置OSS(如果使用):在文件管理或存储设置中,填入阿里云OSS的Bucket名称、Region、AccessKeyId和AccessKeySecret。这样上传的图片才会存到OSS。
  4. 创建分类和标签:开始撰写文章前,先规划好文章分类和常用标签。

5. 生产环境部署实战指南

本地开发没问题后,就可以部署到云服务器上对外服务了。这里以一台干净的Ubuntu 22.04服务器为例。

5.1 服务器基础环境搭建

通过SSH连接到你的服务器。

# 更新系统包 sudo apt update && sudo apt upgrade -y # 安装Docker(用于运行MySQL) sudo apt install -y docker.io docker-compose sudo systemctl start docker sudo systemctl enable docker # 使用Docker Compose运行MySQL(更易于管理) mkdir -p ~/wipi-deploy/mysql-data cd ~/wipi-deploy

创建docker-compose.yml文件:

version: '3.8' services: mysql: image: mysql:5.7 container_name: wipi-mysql restart: always environment: MYSQL_ROOT_PASSWORD: your_very_strong_root_password_here MYSQL_DATABASE: wipi MYSQL_USER: wipi_user MYSQL_PASSWORD: your_strong_wipi_user_password ports: - "3306:3306" volumes: - ./mysql-data:/var/lib/mysql - ./conf.d:/etc/mysql/conf.d command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci

启动MySQL:

docker-compose up -d docker-compose logs -f mysql # 查看日志,确认启动成功

安装Node.js & pnpm & PM2

# 安装Node.js 18.x curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - sudo apt-get install -y nodejs # 安装pnpm sudo npm install -g pnpm # 安装PM2(进程管理工具) sudo npm install -g pm2

5.2 部署Wipi应用代码

1. 克隆代码并安装依赖

cd ~ git clone --depth=1 https://github.com/fantasticit/wipi.git wipi-production cd wipi-production # 安装依赖(生产环境) NODE_ENV=production pnpm install --frozen-lockfile # --frozen-lockfile 会严格根据pnpm-lock.yaml安装,确保环境一致

2. 配置生产环境变量创建生产环境专用的.env.prod文件:

cp .env .env.prod nano .env.prod

修改关键配置:

  • CLIENT_SITE_URL: 改为你的域名,如https://blog.yourdomain.com
  • ADMIN_ASSET_PREFIX: 同上,或CDN地址
  • SERVER_API_URL: 改为你的后端API地址,如https://api.yourdomain.com/api(如果你将前后端部署在同一域名下不同路径,则可能是https://blog.yourdomain.com/api)
  • 数据库DB_HOST: 如果MySQL在同一服务器,可以是127.0.0.1;如果在其他服务器,填写内网IP。
  • 务必修改ADMIN_PASSWD为一个强密码。
  • 填写真实的OSS、邮件等配置。

3. 构建项目

pnpm run build

这个命令会分别构建前端(Next.js)的静态/服务端渲染文件和后端(Nest.js)的JavaScript包。

4. 使用PM2启动应用Wipi项目可能已经提供了pm2的配置文件(如ecosystem.config.js)。如果没有,我们可以创建一个简单的启动脚本,或者直接用PM2启动构建后的产物。

假设构建后,后端服务入口在dist目录,我们可以这样配置PM2:

# 进入项目目录 cd ~/wipi-production # 使用PM2启动服务。假设package.json中定义了start:prod命令来启动生产环境服务。 # 首先,需要设置环境变量指向.env.prod # 一种方法是在package.json的script里设置NODE_ENV=production并加载.env.prod # 更简单的方式是使用PM2的env文件 echo 'NODE_ENV=production' > .env.pm2 # 然后启动应用。如果项目根目录的package.json有“start:prod”脚本,可以直接: pm2 start pnpm --name "wipi" -- run start:prod # 或者,如果项目结构是分列的,可能需要分别启动client和server。这取决于项目的具体脚本。 # 例如,有的项目需要: # pm2 start npm --name "wipi-client" -- run start:client-prod # pm2 start npm --name "wipi-server" -- run start:server-prod # 设置PM2开机自启 pm2 startup # 执行上面命令后,会输出一条类似“sudo env PATH=... pm2 startup ...”的命令,复制并执行它。 pm2 save

5.3 配置Nginx反向代理与HTTPS

现在应用跑在3001-3003端口,我们需要用Nginx作为反向代理,对外提供80/443端口的访问,并配置HTTPS。

1. 安装Nginx

sudo apt install -y nginx

2. 申请SSL证书可以使用Let‘s Encrypt的免费证书,通过Certbot工具自动申请和续期。

sudo apt install -y certbot python3-certbot-nginx sudo certbot --nginx -d blog.yourdomain.com -d admin.yourdomain.com # 根据你的域名调整

Certbot会自动修改你的Nginx配置,启用HTTPS。

3. 配置Nginx如果Certbot没有自动配置好,或者你需要更精细的控制,可以手动配置。假设我们将前后端都通过一个域名访问,通过路径区分:

  • https://blog.yourdomain.com/-> 前台 (3001)
  • https://blog.yourdomain.com/admin/-> 后台 (3002, 注意:这里需要Next.js配置basePath)
  • https://blog.yourdomain.com/api/-> 后端API (3003)

这需要Wipi项目本身支持这种路径映射。更常见的部署方式是子域名

  • https://blog.yourdomain.com-> 前台 (3001)
  • https://admin.yourdomain.com-> 后台 (3002)
  • https://api.yourdomain.com-> 后端API (3003)

这里以子域名方式为例,创建Nginx配置/etc/nginx/sites-available/wipi

# 前台博客 - blog.yourdomain.com server { listen 80; server_name blog.yourdomain.com; # 重定向到HTTPS return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name blog.yourdomain.com; ssl_certificate /etc/letsencrypt/live/blog.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/blog.yourdomain.com/privkey.pem; location / { proxy_pass http://127.0.0.1:3001; # 指向前台应用 proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; # 传递真实IP,重要! proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_cache_bypass $http_upgrade; } } # 后台管理 - admin.yourdomain.com server { listen 80; server_name admin.yourdomain.com; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name admin.yourdomain.com; ssl_certificate /etc/letsencrypt/live/admin.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/admin.yourdomain.com/privkey.pem; location / { proxy_pass http://127.0.0.1:3002; # ... 其他proxy_set_header配置同上 proxy_set_header X-Real-IP $remote_addr; } } # 后端API - api.yourdomain.com server { listen 80; server_name api.yourdomain.com; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name api.yourdomain.com; ssl_certificate /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/api.yourdomain.com/privkey.pem; location / { proxy_pass http://127.0.0.1:3003; # ... 其他proxy_set_header配置同上 proxy_set_header X-Real-IP $remote_addr; } }

启用配置并重启Nginx:

sudo ln -s /etc/nginx/sites-available/wipi /etc/nginx/sites-enabled/ sudo nginx -t # 测试配置语法 sudo systemctl reload nginx

关键点proxy_set_header X-Real-IP $remote_addr;这行配置至关重要。它确保了你的后端服务(Nest.js)能获取到访问者的真实IP地址,而不是Nginx服务器的IP。这对于访问统计、反爬虫等功能是必须的。

6. 运维、优化与故障排查实录

6.1 日常运维命令

  • 查看应用状态pm2 listpm2 monit(可视化监控)
  • 查看日志
    pm2 logs wipi # 查看所有进程日志 pm2 logs wipi --lines 100 # 查看最近100行 pm2 logs wipi --err # 只看错误日志
  • 重启应用pm2 restart wipi(修改代码或配置后)
  • 停止应用pm2 stop wipi
  • 删除应用pm2 delete wipi

6.2 性能与安全优化建议

  1. 数据库优化

    • articles表的created_at,category_id,status等常用查询字段添加索引。
    • 定期清理垃圾评论、回收站文章。
    • 考虑对文章内容等大字段进行压缩存储。
  2. 前端优化

    • 利用Next.js的next/image组件自动优化图片。
    • 配置适当的缓存策略(Cache-Control headers),对静态资源进行长期缓存。
    • 如果流量大,可以考虑将前端构建产物上传至CDN,并在.env.prod中配置CLIENT_ASSET_PREFIX为CDN地址。
  3. 后端优化

    • 对频繁查询且变化不频繁的数据(如网站配置、分类列表)使用内存缓存,如Redis。
    • 使用Nest.js的缓存拦截器。
    • 对列表查询接口实现分页,避免一次性拉取过多数据。
  4. 安全加固

    • 修改所有默认密码:MySQL root密码、Wipi管理员密码。
    • 限制数据库远程访问:在MySQL配置中,将wipi_user的host限制为应用服务器IP,或只允许本地127.0.0.1
    • 定期更新依赖:运行pnpm outdated检查,并安全地更新package.json中的依赖版本。
    • 配置防火墙:只开放80, 443, 22(SSH)端口,关闭3001-3003等内部服务端口的外部访问。
    • 备份:定期备份MySQL数据库(docker exec wipi-mysql mysqldump -u root -p wipi > backup.sql)和上传到OSS的重要文件。

6.3 常见问题与解决方案

问题1:服务启动失败,提示数据库连接错误。

  • 排查:首先检查MySQL容器是否运行 (docker ps)。然后检查.env.env.prod文件中的DB_HOST,DB_PORT,DB_USER,DB_PASSWD是否正确。可以尝试用命令行工具(如mysql -h 127.0.0.1 -u wipi_user -p)手动连接测试。
  • 解决:修正环境变量,确保数据库用户有远程连接权限(如果不在同一主机)。

问题2:前台页面能打开,但图片不显示或上传失败。

  • 排查:检查OSS配置是否正确。登录阿里云OSS控制台,查看Bucket的权限是否为公共读(对于博客图片通常是需要的),或者检查SDK使用的AccessKey是否有上传权限。
  • 解决:核对.env中的OSS配置信息。如果是权限问题,在OSS控制台调整Bucket的ACL或RAM用户权限。

问题3:访问后台或API出现CORS(跨域)错误。

  • 排查:当你的前端域名(如blog.yourdomain.com)访问后端API域名(如api.yourdomain.com)时,浏览器会因同源策略而阻止。错误信息通常在浏览器控制台看到。
  • 解决:需要在Nest.js后端启用并正确配置CORS。在Nest.js的main.ts中,确保有类似app.enableCors({ origin: ['https://blog.yourdomain.com'], credentials: true })的配置。生产环境务必指定具体的origin,不要使用*

问题4:PM2进程无故退出。

  • 排查:运行pm2 logs wipi --err查看错误日志。常见原因有内存溢出、未捕获的异常、端口冲突等。
  • 解决
    • 如果是内存问题,可以尝试使用pm2 start ... --max-memory-restart 300M来设置内存上限,超出后自动重启。
    • 确保端口没有被其他进程占用。
    • 检查代码中是否有全局未处理的Promise rejection。

问题5:网站打开速度慢。

  • 排查:使用浏览器开发者工具的Network面板,查看哪个资源加载慢。可能是图片过大、JS/CSS未压缩、数据库查询慢、或者服务器地理位置远。
  • 解决
    • 图片使用WebP格式,并设置合适尺寸。
    • 开启Nginx的gzip压缩。
    • 为数据库查询添加索引。
    • 考虑使用云服务商提供的全球加速或CDN服务。

部署和维护一个自建CMS就像打理自己的花园,需要持续的投入,但带来的控制感和成就感也是使用第三方平台无法比拟的。Wipi提供了一个非常扎实的起点,让你能专注于内容创作和功能定制,而不用操心最基础的系统搭建。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询