技术探索这事儿,真没你想的那么玄
上周五晚上十点半,我正蹲在公司工位上一边啃着冷掉的黄焖鸡,一边给一个运营活动页面做性能兜底方案。产品经理突然在群里@我:“明天上线前能不能把首屏加载压到1秒内?运营那边说竞品做到了。”
我当时差点把筷子捏断——这需求来得比老板画的饼还圆。
我是谁?某二线互联网公司的三年前端老油条,日常8点准时开工(别笑,早起是为了躲开早高峰地铁+抢会议室插座),代码洁癖晚期患者,看到别人写function a(b){return b+1}会默默重构到带 JSDoc 注解。最近在偷偷刷 LeetCode 和看 JD,毕竟干了三年多,总得换个环境看看外面的世界是不是真如猎头吹的那么香。
今天这篇不是什么高深理论,就是想聊聊技术探索这件事——尤其是在我们这种“既要又要还要”的业务型公司里,怎么在 deadline 的枪口下,还能把技术玩明白、玩出价值。
从一道面试题说起:你做过哪些技术探索?
去年面试一家一线大厂时,面试官问了这么个问题。我第一反应是:“啊?不就是看看文档、跑跑 demo 吗?”
结果人家微微一笑:“我们更关注你是否能结合业务痛点,主动发起并落地一次技术改进。”
当时我就愣住了。回想自己过去两年,确实在搞“技术探索”——比如为了应付周报写了篇《浅谈 Web Workers 在图片处理中的应用》,但实际项目里连个 worker 都没跑起来。纯属纸上谈兵,属于典型的“面试题挑战失败者”。
后来我才意识到:真正的技术探索,不是炫技,而是解决问题。
运营页面的性能之痛:一场被迫的技术实验
回到开头那个黄焖鸡之夜。运营活动页其实是个典型的“短命页面”——上线三天就下线,但流量巨大,且对转化率极度敏感。之前的做法是直接套用公司通用 SPA 框架,结果 Lighthouse 跑出来首屏得分 42,FCP(First Contentful Paint)高达 3.2s。
产品急,运营更急,而我——只想活到周末。
于是这次,我决定不再“临时打补丁”,而是把这次优化当成一次综合性的技术探索实践。目标很明确:
- 首屏加载 ≤ 1s
- 代码可维护(别搞成一坨没人敢动的黑魔法)
- 能复用到后续类似活动
第一步:砍掉 SPA,拥抱 MPA + 静态化
我知道很多人一听“不用 Vue/React”就慌,但现实是:这个页面只有三个静态步骤,根本不需要状态管理、路由跳转那一套。硬塞进 SPA 框架,等于让法拉利去送外卖——性能浪费严重。
于是我用 Vite + EJS 搞了个超轻量 MPA(多页应用)结构,配合预渲染(Prerendering)。构建时直接生成 HTML,用户请求时 Nginx 直接返回,零 JS 阻塞。
// vite.config.js
import { defineConfig } from 'vite'
import ejs from 'ejs'
import fs from 'fs'
export default defineConfig({
build: {
rollupOptions: {
input: {
index: 'src/pages/index.ejs',
step2: 'src/pages/step2.ejs'
}
}
},
plugins: [
{
name: 'render-ejs-pages',
writeBundle() {
const pages = ['index', 'step2']
pages.forEach(name => {
const template = fs.readFileSync(`src/pages/${name}.ejs`, 'utf-8')
const html = ejs.render(template, { /* 注入公共变量 */ })
fs.writeFileSync(`dist/${name}.html`, html)
})
}
}
]
})
效果立竿见影:FCP 降到 0.8s,Lighthouse 得分冲到 92。
第二步:资源懒加载 + 关键 CSS 内联
虽然页面简单,但还是有几张营销图和一个表单组件库。我把非首屏图片全部改成 <img loading="lazy">,表单 JS 延迟到用户滚动到表单位置再动态 import。
最关键的是:把首屏用到的 CSS 抽出来内联到 <head> 中。这里我用了一个小技巧——用 Puppeteer 自动提取关键 CSS:
// extract-critical-css.js
import puppeteer from 'puppeteer'
import fs from 'fs'
async function extractCriticalCSS(url, outputPath) {
const browser = await puppeteer.launch()
const page = await browser.newPage()
await page.goto(url)
const criticalCSS = await page.evaluate(() => {
return Array.from(document.styleSheets)
.filter(sheet => sheet.href?.includes('main'))
.flatMap(sheet =>
Array.from(sheet.cssRules).map(rule => rule.cssText)
)
.join('\n')
})
fs.writeFileSync(outputPath, `<style>${criticalCSS}</style>`)
await browser.close()
}
虽然有点 hack,但在紧急项目里,这种“自动化土法炼钢”反而最有效。
那些踩过的坑:别信文档,信监控
当然,过程不可能一帆风顺。
第一次上线后,测试同学反馈“iOS Safari 下表单错位”。查了半天发现是因为 EJS 渲染时用了 rem 单位,但 viewport meta 没加,导致 iOS 认为页面宽度是 980px。这种细节,在本地开发完全测不出来。
还有一次,我把所有 JS 打包成一个 chunk,结果发现第三方统计 SDK 加载慢,拖累了整个页面。后来改成分离 vendor 和业务逻辑,并加上 rel="preconnect" 提前建立连接。
<link rel="preconnect" href="https://analytics.example.com">
这些教训让我明白:技术探索不能闭门造车,必须有数据闭环。
我在页面埋了几个性能指标上报点:
| 指标 | 上报时机 | 用途 |
|---|---|---|
| FCP | PerformanceObserver | 监控首屏速度 |
| JS Error | window.onerror | 捕获运行时错误 |
| Resource Load Time | Resource Timing API | 分析第三方资源拖累 |
上线三天后,数据回流显示:跳出率下降 18%,转化率提升 7%。运营小姐姐在群里发了个红包,我默默收了——这比任何技术奖都香。
面试题挑战:如果重来,我会怎么做?
现在回头看,这次探索其实是一次“被逼出来的成长”。但如果再给我一次机会,我会更早介入需求阶段。
比如在 PRD 评审时就提出:“这个页面生命周期短、交互少,建议用静态化方案,性能更有保障。” 而不是等上线前一天才手忙脚乱。
我也开始在团队内部推动一个“技术预研卡”机制:每个季度留出 10% 的时间,让工程师针对高频痛点(比如运营页性能、低代码搭建效率)做小规模实验,产出可复用的模板或工具。
最后一点真心话
技术探索不是为了写博客装 X,也不是为了面试时多一道题能答。它是在日复一日的 CRUD 中,给自己留一条“还能折腾”的退路。
我现在每天早上 8 点坐在工位,泡杯速溶咖啡,打开终端敲代码的时候,心里想的不是“今天又要改需求”,而是“今天能不能把那个缓存策略再优化 50ms”。
毕竟,跳槽简历上写的“主导性能优化项目”,总比“熟练使用 Vue”听起来靠谱多了,对吧?
共勉。

评论 0