2026 年初我做了一个决定:建一个自己的 AI 内容站,而不是在别人的平台上发内容。原因很简单——平台的内容分发规则随时会变,而独立站的数据和流量是自己的。这篇文章记录从零搭建的全过程,包括技术选型的考量和掉过的坑。
为什么选 Express + SQLite 而不是 Next.js + PostgreSQL
建站之前我认真对比了几种方案。
Next.js + Vercel。最流行的方案,SSR 对 SEO 友好,部署简单。但 Vercel 在国内访问不稳定,而且 Serverless 函数有冷启动问题。我的站面向的是中英文用户,国内访问占比不低。
WordPress。功能最全,插件生态丰富。但 PHP+MySQL 的运维成本和安全隐患对于一个人的项目来说太重了。半个月不更新就可能被扫到漏洞。
Express + sql.js(实际选型)。选这个方案的原因有三个:第一,JavaScript 全栈,一个人维护成本最低。第二,sql.js 把 SQLite 编译成 WebAssembly,不需要安装维护数据库服务。第三,部署简单——一个 Node.js 进程 + Caddy 就是全部。
当然有取舍。sql.js 不支持并发写,所以所有写操作都是串行的。对于日活几百的站来说完全够用,但如果做到日均上万访问就得换方案了。
Caddy:比 Nginx 更适合一人项目
一开始用的 Nginx,但很快就后悔了。Nginx 的配置语法繁琐,SSL 证书要手动续期,反向代理规则写错一行整个站就挂了。
换成 Caddy 之后体验完全不同:
自动 HTTPS。Caddy 内置 Let's Encrypt 自动申请和续期证书。不需要 certbot,不需要 cron 脚本。配置里写一句 tls your@email.com 就行。
配置文件简洁。反向代理、静态文件服务、安全头设置全部在一页配置里搞定。对比 Nginx 动辄上百行的配置,Caddy 的配置大概只有三分之一。
安全头开箱即用。X-Frame-Options、HSTS、Content-Security-Policy 这些安全头直接在 Caddy 配置里声明,不需要中间件。
对一人项目来说,运维复杂度下降一个档次就是实打实的时间节省。
内容结构的演变:从 PC 站到移动优先
最初的设计方案参考了传统论坛——左侧导航、右侧内容、顶部有复杂的分类标签。上线后实测移动端体验一塌糊涂。按钮太小、布局错位、加载时间太长。
后来做了一次彻底的移动端重构:
- 导航栏改成汉堡菜单,收起非核心链接
- 排行榜卡片用 grid 布局自适应列数
- 论坛帖子列表去掉多余信息,只保留标题和分类
- 所有 padding 和 font-size 用 clamp() 做响应式
- Canvas 星空特效加 pointer-events: none 防止干扰点击
重构完移动端体验明显改善,但有一个新问题:Canvas 星空粒子在低端手机上掉帧。最后加了 screen.width 判断——视野宽度小于 768px 时减少粒子数量一半。
SEO 的技术债:早该做的事
这个站最大的技术债是 SEO。因为做的是 SPA(Single Page Application),内容通过 JavaScript 加载,Google 抓到的页面是空的。
最初的方案是给每个页面做动态 meta 注入——JS 加载内容后更新 title、description、canonical、结构化数据。这个方法对已经通过 JS 渲染的页面有效,但对 Googlebot 不够友好——Google 虽然能执行 JS,但执行成本高,优先级低,抓取频率远低于静态页面。
后来的方案是 prerender(预渲染):发布文章时,同时生成一个静态 HTML 文件。sitemap 指向静态文件而不是动态 URL。这样无论 Googlebot 执不执行 JS,都能拿到完整的文章内容。
prerender 的流程:
发布文章 → POST /api/blog
↓
prerender 读取 DB → 生成 blog/post-{id}.html
↓
gen-sitemap 重新生成 → 包含新静态 URL
↓
新文章在 5 分钟内可被 Google 抓取
这个流程跑通之后,Google 的收录速度从"几周"变成"几个小时"。
持久化和备份
对于一个 sql.js 的站点,整个数据库就是一个文件。备份策略简单到令人感动:每天 cron 把 data.db cp 到备份目录,保留最近 7 天。脚本大概 5 行:
#!/bin/bash
BACKUP=/var/backups/playje
mkdir -p $BACKUP
cp /var/www/playje/server/data.db $BACKUP/data-$(date +%Y%m%d).db
find $BACKUP -name '*.db' -mtime +7 -delete
恢复也简单:把备份文件 cp 回去,重启 PM2 进程。整个过程不超过 30 秒。
对于一人项目来说,简单可靠的备份方案比复杂漂亮的高可用方案重要得多。太复杂的方案你根本不会去执行。
关于成本
这个站每月的运营成本:
- 阿里云日本轻量服务器:约 ¥34/月
- 域名 Namesilo 续费:约 ¥60/年
- Caddy(免费)
- sql.js(免费)
- Cloudflare(免费,已不用)
算下来每月运营成本不到 ¥40。加上 AI API 的费用(约 $50/月),一个独立站的月度支出在 ¥400 左右。这个成本一个人完全承担得起,也是支撑我持续做下去的重要原因。
给想搭站的人的建议
如果你也想建一个独立的内容站,我的建议是:不要等到万事俱备再上线。第一版可以简陋,甚至可以没有后台、没有评论区、没有好看的 UI。只要内容在、能访问,就可以上线了。
后续的功能根据用户反馈和数据来决定优先级。不要猜用户想要什么——问他们。一个简单的反馈按钮比三个月的功能开发更有价值。
最后,关注技术债务。做技术选型时选简单方案没错,但要清楚每个简单方案的局限性,知道它什么时候该换成更成熟的方案。超前的架构决定是无意义的,滞后的重构压力是有代价的。