8.3 KiB
Nuxt全栈博客站
Nuxt 博客 全栈 Vue MySQL Redis
博客站
一个基于 Nuxt@4.0.3、NuxtContent@3.4.0、shadcn/vue、inspira-ui、Drizzle、MySQL、Redis 的全栈站点
娱乐性质的个人空间!
功能
- 登录注册(用户名+密码)
- GitHub 登录
- 点赞
- 评论
- MySQL
- Redis
- 一键复制 HTML 到公众号(保留所有样式)
$fetch/useFetch最佳实践- Sitemap
- RSS
- robots.txt
- PAT 认证
安装依赖
git clone 克隆或下载本仓库到本地
.nvmrc 和 .node-version 中标识了 Node 版本
安装:
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 环境
步骤:
- 启动数据库与缓存(使用内置 compose)
docker compose -f docker-compose.local.yml up -d
默认账号与端口:
- MySQL: root / 123456,数据库 blog,端口 3306
- Redis: 无密码,端口 6379
- 创建 .env(项目根目录)
# 数据库连接(与 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=
- 初始化数据库(二选一)
优先使用迁移(如果仓库已包含 lib/drizzle/migrations):
pnpm db:migrate
如果没有历史迁移或希望按 schema.ts 直接同步结构:
pnpm db:push
- 启动开发服务器
pnpm dev
排错小贴士:
- 3306/6379 端口被占用:修改
docker-compose.local.yml的端口映射,或停止占用进程。 - better-sqlite3 报错:执行
pnpm rebuild better-sqlite3。 - 无法拉取 GitHub 文章:确认
CONTENT_REPO_TOKEN有权限,或临时注释content.config.ts的source配置。
运行前配置
content.config.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 环境,具体操作可以参考这篇文章
Redis 没有配置时,默认连接 localhost 6379 端口,本地同生产(单体数据库服务,不对外开放端口)
DATABASE_URL=mysql://root:root@127.0.0.1:3306/blog
NUXT_FEISHU_WEBHOOK=
NUXT_FEISHU_USER_ID=
先启动 MySQL、Redis
使用 Drizzle 初始化数据库和表结构
# 方式一:使用迁移(推荐)
pnpm db:migrate
# 方式二:按 schema 直接推送
pnpm db:push
启动项目
pnpm dev
生产部署
部署链路:GitHub Actions 构建 -> 打包 .output + pm2.config.json + pm2.preload.cjs -> SSH 上传 -> 服务器 /root/web/blog 原地解压 -> Drizzle 迁移 -> PM2 启动 Blog(端口 4571)。
- 服务器准备
- 安装 Node.js 20+ 与 PM2(全局)
npm i -g pm2
- 创建目录与生产环境变量文件:
- 应用目录:
/root/web/blog - 环境文件:
/root/envs/blog/.env
- 应用目录:
- 必需变量(示例):
DATABASE_URL=mysql://user:pass@host:3306/blogNUXT_SESSION_PASSWORD=<32位随机字符串>NUXT_JWT_SECRET=<随机字符串>- 可选:
REDIS_HOST、REDIS_PORT、CONTENT_REPO_TOKEN、NUXT_*(Nodemailer、OAuth GitHub、COS、飞书等)
- 配置 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_*
- 触发部署
- Push 到
main且提交信息包含chore(release)会自动触发(可使用pnpm release:patch|minor|major脚本生成)
- 运行方式与端口
- PM2 使用
pm2.config.json启动进程名Blog,监听4571 - 运行时通过
node_args: -r ./pm2.preload.cjs读取/root/envs/blog/.env,无需安装dotenv - 反向代理(示例 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; } }
- 数据库迁移
- 工作流会在服务器上自动执行 Drizzle 迁移(优先
dotenv-cli,无则回退为source ENVFILE+npx drizzle-kit migrate) - 如服务器无公网 npm,可自行预先装好
dotenv-cli,或手动执行迁移
- 回滚与灰度(可选)
- 回滚:直接
git revert上次 release 提交并 push(同样会触发部署) - 灰度:仓库包含
pm2.canary.json(4572 端口),如需金丝雀发布可另行添加对应 Workflows 与目录(例如/root/web/blog-canary)
- 常见排查
- 启动异常:
pm2 logs Blog查看日志 - 环境变量未生效:确认
/root/envs/blog/.env存在且键名正确;pm2 env 0/pm2 describe Blog检查进程环境 - 无法连接数据库/Redis:验证
DATABASE_URL、REDIS_HOST/PORT与网络策略
发布
注意 0.x 版本会有不同
# 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 的各种问题
- 分享自己在做的项目



