冷启动不是烧钱,是用第一性原理重构增长引擎
|
去年8月份那个改版上线翻车——就是首页从 SSR 切 CSR 那次,CDN 缓存策略没对齐,首屏白屏三秒半,监控告警响到测试把咖啡泼在键盘上。我盯着 Lighthouse 里 Performance tab 那条惨绿的长条,心想这哪是冷启动,这叫冷冻启动。 冷启动不是烧钱,是用第一性原理重构增长引擎。我原以为只要压住 TTFB 和 FCP 就算赢了,结果 PM 拎着热饮杯坐我工位右边,说“用户根本不在乎你多快,他在乎有没有新东西”。她杯底在桌沿磕了两下,第三下没磕准,水渍洇开一小片,像地图上被抹掉的某个县城。我敲 Enter 刷新 DevTools Network tab,又切回 Elements,光标停在 上不动——这个我敢打包票,viewport 属性没动过,但渲染树就是重建了三次。
文章配图,仅供参考 旁边工位老张刚把双屏壁纸换成《星际穿越》土星环特写,左屏是原始素材,右屏是 PS 调色后的版本,蓝得发硬。他倒水回来时瞥了我一眼:“你那按钮 hover 态还卡顿?”我没答,右手食指按下去、松开、再按——F 键卡了一下,键帽底下有碎饼干渣,上周五团建发的苏打夹心饼,我咬了一口就扔键盘缝里了。现在它卡住的是整个事件循环里的一个微任务帧。增长引擎?我们当时连“引擎”两个字都还没拆开看。PM 甩来一份漏斗转化率表,Excel 表头日期是 7 月 31 日,但真实埋点数据从 8 月 2 日才开始采,因为前端监控 SDK 加载晚于业务 JS 执行——这事儿后端甩锅说“你们 init 太慢”,测试小王边测边念叨“CSS 命名还是该用 BEM,不然谁看得懂 .header--main--sticky--mobile--active-override”……我打断他:“你刚说的那个类名,最后那个 override 是谁加的?”他挠头:“可能是我昨天 PR review 时候顺手写的?”——这我说不准,PR 记录太多,我只记得自己写了七遍重试逻辑,其中四次用 try/catch 包,三次用 setTimeout 降级,一次干脆 return false。 第一性原理?不是让你去背费曼讲义。是逼你问:用户点击那个按钮时,中间必须存在多少个可被绕过的假设?比如——假设网络能返回 200;假设 fetch 不会因 CORS preflight 多耗三百七十二个节点;假设 iOS Safari 的 WebKit 在 touchstart 之后还能及时触发 requestIdleCallback……结果呢?我们重构时把所有异步操作塞进一个 Promise.all,美其名曰“原子化加载”,上线后发现安卓旧机型直接卡死在 Promise.race 里,因为那个 race 的 fallback 函数体里有 await import(),而它的 polyfill 在 Chrome 87 以下根本不 work。我盯着 DevTools Console tab 底部那一行 “Uncaught (in promise) SyntaxError: Unexpected token 'import'”,忽然想起上周团建烤肉摊主递给我一串没刷酱的羊肉,油亮亮地滴着,跟现在我键盘右下角那滴外卖汤一模一样——洒了,但没人擦,大家假装没看见。 优胜劣汰是真的。不是玄学,是物理法则。你硬塞进去的低效路径、冗余守卫、虚假兜底,全会在真实流量下自动坍缩。8 月 17 号那天,AB 测试分组突然倾斜,B 组跳出率比 A 组低十八毫秒,但 UV 下跌百分之九——后台查日志发现,B 组的 GA4 事件采集脚本在加载阶段被广告拦截器干掉了三次,导致后续所有行为漏报。于是“跳出率低”其实是“没上报”,而“UV 跌”才是真相。这个我不敢打包票是不是唯一原因,但那个漏报链路里,恰好卡死了我们在 header 里偷偷写的 window.__DEBUG_TRACKING = true;它本该打印一条 debug 日志,结果什么都没打出。我就盯着那行空 console.log,像盯着一口井。 前天翻老代码,在 utils/request.js 里看到我 2018 年写的注释:“这里不 catch,让 error 穿透出去,由业务层自己决定怎么死。”现在想想真傻。但比傻更糟的是——我们后来给每个 fetch 都包了一层 try/catch,再统一 throw new BizError,结果产品经理拿着错误码表格来问:“5022 是啥意思?”我说:“是用户点了两次按钮,第二次请求被 cancel,cancel 的 Promise 被 reject 出来的。”她眨眨眼:“哦,那就是‘重复提交’?”我点头,她转身就写进需求文档,“增加防重复提交提示”,一行字。没提 cancel、没提 Promise、没提 event loop——就一句话,然后设计出三个弹窗样式让我选。 所以我现在遇到新项目,先删 node_modules,删完清缓存,再 rm -rf dist,接着打开 Chrome DevTools Application tab,手动删掉所有 Service Worker registration,然后关掉所有标签页,重启浏览器——不是仪式,是归零。去年8月那次翻车后,我在首页入口文件里加了段代码:if (location.hostname === 'localhost') { window._COLD_START_DEBUG = true }。它什么也不做,就挂在 window 上。但每次看到它,我就知道,引擎还没点火,先得把油路里的空气排干净。 对了,测试小王昨天问我:“如果重构增长引擎,要不要把埋点 SDK 也重写一遍?”我没答,因为刚收到 HR 邮件,说我季度绩效反馈里有一条:“技术决策前瞻性有待加强”。我截了图发群里,没配文字。群里静了三分钟,老张回了个 GIF:一只乌龟缓慢地、极其缓慢地,把脑袋缩回壳里。 (编辑:站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |




