1.4 最小可用:第一 BAR 界面脚手架

选型聊了三节,再不动手就成纸上谈兵了。这一节进入本章唯一一段真正写代码的部分:把最小可用范围砍到最小,然后跑通项目的第一个界面脚手架。所谓第一 BAR,就是我们 app 顶部那条导航栏——列表、发布、我的三个入口,它一通,整个前端的骨架就立住了。

场景:MVP 范围先做减法

最初的功能清单写了二十多条,讨论了两个晚上砍成下面这样:

功能 MVP 是否做 理由
图文列表分页 做 核心闭环
发布图文带图 做 核心闭环
微信登录 做 发布必须鉴权
点赞和评论 晚一版 可降级为浏览
内容审核 做(调内置能力) 合规底线
个人主页 晚一版 有列表先够用
分享卡片 晚一版 锦上添花

砍功能最痛苦的领悟是:你特别想做的那几个,往往用户根本不在意。先让核心闭环跑起来,比什么都重要。判断标准土但好用——如果一个功能砍掉之后应用还能转,它就不属于 MVP。这套 MVP 思路在已经上线的灯塔站点实战里也有同款演绎。

砍完清单那天我们互相问了一句:现在这个范围,一个周末能不能跑通?答案是勉强可以。于是就按这个节奏排了计划:周六搭骨架,周日验证发布链路,周一给内测群看东西。有期限的最小目标,比没有期限的完整需求靠谱得多。

方案:前端选型与目录结构

前端选型我们也开了个小会,候选就三个:

方案 优点 缺点 结论
Vue3 加 Vite 上手快、生态熟 体积略大 选用
React 生态最大 配置偏多 备选
原生多页 零依赖 路由鉴权全手写 否决

选 Vue3 的理由只有一条:会的人多、冷启动快,两个人都在十分钟内把构建跑通了。框架这种事,团队熟悉度永远比纸面参数重要。

目录结构定成这样:

my-app/
  functions/          # 云函数目录
    signin/           # 登录函数
    add-post/         # 发布图文函数
  public/             # 静态资源
  src/
    views/            # 页面:列表、发布、详情
    components/       # 复用组件,顶部BAR就在这
    apis/             # 封装云开发SDK调用
    app.js            # SDK初始化
  cloudbaserc.json    # 环境与函数配置

习惯上把云函数和前端放在同一个仓库里管理,部署时一条命令全推上去,对两个人小团队友好。顺带一提,apis 目录统一封装云开发调用很有必要:哪天换 SDK 版本或者改函数名,只动一个文件而不是满项目找调用处。这个习惯后来在接入第二个云函数时救了我们半小时。一个命令把骨架拉起来:

# 用官方CLI初始化项目,按提示选Vue模板
tcb init my-app
# 进入项目安装依赖
cd my-app && npm install
# 一键部署全部云函数与配置
tcb fn deploy --all

代码片段:顶部导航栏跑起来

先看 SDK 初始化,所有调用都依赖它一行:

// src/app.js 初始化SDK,填入自己的环境ID
import cloudbase from "@cloudbase/js-sdk";
const app = cloudbase.init({ env: "my-app-env" });
export default app;

导航栏最简单能跑的第一版,目的是验证路由和样式链路:

<template>
  <nav class="bar">
    <router-link to="/list">列表</router-link>
    <router-link to="/post">发布</router-link>
    <router-link to="/me">我的</router-link>
  </nav>
  <router-view />
</template>

<style scoped>
.bar {
  display: flex;
  justify-content: space-around;
  padding: 12px 16px;
  background: #ffffff;
  border-bottom: 1px solid #eeeeee;
}
</style>

别笑它简陋,跑通这一步意味着构建工具、路由、部署链路全部串起来了。当晚我们就把它部署到了静态托管上,合伙人在手机上点开那个链接的时候,项目就算真正开工了。部署的完整步骤见后面的部署上线一节。

这一步还有个额外的收获:因为页面足够简单,网络请求、鉴权失败、环境 ID 填错这类问题会立刻暴露,而不是被复杂的业务逻辑掩盖。脚手架阶段暴露的问题,都是最便宜的问题。这也是我们坚持用最简单的页面先上线的原因:验证基建而不是炫技,任何花在骨架上的复杂度都是负债。

再补一个容易忽略的细节:导航高亮。当前页对应的入口要有个选中态,哪怕只是改个字色,用户体感都会好很多。路由激活样式在 vue-router 里一个类名就搞定:

/* 选中的导航项加深字色 */
.router-link-active {
  color: #1890ff;
  font-weight: 600;
}

我们第一版连这个都没加,合伙人试完吐槽说三个入口长得一模一样,不知道自己在哪。用户体验有时候就是这些一两行的代码。

踩坑:脚手架阶段的三个小坑

第一是环境别名。CLI 初始化会问环境 ID,如果手滑填错,本地调试一切正常,部署就报找不到环境。养成习惯:填完先跑 tcb env list 对一遍再继续。

第二是 SDK 版本。云开发 JS SDK 有大版本差异,网上的旧教程复制过来一跑就报错,以官方文档 cloud.tencent.com/document/product/614 的当前版本为准。我们最早按一篇老博客写初始化,白屏了半小时才反应过来。

第三是路由 base。部署到静态托管的子目录时,路由要配对应的 base,否则本地好好的页面上线就白屏。这个坑我们排查了一个晚上才在构建配置里找到原因,相关排查过程记在了前端接入那一节。

第四是手机真机优先。脚手架阶段习惯在电脑上调页面,等真机打开才发现边距、字号、点击区域全是问题。后来我们立了规矩:任何界面改动,先手机扫码看一眼再提交。这条规矩在后续开发里避免了大量返工,也影响了部署上线一节里我们对预览方式的取舍。

第五是过早设计。第一版导航栏我们差点想做成可配置的动态菜单,被合伙人拦下来:现在一共三个入口,配什么配。确实施工现场最大的浪费,就是给不确定的需求写灵活性。

小结

最小可用的精髓是让最短链路先跑到用户眼前:一条导航栏加三个空页面,看起来什么都没有,但构建、路由、部署、环境连通全部验证完毕。从这一刻起,剩下的每一行代码都是给用户加功能,而不是给项目搭基建。如果说前三节解决的是方向问题,这一节解决的是信心问题:跑通一次,你就知道这条路确实走得通。

最后给一个脚手架阶段的验收清单,全部打勾再进下一章:

  • CLI 安装成功,登录账号无报错
  • 环境已创建,环境 ID 记录在项目配置里
  • 云函数至少部署并调用成功过一个
  • 前端本地能跑,页面能看到导航栏
  • 手机能打开部署后的页面

清单看起来朴素,但每一条背后都对应一组常见的坑。全绿之后再开始写业务,会踏实很多。

第一篇到这里结束。下一章我们正式打开控制台,创建第一个云开发环境,开始设计数据库。如果你按本节的顺序走下来,现在应该已经有一个能点开的页面和一条清晰的计划清单了,剩下的就是照着计划填代码而已。

延伸阅读