🖥️ 自托管 DSH Radar(30 分钟)
中级 · 30 分钟 · 2026-08-16
web/dist/ 里的一堆 HTML/JS/JSON,扔到任何能发静态文件的地方都能跑。
本教程涵盖 3 种托管方案 + 自建 Nginx,按推荐度排序。
先跑通本地构建
不管选哪种方案,前提都是这两步能跑通。抓数据脚本零依赖,只要 Node.js ≥ 18(内置 fetch):
git clone https://github.com/dsh-radar/dsh-radar.git
cd dsh-radar
# ① 抓 npm + GitHub 数据,算 5 维评分,写入 data/
node scripts/build-data.mjs
# 初次试跑建议限流:LIMIT=50 node scripts/build-data.mjs
# ② 构建静态站,产物在 web/dist/
cd web && npm install && npm run build 方案对比
| 方案 | 难度 | 费用 | 推荐场景 |
|---|---|---|---|
| Cloudflare Pages | ⭐ 简单 | 免费(不限带宽) | 99% 的人;国内访问最稳 |
| GitHub Pages | ⭐ 简单 | 免费(吃 Actions 配额) | 数据更新已经跑在 Actions 上,想一条龙 |
| Vercel | ⭐⭐ | 免费额度 | 想要 preview deploy / CLI 一把梭 |
| 自建 Nginx | ⭐⭐⭐ | 服务器费用 | 内网 / 数据合规 / 接私有 registry |
三个托管平台的本质差异只有一个:谁来跑 build-data.mjs。
在平台构建容器里直接抓数据会撞上 GitHub API 60 次/小时的匿名限流;
更稳的做法是让 GitHub Actions 定时抓数据并提交回仓库,托管平台只负责 npm run build。
GitHub Pages 天然适合前者,Cloudflare / Vercel 适合后者。
方案 1:Cloudflare Pages(推荐)
步骤 1:准备 fork
- Fork dsh-radar/dsh-radar
- 本地 clone:
git clone https://github.com/YOU/dsh-radar.git - 跑一次构建确保环境 OK:
cd dsh-radar/web npm install --cache /tmp/npm-cache npm run build
步骤 2:连 Cloudflare Pages
- 登录 Cloudflare Dashboard
- Workers & Pages → Create application → Pages → Connect to Git
- 选你的 fork 仓库
- 配置:
Build command: cd web && npm install --cache /tmp/npm-cache && npm run build Build output: web/dist Root directory: / - 环境变量(Settings → Environment variables):
NODE_VERSION = 22 PUBLIC_WEB3FORMS_KEY = <your-key> - Save and Deploy
步骤 3:自定义域名
- Pages → 你的项目 → Custom domains → Set up a custom domain
- 输入域名(如
radar.yourcompany.com) - Cloudflare 会给一个 CNAME,在你的 DNS 添加
- 等待 DNS 生效(5-30 分钟)
方案 2:Vercel(最简单)
# 1. 安装 vercel CLI
npm i -g vercel
# 2. 在项目根目录
cd dsh-radar
vercel login
vercel --prod
# 3. 跟着提示选 framework = Other
# Root Directory = web
# Build Command Override = npm run build
# Output Directory Override = dist
# 或者跳过全部交互,一行搞定:
cd dsh-radar/web
vercel --prod --yes \
--build-env NODE_VERSION=22 \
--env PUBLIC_WEB3FORMS_KEY=<your-key>
Vercel 会把这些设置写进 .vercel/project.json,之后每次只要 vercel --prod 即可。
方案 3:自建 Nginx
构建产物
# 本地
cd dsh-radar/web
npm run build
# 上传
rsync -avz --delete dist/ user@server:/var/www/dsh-radar/ Nginx 配置
server {
listen 443 ssl http2;
server_name radar.yourcompany.com;
ssl_certificate /etc/letsencrypt/live/radar.yourcompany.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/radar.yourcompany.com/privkey.pem;
root /var/www/dsh-radar;
index index.html;
# 启用 gzip
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# 静态资源长缓存(文件名带 hash)
location /_astro/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# 数据 JSON 短缓存:每周才更新一次,5 分钟足够
location ~* \.json$ {
expires 5m;
add_header Cache-Control "public, must-revalidate";
}
# 关键:目录式路径 + SPA fallback
# astro.config 用了 build.format: 'directory',页面产物是 /plugins/index.html,
# 少了这行,直接刷新 /plugins/xxx 这类深链接会 404
location / {
try_files $uri $uri/ $uri.html /index.html;
}
# sitemap + robots 显式返回
location = /sitemap.xml { add_header Cache-Control "public, max-age=3600"; }
location = /robots.txt { add_header Cache-Control "public, max-age=86400"; }
# 安全头
add_header X-Content-Type-Options "nosniff";
add_header X-Frame-Options "SAMEORIGIN";
add_header Referrer-Policy "no-referrer-when-downgrade";
} 每周自动更新(cron)
# crontab -e
# 每周一 UTC 02:00 重新拉数据 + 重新 build + 重启 nginx
0 2 * * 1 cd /opt/dsh-radar && git pull && node scripts/build-data.mjs && (cd web && npm run build) && rsync -avz --delete web/dist/ /var/www/dsh-radar/ && nginx -s reload 环境变量配置
整站只有一个前端环境变量:PUBLIC_WEB3FORMS_KEY,
供 /subscribe 页面的表单使用。
PUBLIC_ 是 Astro 的约定前缀——带这个前缀的变量会被编译进客户端产物,
所以它天生就是公开的,绝对不要往里塞任何私密凭据。
# web/.env(本地开发用,已在 .gitignore 里)
PUBLIC_WEB3FORMS_KEY=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
# 代码里这样读,没配置时优雅降级成空串(表单回退 mailto):
# const web3formsKey = import.meta.env.PUBLIC_WEB3FORMS_KEY || '';
抓数据阶段另有两个可选变量,它们只作用于 scripts/build-data.mjs,不会进前端产物:
GITHUB_TOKEN(把 GitHub API 限流从 60 次/小时提到 5000 次/小时)与
LIMIT(只处理下载量前 N 个包,0 表示全量)。
DSH Radar 本身零追踪,不需要任何统计脚本的 key。
自定义域名 DNS 配置
三个平台都是同一套 CNAME 逻辑,区别只在目标值:
# 子域名(推荐,最省事)
类型 名称 值
CNAME radar your-project.pages.dev # Cloudflare Pages
CNAME radar cname.vercel-dns.com # Vercel
CNAME radar <用户名>.github.io # GitHub Pages
# 根域名(apex 上 CNAME 不合法,用平台 flatten 或 A 记录)
Cloudflare : CNAME @ → your-project.pages.dev(自动 CNAME flattening)
Vercel : A @ → 76.76.21.21
GitHub : A @ → 185.199.108.153(官方 4 个 IP 全部添加)
加完记录一定要回平台后台把域名 Add / Verify 一遍,证书才会自动签发。
用 GitHub Pages 还要额外在 web/public/CNAME 里写上域名,
否则每次部署都会把自定义域名重置掉。DNS 生效一般 5-30 分钟。
部署后自检清单
/plugins— 711 个插件和 S/A/B/C/D 等级正常渲染/search— 搜索索引是客户端 JSON,最容易因缓存出问题/plugins/任意插件— 深链接直接刷新不 404(验证 try_files)/trends和/methodology— 确认data/stats.json被正确读取- DevTools Network — 确认没有任何第三方请求,这是本项目零追踪的底线
常见问题
构建失败:Cannot find module 'astro'
没装依赖。跑 cd web && npm install。
部署后页面是旧的
浏览器缓存。强制刷新(Ctrl+Shift+R / Cmd+Shift+R),或在 URL 加 ?v=2。
怎么绑定自己的域名到 Cloudflare Pages?
Pages → Custom domains → 输入域名 → 按提示加 CNAME。也可以把整个域名 NS 迁到 Cloudflare(推荐,免费 DNSSEC)。
🚀 下一步
部署好后,配 GitHub Actions 每周自动更新。