最近做了几个纯前端项目,每次到部署阶段都要折腾服务器,开启 Nginx、配证书、设反向代理……说实话对于静态站点来说太重了。后来改用 OSS + CDN 的方案,不仅省去了维护服务器的麻烦,整体访问速度也提升明显。这篇就把我实际搭建的流程整理一下,希望对有类似需求的同学有参考价值。
本文实验环境使用了阿里云 OSS 服务,目前新购续费同价,费用较低,通过这个链接注册的新用户可以直接开通体验。
一、为什么选 OSS 托管静态站点
传统静态站点部署方案:
| 方案 | 优点 | 缺点 |
|---|---|---|
| 自建 Nginx | 灵活 | 需要维护服务器、手动配证书 |
| GitHub Pages | 免费 | 国内访问慢、无法自定义后端逻辑 |
| Vercel/Netlify | 体验好 | 海外节点,国内延迟不稳定 |
| OSS + CDN | 稳定、国内速度快、按量计费 | 需要一点配置成本 |
OSS 的核心优势在于:它是对象存储,天然适合存放 HTML/CSS/JS/图片等静态资源,配合阿里云 CDN 可以在全国各省做边缘节点加速,访问延迟基本在 50ms 以内。
二、环境准备
需要:
- 阿里云账号(已实名认证)
- 一个构建好的前端项目(本文以 Vite + React 为例)
- 自定义域名(可选,但建议配置)
三、Step 1:创建 OSS Bucket
登录阿里云控制台 → 对象存储 OSS → 创建 Bucket:
- Bucket 名称:全局唯一,建议用项目名,如
my-project-static - 地域:选择离目标用户近的节点(华东/华北均可)
- 读写权限:改为「公共读」(静态网站需要匿名访问)
- 版本控制:可开启,方便回滚
创建完成后,进入 Bucket → 基础设置 → 静态网站托管:
- 默认首页:
index.html - 默认 404 页(对于 SPA 应用):同样填
index.html(这样前端路由才能正常工作)
⚠️ SPA 路由 404 问题是最常见的坑:如果你用了 React Router 或 Vue Router 的 History 模式,不设置 404 跳转到 index.html 会导致刷新页面直接 404。
四、Step 2:上传构建产物
本地构建项目:
npm run build
# 构建产物默认在 dist/ 目录
方案 A:控制台手动上传(适合小项目)
直接把 dist/ 目录内容拖入 Bucket 文件管理界面。
方案 B:使用阿里云 OSS CLI 工具(推荐)
# 安装 ossutil(macOS/Linux)
curl https://gosspublic.alicdn.com/ossutil/1.7.19/ossutil64 -o ossutil
chmod +x ossutil
# 配置 AK/SK(从 RAM 子账号获取,不要用主账号)
./ossutil config
# 增量同步 dist/ 到 Bucket
./ossutil sync dist/ oss://my-project-static/ \
--delete \ # 删除 OSS 中 dist/ 里已不存在的文件
--force \ # 不弹出确认提示
--jobs 10 # 并发上传数
关于 RAM 子账号权限:强烈建议单独创建一个只有 OSS 特定 Bucket 写权限的子账号,把 AK/SK 写进 CI/CD 环境变量,主账号的 AK 一旦泄露损失会很大。
方案 C:GitHub Actions 自动部署
# .github/workflows/deploy.yml
name: Deploy to OSS
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: 18
- name: Build
run: npm ci && npm run build
- name: Upload to OSS
uses: manyuanrong/setup-ossutil@v2.0
with:
endpoint: oss-cn-hangzhou.aliyuncs.com
access-key-id: ${
{
secrets.OSS_ACCESS_KEY_ID }}
access-key-secret: ${
{
secrets.OSS_ACCESS_KEY_SECRET }}
- run: ossutil sync dist/ oss://my-project-static/ --delete --force
五、Step 3:绑定自定义域名 + HTTPS
在 Bucket → 域名管理 → 绑定用户域名,添加你的域名(如 www.example.com),然后在 DNS 服务商处把该域名 CNAME 解析到 OSS 提供的 Endpoint 地址。
HTTPS 证书建议直接用阿里云免费的 DV 证书(SSL 证书服务 → 免费证书),上传到 Bucket 绑定域名处即可,免去手动续签的麻烦。
六、Step 4:接入 CDN 加速
OSS 本身没有 CDN 加速,如果用户分布全国,建议再套一层 CDN:
控制台 → CDN → 添加加速域名 → 源站选「OSS 域名」→ 选择刚才的 Bucket 即可。
缓存策略建议:
# 带 hash 的静态资源(JS/CSS):强缓存
*.js, *.css → Cache-Control: max-age=31536000, immutable
# HTML 文件:不缓存(每次都要最新版本)
*.html → Cache-Control: no-cache
# 图片资源:中等缓存
*.png, *.jpg, *.webp → Cache-Control: max-age=604800
这个策略的核心逻辑:Vite/webpack 构建出来的 JS/CSS 文件名里带内容 hash(如 main.a3f9b2.js),内容变了文件名就变了,可以放心强缓存;而 HTML 作为入口文件要保持最新,不能缓存。
七、踩坑记录
坑 1:跨域问题
如果你的站点需要通过 JS 访问 OSS 上的资源(比如直接请求图片/文件),需要在 Bucket 设置跨域规则(CORS):
{
"AllowedOrigins": ["https://www.example.com"],
"AllowedMethods": ["GET", "HEAD"],
"AllowedHeaders": ["*"],
"MaxAgeSeconds": 3600
}
坑 2:上传大文件超时
单文件超过 100MB 建议开启分片上传(Multipart Upload),ossutil 默认超过 100MB 会自动分片,但如果用 SDK 自己写上传逻辑要注意手动实现。
坑 3:CDN 缓存刷新
每次发布新版本后,记得去 CDN 控制台刷新 HTML 文件缓存(或者通过 CDN API 自动化这一步),否则用户拿到的还是旧 HTML,加载到的还是旧 JS。
八、成本估算
以一个中型项目为例(月访问量 10 万次,存储 2GB 静态资源,流出流量 50GB):
| 费用项 | 大致费用 |
|---|---|
| OSS 存储(2GB) | ≈ ¥0.12/月 |
| OSS 请求次数(10万次) | ≈ ¥0.01/月 |
| CDN 流量(50GB) | ≈ ¥17.5/月 |
| 合计 | ≈ ¥18/月 |
相比一台最低配 ECS(约 ¥100+/月),省了不少,而且还省去了运维成本。如果想算一下自己项目的费用,可以参考阿里云 OSS 价格页的官方计费说明,现在新购续费同价,长期使用也不用担心续费涨价。
九、总结
OSS + CDN 做静态站点托管这套方案用下来整体体验不错,适合以下场景:
- 前端 SPA 应用(React/Vue/Angular)
- 文档站点(VitePress/Docusaurus 生成的 HTML)
- 营销落地页、活动页
- 图床/资源 CDN
不太适合的场景:需要服务端渲染(SSR)、有数据库交互的动态应用,这类还是得上 ECS 或者函数计算。
如果你也有类似的静态站点部署需求,可以试试这套方案,评论区欢迎交流踩过的坑。