当我把前端条件加载做到极致

各位网友晚上好,相信大家都对使用type="module"和nomodule这种技巧有所耳闻。今天我将为大家分享我把这种技巧应用到极致的经验:4 条件加载方案。

什么是分条件加载

在前端构建中,我们通常需要进行 Babel 语法降级和 polyfill 插入等操作以兼容低版本浏览器。但这会导致一个问题:在现代浏览器中也会加载大量兼容性代码,无法享受浏览器原生支持的新特性带来的性能优势。

分条件加载的核心思想是:为不同能力的浏览器提供差异化的构建产物。最基础的实现就是利用 HTML5 标准中的type="module"和nomodule属性进行区分:

html 复制代码
<!-- 仅供参考 -->
<script type="module" src="modern-bundle.js"></script>
<script nomodule src="legacy-bundle.js"></script>

这样在支持 ES Module 的浏览器中会加载type="module"的脚本,而不支持的浏览器会忽略这个标签并加载带有nomodule属性的脚本。通过这种方式,现代浏览器就能直接运行原生 class、ES Module、解构赋值等新特性,无需加载冗余的兼容性代码。

3 个条件的分条件加载

由于IE8与IE9之间有巨大的差异,因此在上述2个版本的构建产物之上,使用条件注释在分出第3个版本专用于IE8及以下。

html 复制代码
<!-- 仅供参考 -->
<!--[if gte IE 9]><!-->
<script type="module" src="modern-bundle.js"></script>
<script nomodule src="legacy-bundle.js"></script>
<!--><![endif]-->
<!--[if lte IE 8]>
  <script src="ie8-bundle.js"></script>
<![endif]-->

这样IE8及以下加载特制兼容包可以更加精简,其他版本也能避开恶心的兼容代码。

为什么需要分4条件加载

分3个版本似乎己经够用了,但是随着top-level-await的出现,变得不够用了。使用type="module"和nomodule分版本的一个目的就是能使用原生esmodule 。而top-level-top出现后,无法用旧有的esmodule实现top-level-await。因此只能使用传统方式,比如构建成AMD格式 ,用AMD加载器加载。因此我们可以进一步细分出一个版本。 现在我们有4个版本了

  • IE8及以下
  • 不支持原生esm的版本(chrome4~chrome60)
  • 支持原生esm但不支持top-level-await(chrome61~chrome89)
  • 原生支持top-level-await的浏览器(chrome90+)

注意哦,上面最新的版本是chrome90,现在都chrome130+了,随着浏览器的更新,我希望用新浏览器的用户能够直接运行新特性,因此我需要用一个较新的特性做区分,于是我选择了Promise.try。现在的4个版本改变为

  • IE8及以下
  • 不支持原生esm的版本(chrome4~chrome60)
  • 支持原生esm但不支持Promise.try(chrome61~chrome127)
  • 原生支持Promise.try的浏览器(chrome128+)

这里我选择了Promise.try 是因为我还没有在公司推开es2025的使用,业务人员是不允许使用es2025的特性,代码中也必然不存在es2025的代码。等我在公司构建工具链中做完了es2025的降级处理,就会把用Promise.try判断,改成用更新的特性来判断。

html 复制代码
<!-- 仅供参考 -->
<!--[if gte IE 9]><!-->
<script type="module">
if(Promise.try){__import__("xxxx")}else{__import__("yyyy")}
</script>
<script nomodule src="legacy-bundle.js"></script>
<!--><![endif]-->
<!--[if lte IE 8]>
  <script src="ie8-bundle.js"></script>
<![endif]-->

最后我们看看打包后的运行效果。我们发现在最新浏览器中没有polyfill引用,也可以原生运行top-level-await。

总结

通过多条件加载,可以在全浏览器兼容的前提下,减少新式浏览器的加载内容大小。分4版本条件加载,是做到极致的水平。

相关推荐
前端一小卒4 小时前
搜索 API 额度用完返回空数组,Agent 就开始一本正经地胡说
前端·javascript·node.js
乘风gg4 小时前
Spec Kit vs OpenSpec vs Superpowers:三大 AI Coding 框架深度对比
前端·ai编程·claude
w2sfot5 小时前
AI时代,JS加密还有效吗?
开发语言·前端·javascript
风骏时光牛马5 小时前
AI服务线上接口异常导致响应中断
前端
haluhalu.5 小时前
Agent = LLM + 上下文 + 工具(含观察 / 动作空间、ReAct 循环)
前端·javascript·人工智能·python·react.js·机器学习·个人开发
子兮曰10 小时前
把 649 种文件格式塞进一个网页里:一个「文件不出浏览器」的预览器
前端·javascript·后端
sm_9267870513 小时前
RFID 标签打印的技术实现要点与二次开发实践
java·大数据·前端·c++·编辑器
IMPYLH14 小时前
HTML 的 <video> 元素
前端·html
溪语流沙14 小时前
【每天一个CSS | Day19】流光文字与一笔写成的手写签名
前端·javascript·css
逐光者93314 小时前
STM32——SPI 屏 · Flash · 高速
java·前端·stm32