最近做了一个优惠券聚合工具站,纯前端实现,不用任何框架,部署在 Vercel 上。
在线体验:quan.toppush.cn
本文分享整个技术方案和踩坑记录。
项目背景
需求很简单:做一个页面,聚合美团、京东、淘宝的每日优惠券,用户点击后自动复制口令并跳转到对应 App。
要求:
- 加载快(用户从搜索引擎或社交平台进来,3 秒内必须可用)
- 可以添加到手机桌面(PWA)
- 运维成本趋近于零
- 非技术人员能更新优惠内容
技术选型:为什么不用框架?
考虑过 Next.js、Nuxt,最终决定用纯 HTML + Vanilla JS,原因:
- 页面就一个:单页应用,没有路由需求
- 交互极简:点击复制 + 跳转,不需要状态管理
- SEO 友好:纯 HTML 对爬虫最友好,不存在 SSR/CSR 的问题
- 构建零配置:不需要 Webpack/Vite,Vercel 直接托管静态文件
唯一引入的外部依赖是 js-yaml(CDN 引入),用来解析配置文件。
架构设计
index.html # 单文件应用(HTML + CSS + JS 全部内联)
config.yaml # 优惠数据配置(非技术人员可编辑)
manifest.json # PWA 配置
icons/ # 应用图标
核心思路:配置驱动渲染。页面加载时 fetch config.yaml,解析后动态生成 DOM。
config.yaml 结构
updated_at: "2026-03-31 08:00"
platforms:
meituan:
name: 美团外卖
color: meituan
items:
- name: 天天神券
code: "复制这段口令打开美团..."
type: daily
source: 美团官方活动
jd:
name: 京东外卖
color: jd
items:
- name: 新人立减券
code: "https://..."
type: once
source: 京东外卖新人活动
YAML 比 JSON 的优势:支持注释、可读性好、非技术人员编辑门槛低。
关键实现
1. 三种跳转模式
不同平台的优惠有不同的领取方式,抽象为三种模式:
// URL 模式:直接跳转链接
window.location.href = item.url;
// Deep Link 模式:优先调起 App,失败回退 URL
const schemes = {
meituan: 'imeituan://',
jd: 'openapp.jdmobile://',
taobao: 'taobao://'
};
// 口令模式:复制到剪贴板 → 调起 App
await copyToClipboard(item.code);
window.location.href = schemes[platform];
2. 剪贴板兼容处理
移动端浏览器对 Clipboard API 的支持参差不齐,做了双重降级:
async function copyToClipboard(text) {
// 方案一:现代 Clipboard API
if (navigator.clipboard?.writeText) {
try {
await navigator.clipboard.writeText(text);
return true;
} catch (e) {
// Safari 在非用户交互上下文中会拒绝
}
}
// 方案二:传统 execCommand
const textarea = document.createElement('textarea');
textarea.value = text;
textarea.style.position = 'fixed';
textarea.style.left = '-9999px';
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
return true;
}
关键踩坑:iOS Safari 要求 clipboard.writeText 必须在用户手势回调栈内执行,不能放在 async 中间等待其他异步操作之后。
3. PWA 配置
{
"name": "值得推 · 全平台精选优惠",
"short_name": "值得推",
"display": "standalone",
"start_url": "/",
"theme_color": "#06070f",
"background_color": "#06070f",
"icons": [
{ "src": "/icons/icon-192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png" }
]
}
iOS 还需要额外的 meta 标签:
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<link rel="apple-touch-icon" href="/icons/apple-touch-icon.png">
4. 骨架屏加载态
配置文件通过网络加载,为了避免白屏,做了 CSS 骨架屏:
.skeleton {
background: linear-gradient(90deg, #1a1a2e 25%, #2a2a4e 50%, #1a1a2e 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
border-radius: 8px;
}
@keyframes shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
配置加载完成后替换为真实内容,体验很流畅。
5. SEO 优化
<!-- 结构化数据 -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebApplication",
"name": "值得推",
"description": "每日精选优惠券聚合工具",
"url": "https://quan.toppush.cn",
"applicationCategory": "ShoppingApplication",
"operatingSystem": "All"
}
</script>
<!-- Open Graph -->
<meta property="og:title" content="值得推 - 每日精选优惠">
<meta property="og:type" content="website">
<meta property="og:url" content="https://quan.toppush.cn">
部署方案
选择 Vercel 的原因:
- 免费额度完全够用(个人项目月 100GB 带宽)
- 全球 CDN,国内也能访问(非 vercel.app 域名)
- Git 推送自动部署
- 自定义域名免费 HTTPS
部署步骤:
npm i -g vercelvercel --prod- 在 Vercel 控制台绑定自定义域名,DNS 添加 CNAME 记录
纯静态站,没有构建步骤,部署秒级完成。
CSS 设计细节
深色主题 + 毛玻璃效果:
:root {
--bg: #06070f;
--card-bg: rgba(255, 255, 255, 0.05);
}
.platform-card {
background: var(--card-bg);
backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 16px;
}
用 CSS clamp() 做响应式字号,不写媒体查询:
h1 { font-size: clamp(1.5rem, 4vw, 2rem); }
总结
这个项目的技术含量不高,但验证了一个观点:不是所有项目都需要框架。
对于单页、轻交互、内容驱动的工具站,纯 HTML + JS + CSS 是最简单高效的方案。配合 YAML 配置文件和 Vercel 部署,运维成本几乎为零。
源码结构很简单,感兴趣的可以直接查看页面源代码学习。
在线体验:quan.toppush.cn
如果你也在做类似的轻量工具站,欢迎交流技术方案。