喀麦隆的一款离线优先收银 PWA
发布于
2026 年 10 月 2 日,Caisse Boutique 账号在 dev.to 上发布了一篇法语建设报告,讲的是一款 为喀麦隆小零售商写的收银(POS)渐进式 Web 应用。文章写道,在撒哈拉以南非洲为小商 铺设计收银软件,不是去照抄 Square 或 Shopify,而是要解决三件现场难题:它点名的 MTN 与 Orange 这两家电信网络的中断、移动数据流量的高昂单价,以及现金管理。它把 Caisse Boutique 介绍为一款为喀麦隆商铺设计的离线优先渐进式 Web 应用,并说下文要交代的就是它背后 的架构与技术选择 (该报告)。
这篇报告交代了什么
Section titled “这篇报告交代了什么”下面依次交代报告点名的现场条件、它印出的架构对照、它描述的离线机制、它为本地市场列出的功 能,以及它引用的商户反馈,用词一律照文章自己的说法。
作者点名的现场条件
Section titled “作者点名的现场条件”文章描述了一位杜阿拉店主的日常,点名了 Akwa 的小吃店、Deido 的食品店和中央市场 (Marche Central)的五金店,并描述了下面这些条件。第一项是连接的长期不稳定:它写道,4G 与 3G 移动网络在高峰时段会定期中断,而如果一套收银程序依赖同步的云端 API,队伍就会越排越长,店 主会立刻退回纸笔和账本。第二项是它所称的「应用商店的摩擦」:它写道,让一位店主从 Google Play 商店下载一个 80 MB 的应用,会吃掉这个人自己的流量包,很多人因此拒绝或放弃。第三项是 它所称的「看不见的金钱流失」,它把原因归为员工无正当理由取消的小票、估算式的心算,以及无 记录的库存失窃 (该报告)。
金钱流失那一项后面挂着一个数字。文章写道,一家没有电子收银的小商铺,平均每月会在毫无察觉的情 况下损失 5 万到 15 万中非法郎(FCFA) (该报告)。
文章印出的架构对照表
Section titled “文章印出的架构对照表”文章给出选择渐进式 Web 应用、并采用它所称的「彻底离线优先」路线的理由,形式是一张表,把通 过 Play 商店或 APK 分发的原生应用与它自家的 PWA 并列对照。各行连同文章自己的取值是:下载 体积,原生应用 50 到 120 MB 的移动流量,对 PWA 不到 2 MB;安装,必须有 Google Play 账 号,对 PWA 的一次点击「添加到主屏幕」;网络依赖,没有连接时常常直接卡住,对它所称的用 Service Worker 加 LocalStorage 或 IndexedDB 实现的完全离线自主运行;更新,沉重的手动下 载,对每次重新联网时静默而即时的更新;兼容性,仅限较新的 Android 版本,对任意智能手机、平 板或老旧 PC (该报告)。
离线模式是怎么描述的
Section titled “离线模式是怎么描述的”离线模式是通过它点名的几套机制来描述的。第一套是资源的缓存优先处理:它写道,HTML 组件、Tailwind CSS 样式与应用 脚本这一整套,从第一次打开起就由浏览器缓存在本地。第二套是交易的本地存储:每一笔销售、库 存改动或小票打印,都记录在设备上它所称的「安全队列」里。第三套是后台对账:设备一旦重新接 上网络(Wi-Fi 或移动数据),一个同步引擎就会把交易成批推送到中央数据库,而且从不阻塞收银 员的结账界面 (该报告)。
那张架构对照表点名的两套存储机制里,MDN 记录了 IndexedDB。MDN 把 IndexedDB 描述为一个用于在客户端存储大量 结构化数据(包括文件与 blob)的低层 API,写道它用索引来支持对这些数据的高性能检索,并说 Web Storage 适合存较少量的数据、对较大量的结构化数据则不那么合用。MDN 还写道,用 IndexedDB 执行的操作是异步完成的,以免阻塞应用,并且 IndexedDB 在 Web Worker 中可用 (MDN,IndexedDB API)。
为本地市场写的功能
Section titled “为本地市场写的功能”排在最前的是 58 毫米热敏小票的蓝牙打印:文章写道,纸质小票对喀麦隆顾客来说 仍是信任的绝对象征,应用会直接连上本地市场或 Jumia 上售卖的 58 毫米迷你热敏打印机,而小票 会自动带上 DGI 要求的法定标注,它把这些标注列为 NIU、RCCM 与顺序发票号。第二项是在没有打 印机或纸卷用完时,一次点击把小票发到 WhatsApp。第三项是属于老板的主 PIN 码,文章说它锁住 每一项敏感操作,点名了取消一笔销售、给出例外折扣和修改库存。第四项是收费模式:文章写道, 不需要国际银行卡,每月 5 000 中非法郎的订阅费可以直接通过 MTN Mobile Money 或 Orange Money 支付 (该报告)。
文章引用了一位它称为 Papa Jean 的商户的反馈,说此人在杜阿拉 Deido 经营一家街区食品店。 那段法语引文是:“Avant, c’etait le cahier. Quand je devais m’absenter pour aller voir les grossistes, les produits disparaissaient et le compte du soir ne tombait jamais juste. Depuis que la tablette est posee au comptoir, je sais exactement ce qui a ete vendu, franc par franc, meme sans connexion. Les 5 000 FCFA d’abonnement me paient la paix du coeur.” 它讲的是以前只有纸账本;老板不得不外出见批发商时,货品会消失、 晚上的账从来对不齐;而自从柜台上摆了一台平板,他就清楚知道卖出了什么,包括在没有连接的时 候 (该报告)。
对 PWA 开发者为什么重要
Section titled “对 PWA 开发者为什么重要”文章把 Service Worker 列为它所称完全离线自主运行的一部分,而 MDN 记录了这套机制。MDN 把 Service
Worker 描述为坐在 Web 应用、浏览器与(可用时的)网络之间的代理服务器,并写道它们的用途之
一就是让有效的离线体验得以成立、拦截网络请求,并依据网络是否可用采取相应动作。同一页还写
道,Service Worker 只在安全上下文中可用,也就是文档通过 HTTPS 提供,同时浏览器也把
http://localhost 当作安全上下文,以便本地开发
(MDN,Service Worker API)。
MDN 也记录了那个 worker 的限制。MDN 写道,Service
Worker 运行在 worker 上下文里,没有 DOM 访问权,运行在与驱动应用的主 JavaScript 不同的线
程上,因此诸如同步 XHR 与 Web Storage 之类的 API 不能在 Service Worker 内部使用。MDN 还
写道,Service Worker 不能动态导入 JavaScript 模块,在 Service Worker 全局作用域里调用
import() 会抛出错误,而用 import 语句做静态导入是允许的
(MDN,Service Worker API)。
文章的小票打印是通过蓝牙连上热敏打印机的,而 MDN 记录了 Web Bluetooth API。MDN 把它标记为可用性有
限,写明该特性不属于 Baseline,因为它在一些使用最广泛的浏览器里并不工作,并把它标为实验
性,建议在投入生产之前仔细查阅浏览器兼容性表。MDN 把这个 API 描述为提供连接并与蓝牙低功耗
外设交互的能力,写道它只能在安全上下文中使用,并指出它在 Web Worker 中不可用,因为它没有
通过 WorkerNavigator 暴露
(MDN,Web Bluetooth API)。
站内相关条目
Section titled “站内相关条目”- Capabilities:报告里的小票打印机是一处 Web Bluetooth 集成, 而这一页正是 OpenPWA 记录 PWA 可以调用的设备与平台能力(蓝牙在其中)的地方。
- Storage:文章把离线队列描述为设备上的 LocalStorage 或 IndexedDB, 而这一页讲的是配额、持久化与逐出,这些才决定这样一个队列能不能活下来。
- Performance:文章的核心对照是与原生应用相比的下载体积数字, 而这一页正是记录这笔交换中性能预算那一侧的地方。
待核实与存疑之处
Section titled “待核实与存疑之处”- 「没有电子收银的小商铺每月损失 5 万到 15 万中非法郎」这个数字是出自某项研究、某个样本, 还是一次估算,尚未确认。
- 本地交易队列究竟是在 Service Worker 里读写,还是只在页面里读写,尚未确认。
- 「不到 2 MB」这个下载数字覆盖的是首次加载、缓存后的应用,还是两者兼有,尚未确认。
- 文章点名的那些 58 毫米热敏打印机,在其商户实际使用的具体浏览器与操作系统版本上能否通过 Web Bluetooth 工作,尚未确认。
- 所引用的商户反馈是否经过某种既定流程收集,以及是否问过不止一位商户,尚未确认。
- 文章那一行写作「任意智能手机、平板或老旧 PC」的兼容性说法,是否也打算覆盖蓝牙小票打印而 非仅覆盖应用的其余部分,尚未确认。
- 这款应用是否在 MDN 所称「Web Bluetooth 并不工作」的那些使用最广泛的浏览器上做过测试,尚 未确认。
- Comment j’ai construit une PWA de caisse enregistreuse 100% hors-ligne pour les commercants du Cameroun(dev.to)
- Service Worker API(developer.mozilla.org)
- IndexedDB API(developer.mozilla.org)
- Web Bluetooth API(developer.mozilla.org)