现代Web开发:构建Bootstrap竟需500个包
内容提要
作者为定制Bootstrap主题,被迫安装数百个npm包、占用数十MB空间。尝试webpack、Gulp等工具后发现依赖臃肿,充斥重复无用的单行包(如is-even、各类ansi颜色库),并涉及众多许可证。最终改用Bash配合Sass和postcss,将依赖从545个降至144个。作者批评现代Web开发生态依赖泛滥、代码未经审计,存在安全隐患。
延伸解读
依赖膨胀的根源:工具链的间接依赖
文章指出,545个包中大部分来自gulp/gulp-cli(384个)和node-sass(177个),而非直接使用的Sass或Autoprefixer本身。这说明现代前端构建工具的依赖树往往由工具链的间接依赖主导,开发者真正需要的功能只占少数。即使改用Bash加postcss-cli,依赖仍达438个,直到自定义Node脚本才降至144个。读者应意识到,减少依赖的关键在于替换掉那些自带大量间接依赖的构建工具,而非仅仅精简直接依赖。
微包与许可证:被忽视的合规风险
作者在node_modules中发现大量单行包,如is-even、is-odd、number-is-nan以及多个ansi颜色库,它们功能简单却各自带有版权和许可证。通过license-checker统计,依赖涉及MIT、ISC、Apache-2.0、BSD、CC-BY等多种许可证,甚至出现4-clause BSD这类含广告条款的旧许可证。文章提醒,开发者通常不清楚自己依赖的许可证义务,而数百个贡献者的授权叠加,可能给项目带来合规负担。
从545到144:精简依赖的可行路径
作者最终用Bash脚本配合dart-sass、postcss-cli和自定义Node脚本,将依赖从545个降至144个,node_modules从51 MiB减至21 MiB。关键改动包括:用dart-sass替代node-sass,用cssnano替代csso,并去掉Gulp,改用直接调用postcss的脚本。虽然仍新增了get-stdin这一依赖,但因其无子依赖而被接受。这表明,在不完全脱离npm生态的前提下,通过替换重型工具和减少中间层,可以显著压缩依赖规模。
未审计代码的安全隐患
文章强调,这些依赖大多是未知、未经审计的代码,并引用left-pad删除导致Babel构建失败、event-stream被植入窃取加密货币代码的事件。作者还发现部分包中残留.DS_Store文件,暗示发布内容缺乏清理。对于仅需编译CSS的简单任务,却引入数百个来自众多贡献者的包,意味着攻击面被不必要地放大。读者应关注依赖来源和发布内容,而非仅看包数量。
Q&A
为什么作者说现代Web开发构建Bootstrap需要500多个包?
作者在定制Bootstrap 4主题时,需要手动编译Sass并使用Autoprefixer,这导致他尝试了webpack和Gulp等工具,最终安装了545个npm包,占用51 MiB磁盘空间。这些依赖包括许多微小的、重复的包,如is-even、各种ansi颜色库等。
作者最终如何将依赖从545个减少到144个?
作者放弃Gulp,改用Bash脚本配合dart-sass和postcss-cli(通过npx调用),后来进一步用自定义Node脚本替代npx postcss,仅依赖get-stdin等少量包。最终依赖降至144个,占用21 MiB。
node_modules中有哪些令人哭笑不得的微小包?
例如is-even(仅调用is-odd)、is-odd(依赖is-number)、number-is-nan(一行polyfill)、ansi-gray(调用ansi-wrap)、has-ansi(一行正则检查)等。这些包功能极其简单,却作为独立包发布并广泛依赖。
使用大量npm依赖可能带来哪些风险?
作者指出,依赖泛滥导致代码未经审计,存在安全隐患。例如left-pad事件导致Babel构建失败,event-stream被篡改用于窃取加密货币。此外,众多许可证(如4-clause BSD)可能带来法律风险。
作者对现代Web开发中的工具链有什么批评?
作者批评工具链复杂且文档糟糕,例如webpack要求用JS导入CSS,Gulp依赖过多。他认为许多工具是不必要的,简单的任务应该用简单的方法(如Bash脚本)完成,而不是引入大量依赖。
作者如何用Bash脚本实现Bootstrap主题的构建?
作者最初用Bash调用sass编译SCSS,然后手动通过Autoprefixer网页处理,再用curl调用cssminifier.com压缩。后来改进为用sass管道到postcss(通过npx)自动完成前缀和压缩,最终用自定义Node脚本替代npx。