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

各位网友晚上好,相信大家都对使用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版本条件加载,是做到极致的水平。

相关推荐
程序员爱钓鱼1 小时前
Go操作Excel实战详解:github.com/xuri/excelize/v2
前端·后端·go
子兮曰9 小时前
async/await高级模式:async迭代器、错误边界与并发控制
前端·javascript·github
恋猫de小郭10 小时前
2026 Flutter VS React Native ,同时在 AI 时代 VS Native 开发,你没见过的版本
android·前端·flutter
GIS之路12 小时前
ArcGIS Pro 中的 Notebooks 入门
前端
IT_陈寒13 小时前
React状态管理终极对决:Redux vs Context API谁更胜一筹?
前端·人工智能·后端
Kagol14 小时前
TinyVue 支持 Skills 啦!现在你可以让 AI 使用 TinyVue 组件搭建项目
前端·agent·ai编程
柳杉14 小时前
从零打造 AI 全球趋势监测大屏
前端·javascript·aigc
simple_lau14 小时前
Cursor配置MasterGo MCP:一键读取设计稿生成高还原度前端代码
前端·javascript·vue.js
睡不着先生14 小时前
如何设计一个真正可扩展的表单生成器?
前端·javascript·vue.js
天蓝色的鱼鱼14 小时前
模块化与组件化:90%的前端开发者都没搞懂的本质区别
前端·架构·代码规范