为什么把 mermaid 从依赖里删掉
装了又卸。npm audit 报出五个高危漏洞,链条全在 mermaid 的解析器依赖上,最后改成从 CDN 懒加载。
踩坑记录。结论先放前面:mermaid 不要装成 npm 依赖,改成浏览器里按需从 CDN 加载。
事情经过
画流程图需要 mermaid。第一反应是照常规做法装包:
npm install mermaid
装完顺手跑了一次审计:
npm audit
输出里跳出 5 个 high:
| 漏洞 | 位置 | 类型 |
|---|---|---|
lodash-es | @chevrotain/* 链路 | Code Injection via _.template |
lodash-es | @chevrotain/* 链路 | Prototype Pollution via _.unset |
lodash-es | @chevrotain/* 链路 | Prototype Pollution via _.omit |
问题不在 mermaid 本身,在它用来做语法解析的 chevrotain 那一串依赖,里面拖着 lodash-es。这些包是运行时进浏览器的,不是只在构建期跑。
怎么处理的
先把包卸掉:
npm uninstall mermaid
再审计一次:
npm audit
结果是 found 0 vulnerabilities。
然后改成在页面里按需加载。只有页面真的出现 <div class="mermaid"> 时才去 CDN 拉脚本,其他页面一个字节都不下载。代价是离线环境下图表渲染不出来,这个已经写进关于页的已知边界里了。
取舍要说清楚
卸包解决的是「这些代码没有被我们的构建产物打包进去」。CDN 那条路是另一件事:图表源码会经过第三方 CDN。图表里如果不放敏感内容,这个代价可以接受;要放敏感内容,就得把 mermaid 自托管到
public/下面。
顺带说一个更常见的坑
不是所有依赖都值得装。判断标准大概三条:
- 它是不是只在某一个页面用得到?是的话,按需加载比打进主包划算。
- 它是运行时依赖还是构建期依赖?构建期的包不进用户浏览器,风险小一截。
- 它拖进来多少间接依赖?
npm ls <包名>能看清整棵树,树太深就要警惕。
可复现的检查清单
npm install <候选包>
npm audit # 看有没有漏洞
npm ls <候选包> # 看依赖树有多深
npx depcruise src # 可选,看模块耦合
不满意就 npm uninstall 回退,npm 里这是无损操作。
给之后的自已
加任何依赖之前先看一眼依赖树。省下来的排查时间比省下来的配置时间多得多。