# 为什么很多MVP根本不需要登录？

URL: https://caijiao.org/posts/134
Source: docs/posts/134.md
Description: Gusto 的免费时薪工资计算器页面，"wage calculator" 月搜索量约 17000，页面月访问约 17776——没有注册、没有保存、没有后端状态，搜索量几乎一比一变成了访问。MVP 阶段加登录墙，等于把最该看的漏斗数据掐断。

Gusto 有个免费的时薪工资计算器页面。"wage calculator" 这个词的月搜索量约 17000，而那个页面的月访问约 17776。它不需要注册，不保存任何记录，甚至没有"我的计算历史"这种东西。

![Gusto 官网首页截图](/images/2026-09/gusto.com.jpg)

*Gusto 首页直接摆出 Create free account 和 See demo——免费账户就是它的漏斗入口。*

这两个数字放在一起值得停一下：17776 / 17000 ≈ 1.05。一个无登录页面能贴近这个比例，原因很直白——从搜索结果点进来的人，在页面出现的那一刻就能开始算，中间没有一道"先创建账号"的门。

## 登录墙会把你最想看的那个数字掐断

MVP 阶段你最想知道的是"有多少人能走完核心路径"。加了登录，这条路径被切成两段，你能拿到的数字从"完成了计算的人"变成"注册了的人"。

这两个群体差别极大。前者包含所有对你有过一点点兴趣的人，后者只剩下愿意交出邮箱、并且当下正好愿意花 30 秒填表的人。用后者反推前者，误差大到没法用来做决策。

更麻烦的是，你连"有多少人因为要先注册而离开"都测不到——他们没有产生任何事件，在统计里就是不存在。

登录墙还会顺手掐断另一条路：分享。一个带状态的 URL 可以贴进工作群，同事点开就能看到同样的结果；如果这个结果必须登录才能看，那这条传播链就断了。对早期项目来说，能被转发是极低成本的获客方式，而注册要求是它最直接的杀手。

## 不登录也能个性化：把状态塞进 URL

多数 MVP 想要的"个性化"其实很轻，用不着用户表。三种做法按代价从低到高排。

第一种是把状态编码进 URL（query string 或 hash）。用户把链接存进书签、发给同事，就得到了完整的还原能力，还顺带获得了可分享性——10015.io 的很多工具就是这种形态，URL 本身就是状态。

实现上有几个细节值得注意。输入变化时用 `history.replaceState` 更新地址栏，而不是 `pushState`，否则用户按返回键要连按十几次才能离开这个页面。中文和特殊字符必须走 `encodeURIComponent`，不然复制出来的链接在聊天软件里会被截断。状态特别大时，先压缩再编码，或者干脆只把"能重建结果的种子"放进去——比如存随机种子和参数，不存完整结果。URL 长度也别忽视：浏览器侧几万字符通常没事，但中间的代理和服务器往往只认 8KB 以内，长链接在某些环境里会被静默截断。

第二种是 localStorage 存最近几次输入和历史，单设备内有效，零后端成本。缺点是清缓存就没了，所以界面上要说明"历史只存在这台设备"，别让用户误以为换台电脑还能看到。

第三种是导出/导入 JSON 文件，给确实需要备份的人留一条手动迁移的路。这一条的成本极低，但能挡住大部分"我清了浏览器缓存，数据没了"的抱怨。

这三件事加起来可能不到 200 行前端代码，[JavaScript](/javascript/) 的原生 API 就够，不需要任何服务端参与。而一套账号系统的服务端部分通常在几千行量级，还要配邮件服务。

## 什么时候 MVP 必须有登录

三条硬条件，满足任意一条才做。

用户换台设备还想要上次的结果，而且这个结果对他真有价值。这条必须经过验证才算成立——很多人以为用户在乎，实际上他重新填一遍只要半分钟。

你要收钱，而且是按周期的订阅。Data Fetcher 有 600 个付费客户，订阅状态、到期时间、用量计数必须落在服务端，这时登录是业务的一部分，没有讨论余地。

接口的边际成本不可忽略，需要按人限流。每个请求都要调外部 API 并按次付费时，匿名等于开着门让人刷。

Cakedesk 是个有意思的反例：它是桌面端应用，一次性 69 欧元，压根没有网站账号——付费和授权都发生在本地，用户数据存在用户自己的硬盘上。2025 年它卖出 239 份新授权，约 16000 欧元毛收入。它证明的是，"收钱"和"有账号系统"是两件事。

## 推迟登录不等于放弃它，先留一条后门

把登录往后推的时候，有两件小事现在做几乎不花钱，以后补却很麻烦。

第一件是给数据预留一个归属位。哪怕现在没有用户表，导出的数据结构里也留一个 `owner` 字段，将来补身份时不用做数据迁移。

第二件是给匿名访问发一个标识：首次打开时在 localStorage 里生成一个随机 ID，之后每次请求带上它。这样即使没有账号，你也能统计"同一个人来过几次"，而将来真做了账号，只要把这一个 ID 绑定到新账号上，历史行为就接上了，不需要重新埋点。

## 一个更实用的问法

把"要不要做登录"换成一句更具体的话：用户关掉浏览器之后，他在不在乎刚才那些数据？

在乎，而且愿意为一个邮箱付出代价——那就做。不在乎，或者重新填一遍的成本低于注册的成本——那你要做的是把结果塞进 URL，让它能被收藏、能被转发。

这两条路会长出完全不同的产品。前者需要持续维护：用户表、会话、找回密码、数据导出；后者可以一直保持"推静态文件就完成部署"的状态，连 [SQLite](/sqlite/) 都用不上。那种纯前端的形态在 [在线工具](/tool/) 这类站点上已经被反复验证过，它不是妥协，是一种被选中的架构。

---

*Gusto 工资计算器页面访问量与关键词搜索量为第三方估算工具数据。*
