catalog/repos/aatrooox--blog-zzao-club.md

283 lines
8.3 KiB
Markdown
Raw Permalink Normal View History

2026-04-06 19:01:37 +08:00
# Nuxt全栈博客站
`Nuxt` `博客` `全栈` `Vue` `MySQL` `Redis`
# 博客站
一个基于 [Nuxt@4.0.3](https://nuxt.com/)、[NuxtContent@3.4.0](https://content.nuxt.com/)、[shadcn/vue](https://www.shadcn-vue.com/)、[inspira-ui](https://inspira-ui.com/components)、Drizzle、MySQL、Redis 的全栈站点
**娱乐性质的个人空间!**
![](/githubAssets/page-home.png)
![](/githubAssets/page-memo.png)
![](/githubAssets/page-articles.png)
## 功能
- 登录注册(用户名+密码)
- GitHub 登录
- 点赞
- 评论
- MySQL
- Redis
- 一键复制 HTML 到公众号(保留所有样式)
- `$fetch/useFetch` 最佳实践
- Sitemap
- RSS
- robots.txt
- PAT 认证
## 安装依赖
`git clone` 克隆或下载本仓库到本地
`.nvmrc``.node-version` 中标识了 Node 版本
安装:
```bash
npm i
pnpm i
```
视报错信息而定:
涉及从 npm 切换到 pnpm 时,可能需要重新 `pnpm add better-sqlite3``pnpm rebuild better-sqlite3`
## 零环境快速开始(本地开发)
先决条件:
- Node.js 20+(建议用 nvm 管理PNPM 10+
- Docker 与 Docker Compose用于本地 MySQL/Redis
- macOS/Linux 或 Windows WSL2 环境
步骤:
1) 启动数据库与缓存(使用内置 compose
```bash
docker compose -f docker-compose.local.yml up -d
```
默认账号与端口:
- MySQL: root / 123456数据库 blog端口 3306
- Redis: 无密码,端口 6379
2) 创建 .env项目根目录
```bash
# 数据库连接(与 compose 保持一致)
DATABASE_URL=mysql://root:123456@127.0.0.1:3306/blog
# Redis不配置则默认 127.0.0.1:6379
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
# 从 GitHub 仓库拉取文章内容所需(如不使用,可留空或注释 content.config.ts 的 source
CONTENT_REPO_TOKEN=
# 应用密钥(本地可任意随机值,生产需妥善保管)
NUXT_SESSION_PASSWORD=please_set_a_32_chars_random_string
NUXT_JWT_SECRET=please_set_a_random_string
# 可选:邮件/COS 等第三方配置(本地可留空)
NUXT_NODEMAILER_HOST=
NUXT_NODEMAILER_PORT=
NUXT_NODEMAILER_AUTH_USER=
NUXT_NODEMAILER_AUTH_PASS=
NUXT_COS_SECRET_ID=
NUXT_COS_SECRET_KEY=
NUXT_COS_BUCKET=
NUXT_COS_REGION=
```
3) 初始化数据库(二选一)
优先使用迁移(如果仓库已包含 `lib/drizzle/migrations`
```bash
pnpm db:migrate
```
如果没有历史迁移或希望按 `schema.ts` 直接同步结构:
```bash
pnpm db:push
```
4) 启动开发服务器
```bash
pnpm dev
```
访问http://localhost:4775
排错小贴士:
- 3306/6379 端口被占用:修改 `docker-compose.local.yml` 的端口映射,或停止占用进程。
- better-sqlite3 报错:执行 `pnpm rebuild better-sqlite3`
- 无法拉取 GitHub 文章:确认 `CONTENT_REPO_TOKEN` 有权限,或临时注释 `content.config.ts``source` 配置。
## 运行前配置
`content.config.ts`
```ts
// content 可以随意更改,对应的是 queryCollection 的第一个参数
content: defineCollection({
// page 表示会一对一生成路由
type: 'page',
source: {
// 过滤 md 文件,因为一个 ob 库里可能什么文件都有
include: '**/*.md',
// 过滤掉某些文件,如没写完的或者不想给人看的
// book 是我的 ob 根目录下的一个文件夹名称,视情况修改
exclude: ['**/-*.md', 'book/**/*.md'],
// 路由前缀 /post因为渲染文章的 vue 文件位于 app/pages/post/[...slug].vue
// 所以为了匹配这个路径要加这个路由前缀
prefix: '/post',
// cwd: process.env.CONTENT_FS_PATH,
// TODO 替换为你的仓库地址,不能使用组织仓库
repository: 'https://github.com/aatrooox/Blog',
// TODO 替换为你的 token在 github > settings > developers settings > personal access tokens
authToken: process.env.CONTENT_REPO_TOKEN
},
// md 文件的元信息,根据自己的实际情况来,这些字段会用作数据库中的表头
schema: z.object({
date: z.date(),
lastmod: z.date(),
tags: z.array(z.string()),
versions: z.array(z.string()),
})
}),
```
`env`
MySQL、Redis 环境,具体操作可以参考[这篇文章](https://zzao.club/post/nuxt/local-init-mysql-by-docker)
Redis 没有配置时,默认连接 localhost 6379 端口,本地同生产(单体数据库服务,不对外开放端口)
```
DATABASE_URL=mysql://root:root@127.0.0.1:3306/blog
NUXT_FEISHU_WEBHOOK=
NUXT_FEISHU_USER_ID=
```
先启动 MySQL、Redis
## 使用 Drizzle 初始化数据库和表结构
```bash
# 方式一:使用迁移(推荐)
pnpm db:migrate
# 方式二:按 schema 直接推送
pnpm db:push
```
## 启动项目
```bash
pnpm dev
```
## 生产部署
部署链路GitHub Actions 构建 -> 打包 `.output` + `pm2.config.json` + `pm2.preload.cjs` -> SSH 上传 -> 服务器 `/root/web/blog` 原地解压 -> Drizzle 迁移 -> PM2 启动 `Blog`(端口 4571
1) 服务器准备
- 安装 Node.js 20+ 与 PM2全局
- `npm i -g pm2`
- 创建目录与生产环境变量文件:
- 应用目录:`/root/web/blog`
- 环境文件:`/root/envs/blog/.env`
- 必需变量(示例):
- `DATABASE_URL=mysql://user:pass@host:3306/blog`
- `NUXT_SESSION_PASSWORD=<32位随机字符串>`
- `NUXT_JWT_SECRET=<随机字符串>`
- 可选:`REDIS_HOST``REDIS_PORT``CONTENT_REPO_TOKEN``NUXT_*`Nodemailer、OAuth GitHub、COS、飞书等
2) 配置 GitHub Secrets仓库 Settings -> Secrets and variables -> Actions
- SSH 访问:`SSH_PRIVATE_KEY``SSH_HOST``SSH_USER``SSH_PORT`
- 应用密钥与依赖:`DATABASE_URL``NUXT_SESSION_PASSWORD``NUXT_JWT_SECRET`
- 内容拉取:`CONTENT_REPO_TOKEN`(若启用 content 仓库)
- 可选通知与第三方:`NUXT_FEISHU_WEBHOOK``NUXT_FEISHU_USER_ID``NUXT_NODEMAILER_*``NUXT_OAUTH_GITHUB_CLIENT_ID/SECRET``NUXT_COS_*`
3) 触发部署
- Push 到 `main` 且提交信息包含 `chore(release)` 会自动触发(可使用 `pnpm release:patch|minor|major` 脚本生成)
4) 运行方式与端口
- PM2 使用 `pm2.config.json` 启动进程名 `Blog`,监听 `4571`
- 运行时通过 `node_args: -r ./pm2.preload.cjs` 读取 `/root/envs/blog/.env`,无需安装 `dotenv`
- 反向代理(示例 Nginx
```nginx
server {
listen 80;
server_name your.domain.com;
location / {
proxy_pass http://127.0.0.1:4571;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
5) 数据库迁移
- 工作流会在服务器上自动执行 Drizzle 迁移(优先 `dotenv-cli`,无则回退为 `source ENVFILE` + `npx drizzle-kit migrate`
- 如服务器无公网 npm可自行预先装好 `dotenv-cli`,或手动执行迁移
6) 回滚与灰度(可选)
- 回滚:直接 `git revert` 上次 release 提交并 push同样会触发部署
- 灰度:仓库包含 `pm2.canary.json`4572 端口),如需金丝雀发布可另行添加对应 Workflows 与目录(例如 `/root/web/blog-canary`
7) 常见排查
- 启动异常:`pm2 logs Blog` 查看日志
- 环境变量未生效:确认 `/root/envs/blog/.env` 存在且键名正确;`pm2 env 0`/`pm2 describe Blog` 检查进程环境
- 无法连接数据库/Redis验证 `DATABASE_URL``REDIS_HOST/PORT` 与网络策略
## 发布
> 注意 0.x 版本会有不同
```bash
# 1.0.0 => 1.0.1 0.1.0 => 0.1.1
pnpm release:patch
# 1.0.0 => 1.1.0 0.1.0 => 0.1.1
pnpm release:minor
# 1.0.0 => 2.0.0 0.1.0 => 0.2.0
pnpm release:major
```
## 自定义字体
使用自定义字体,要注意 format 的值:
```
.woff 文件:使用 format('woff')
.woff2 文件:使用 format('woff2')
.ttf 文件:使用 format('truetype')
.otf 文件:使用 format('opentype')
.eot 文件:使用 format('embedded-opentype')
.svg 文件:使用 format('svg')
```
## 关于环境变量
`.env` 文件用于开发、构建、生成期间。
生产环境如何设置环境变量,取决于你的生产环境是什么。
因为有些 `serverless` / `cf worker` 环境下没有传统的文件系统,所以 `nuxt` 选择不维护环境变量的生产环境配置。
### Nuxt 交流群
- 小群(少于 50 人)
- 分享 Nuxt 相关高质量资料
- 探讨 Nuxt 的各种问题
- 分享自己在做的项目
![](githubAssets/wxgroup.png)