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

8.3 KiB
Raw Blame History

Nuxt全栈博客站

Nuxt 博客 全栈 Vue MySQL Redis

博客站

一个基于 Nuxt@4.0.3NuxtContent@3.4.0shadcn/vueinspira-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-sqlite3pnpm rebuild better-sqlite3

零环境快速开始(本地开发)

先决条件:

  • Node.js 20+(建议用 nvm 管理PNPM 10+
  • Docker 与 Docker Compose用于本地 MySQL/Redis
  • macOS/Linux 或 Windows WSL2 环境

步骤:

  1. 启动数据库与缓存(使用内置 compose
docker compose -f docker-compose.local.yml up -d

默认账号与端口:

  • MySQL: root / 123456数据库 blog端口 3306
  • Redis: 无密码,端口 6379
  1. 创建 .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=
  1. 初始化数据库(二选一)

优先使用迁移(如果仓库已包含 lib/drizzle/migrations

pnpm db:migrate

如果没有历史迁移或希望按 schema.ts 直接同步结构:

pnpm db:push
  1. 启动开发服务器
pnpm dev

访问:http://localhost:4775

排错小贴士:

  • 3306/6379 端口被占用:修改 docker-compose.local.yml 的端口映射,或停止占用进程。
  • better-sqlite3 报错:执行 pnpm rebuild better-sqlite3
  • 无法拉取 GitHub 文章:确认 CONTENT_REPO_TOKEN 有权限,或临时注释 content.config.tssource 配置。

运行前配置

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

  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_HOSTREDIS_PORTCONTENT_REPO_TOKENNUXT_*Nodemailer、OAuth GitHub、COS、飞书等
  1. 配置 GitHub Secrets仓库 Settings -> Secrets and variables -> Actions
  • SSH 访问:SSH_PRIVATE_KEYSSH_HOSTSSH_USERSSH_PORT
  • 应用密钥与依赖:DATABASE_URLNUXT_SESSION_PASSWORDNUXT_JWT_SECRET
  • 内容拉取:CONTENT_REPO_TOKEN(若启用 content 仓库)
  • 可选通知与第三方:NUXT_FEISHU_WEBHOOKNUXT_FEISHU_USER_IDNUXT_NODEMAILER_*NUXT_OAUTH_GITHUB_CLIENT_ID/SECRETNUXT_COS_*
  1. 触发部署
  • Push 到 main 且提交信息包含 chore(release) 会自动触发(可使用 pnpm release:patch|minor|major 脚本生成)
  1. 运行方式与端口
  • 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;
      }
    }
    
  1. 数据库迁移
  • 工作流会在服务器上自动执行 Drizzle 迁移(优先 dotenv-cli,无则回退为 source ENVFILE + npx drizzle-kit migrate
  • 如服务器无公网 npm可自行预先装好 dotenv-cli,或手动执行迁移
  1. 回滚与灰度(可选)
  • 回滚:直接 git revert 上次 release 提交并 push同样会触发部署
  • 灰度:仓库包含 pm2.canary.json4572 端口),如需金丝雀发布可另行添加对应 Workflows 与目录(例如 /root/web/blog-canary
  1. 常见排查
  • 启动异常:pm2 logs Blog 查看日志
  • 环境变量未生效:确认 /root/envs/blog/.env 存在且键名正确;pm2 env 0/pm2 describe Blog 检查进程环境
  • 无法连接数据库/Redis验证 DATABASE_URLREDIS_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 的各种问题
  • 分享自己在做的项目