部署和回滚只值两条命令
内部工具的生命周期通常很短:需求来得急,用的人少,维护的人往往就是写它的人。正因为如此,选择技术栈时最该考虑的是「半年后还有没有人敢改它」。我们团队这两年把十几个内部工具做成了纯静态页,下面几条是踩过坑之后留下的理由。
部署和回滚只值两条命令
静态页的产物就是一堆 html/js/css,扔进 nginx 目录或对象存储即可。我们的流水线只有一步:rsync -av --delete dist/ deploy@host:/var/www/tools/xxx/。回滚就是把上一版目录的软链指回去,或者 git revert 后重跑一次,全程不到半分钟。
对比带后端的工具,回滚要同时确认镜像版本、数据库 migration 是否兼容、环境变量有没有改过。静态页没有这些顾虑,因为它不持有任何持久状态,状态要么在 URL 里,要么在别人的数据库里。
认证和权限交给网关,前端不写登录
内部工具绕不开登录,但别在前端写登录页。用 nginx 的 auth_request 或 oauth2-proxy 挡在前面,未登录直接 302 到公司 SSO,登录成功后网关注入 X-User-Email 头,前端读它做按钮级权限即可。
这样做的好处是改权限不用发版:白名单写在网关配置里,加一个人只需要改一行并 reload。前端永远拿不到 token,也就没有把 token 写进 localStorage 被顺手拷走的风险。
数据从已有系统来,不新建数据库
大部分内部工具要的数据其实已经存在:订单在 MySQL、日志在 Loki、指标在 Prometheus。静态页不需要自己的库,直接调这些系统已有的 HTTP 接口。跨域麻烦就在同域下加一条 location /api/ { proxy_pass ... },前端统一 fetch('/api/...'),既避开 CORS,也顺便把凭据留在网关侧。
写操作也能做,但要求接口幂等:提交走已有服务,前端只负责校验、防重复点击和失败重试。如果某个流程真的需要事务和补偿,那它就不该被当成「小工具」,别硬塞进静态页。
状态放 URL,工具才能被分享
把筛选条件、分页、排序全部序列化进 URL:history.replaceState(null, '', '?' + params)。同事把链接发到群里,对方打开就是同一个视图,这比写一份「使用说明」有用得多。
- 个人偏好(列宽、暗色模式、上次选的仓库)放
localStorage,键名带版本号,例如tool.v2.columns,改结构时不会读到脏数据。 - 导出不需要后端:
new Blob([csv], {type:'text/csv'})加一个a.download就够,十万行以内浏览器毫无压力。 - 刷新即重置的临时状态(比如弹窗开关)不要写进 URL,否则后退键会变得很难用。
构建链越短,活得越久
我们分两档:一次性工具就一个 index.html,原生 JS 加 type="module",本地 python -m http.server 就能跑;稍复杂的用 Vite 构建,但坚持不引入需要常驻进程的依赖。新人接手时 npm i && npm run dev 三分钟看到页面,这直接决定了工具能活多久。
代价也要说清楚:静态页不适合高频写入、复杂权限矩阵、需要定时任务和长连接的场景。判断标准很简单——如果这个工具挂掉一天,业务会不会停。不会,那就放心用静态页。
- 点赞
- 收藏
- 关注作者
评论(0)