HTML本身不参与代码拆分,所有模块化效果均依赖JS模块系统或构建工具;<link rel="import">已被废弃,fetch()+insertAdjacentHTML()无模块语义,仅构建时内联或Custom Elements配合import()才能真正联动代码拆分。

HTML 本身不参与代码拆分,所有“HTML 模块化”带来的拆分效果,都来自 JS 模块系统或构建工具的间接支持——直接写 <include src="header.html"> 不会自动触发代码分割,也不会生成独立 chunk。
为什么 <link rel="import"> 不能用于代码拆分
它早在 Chrome 73 就被全系移除,现在任何主流浏览器加载含该标签的页面,控制台只会报 Failed to load resource: net::ERR_UNKNOWN_URL_SCHEME 或静默失败。即使搭配 polyfill,Safari 和新版 Edge 也完全不认。它既不触发 JS 模块加载,也不被 Webpack/Vite 当作分割点,纯属历史包袱。
fetch() + insertAdjacentHTML() 能否触发代码拆分
不能。这种运行时加载只是把 HTML 字符串塞进 DOM,和 innerHTML 本质一样:无模块语义、无依赖声明、无法被构建工具识别为分割入口。它只解决“内容拼接”,不解决“资源按需加载”。
- 适合场景:局部刷新、A/B 测试组件、SPA 中折叠区块等轻量动态插入
- 必须加 fallback:网络失败时要有
<div class="loading">或错误提示 - 避免 XSS:绝不用
element.innerHTML = responseText;优先用insertAdjacentHTML('beforeend', html) - 缓存要手动控:重复请求同一 URL 时,加
fetch(url, { cache: 'force-cache' })或时间戳参数
真正能联动代码拆分的 HTML 模块化路径
只有两种方式能让 HTML 片段的“模块化”与 JS 代码拆分形成闭环:
立即学习“前端免费学习笔记(深入)”;
-
构建时内联:用
rollup-plugin-html或posthtml-include,在打包阶段把header.html等片段静态注入主 HTML。输出仍是单个文件,零运行时开销,且可配合 Webpack 的splitChunks把共用逻辑(如工具函数)抽成vendors.js -
Custom Elements + 动态 import():定义
<search-select>这类自定义元素,在其connectedCallback中调用await import('./search-select.js')。这时构建工具才能识别 import() 为分割点,生成独立 chunk,并按需加载 JS + 关联 CSS
注意:import() 的路径必须是字符串字面量(不能是变量拼接),否则 Webpack/Vite 无法静态分析;import.meta.url 是解析当前模块路径的唯一可靠方式,document.currentScript.src 在模块脚本里永远是 null。
容易被忽略的生命周期问题
Custom Element 实例被从 DOM 移除时,disconnectedCallback 里必须手动清理定时器、事件监听、fetch 中止信号(AbortController),否则内存泄漏比静态 include 更隐蔽。而构建时内联的方案,根本不存在这个环节——它压根没“加载”,也就谈不上“卸载”。



















