HTML本身不参与Tree Shaking,但会干扰JS模块摇树效果:script标签直引、内联事件、CDN引入等方式使代码脱离模块系统,导致无法摇除未使用代码。

HTML 结构本身不会被 Tree Shaking,但它会实实在在地干扰 JS 模块的摇树效果——不是“没作用”,而是“起反作用”。
HTML 中 <script></script> 标签直接引用 JS 文件会绕过模块分析
Rollup、Webpack、Vite 都只从 JS 入口文件(如 src/index.js)开始构建依赖图。如果你在 HTML 里写:<script src="utils.js"></script>,那 utils.js 就完全游离在模块系统之外:
- 打包工具不会去读
utils.js的export,也不会检查你是否只用了其中某个函数 - 即使
utils.js是 ESM 格式,只要没被import进主链,它整个文件都会原样打进产物 - 更糟的是:如果它有副作用(比如往
window上挂方法),工具还会因安全顾虑不敢删任何东西
内联 <script></script> 或 onclick 会让打包工具误判函数“被使用”
HTML 里写 或 <script>initApp()</script>,等于告诉打包器:“这个函数名可能被运行时调用”,于是 handleClick 和 initApp 即使没被 JS 代码 import,也会被标记为“已使用”:
- Webpack 默认把所有全局函数名视为潜在入口点,除非你显式声明
"sideEffects": false -
html-webpack-plugin不会帮你分析这些调用,它只负责注入 script 标签 - Vue/React 的模板中用
v-on:click或onClick属于运行时绑定,不影响构建期摇树,但 HTML 原生onclick是硬编码字符串,无法静态判定
HTML 引用第三方库的路径方式决定你能否享受摇树
你用 import { debounce } from 'lodash-es' 能摇掉其他函数,但如果你在 HTML 里通过 CDN 引入:<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>,那就彻底放弃摇树机会:
- CDN 脚本是全局变量(
_),打包器无法识别哪些属性被用了 - 哪怕你在 JS 里写
const { debounce } = _,这属于运行时解构,不是静态 import,Tree Shaking 失效 - 想用摇树,必须走 ESM 路径:确保
package.json中该库有"module"字段,且你用的是import语法
真正容易被忽略的点:HTML 不参与摇树,但它是 JS 模块能否干净进入摇树流程的“闸门”。一个 data-action="loadData" 或一段内联 console.log(),都可能让整块逻辑保留在 bundle 里——不是因为代码写得不好,而是 HTML 把它“钉死”在了全局作用域。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











