Bundle or Bundleless?一起来看看前端构建问题

Posted 高级前端进阶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bundle or Bundleless?一起来看看前端构建问题相关的知识,希望对你有一定的参考价值。

前言

Bundle or Bundleless?自 2015 年 ESM 标准发布后,路线之争就开始逐步升温。转眼间,时间已来到 2021 年。如果白酒的车你错过了,那么不妨看看 Bundleless,或许它就是前端圈的下一位「茅台」。

前端构建当下的问题

不得不说,曾经把自己定位为「打包器」的 Webpack,如今已形成强大的构建生态,俨然一统江湖。但前端构建的道路还远没有走到最后。随着业务的发展,前端工程的复杂度越来越高,构建方面的也开始暴露出新的问题。

构建时间逐步拉长

相信许多前端同学刚入行时,都经历过「刷新一下全都有」的幸福时光:写几个 html 标签,写几句内嵌代码,浏览器中就会呈现出美妙的 UI。而如今,业务工程越来越复杂,代码量连年增长,构建的时间也越来越长。曾经「秒级构建」的前端,终究跻身「分钟级构建」的圈子了。

前端工程构建时间的拉长,自然使得前端开发者在日常业务工作中的状态

模块标准引领方向

如果我们纵观前端领域的发展,就可以看到标准是如何推动各大浏览器建设,整个前端生态又是如何发生的变化。

2002 年,AJAX 推出,此后前端承担的工作越来越多。彼时,浏览器厂各行其是,因此兼容性是当时的主要问题。于是 2006 年,jQuery 的出现进一步带动了前端的发展。

2009 - 2011 年,CommonJS、AMD、UMD 相继为 JS 带来了模块规范。同一时期,部分遵循 CommonJS 的 Node 为 JS 带来了运行环境,为前端工程化的解锁奠定基础:

  • 模块加载工具开始涌现,如 RequireJS、SeaJS 等
  • 包管理工具,如 npm、spm 等
  • 轻量的打包器开始出现,如 Browserify
  • 任务工具开始出现,如 Gulp

Angular、React、Vue 等的相继火爆,也推动了前端的又一波浪潮:它们的发展提高了前端在业务中的表达能力,并向更高程度的工程化提出诉求。

2015 年,HTTP/2.0 推出,同时 JS 迎来了自己的模块标准 ESM:ES2015 一发布,Babel 就让开发者们用上了 ES Module,真香。于是此后的几年,Webpack & Babel 几乎成了前端工程化的代名词,甚至让人以为,前端工程化已成定局。

2018 年,Chrome、Safari、Firefox 相继完成了对 ESM 的支持。但得益于 Webpack 生态对 CommonJS、AMD、UMD 的支持,开发者们对 ESM 的享用更多是在编码阶段和一定程度的 Tree-shaking,在构建层面并没有直接的得利。

总结

当下时间点,出现了新的契机:
其一,「工程体积的日益增长」与「亟待提升的构建性能」之间的矛盾;
其二,「先进的前端模块标准」与「落后的前端模块规范」之间的矛盾。

Bundleless 为什么是答案

Bundleless 说到底,就是指无打包构建,与我们当下流行的打包构建相对,而打包器则是我们前端开发者用于将 JS 模块打包成单一的、可在浏览器内运行的文件的工具。

为什么过去需要打包

这一问题在社区也有非常多的总结,概况来讲,主要包括以下理由:

  • HTTP/1.1 各浏览器有并行连接限制
  • 浏览器不支持模块系统(如 CommonJS 包不能直接在浏览器运行)
  • 代码依赖关系与顺序管理

HTTP/1.1 各浏览器默认并行连接数

浏览器 Firefox 3+ Opera 12 Safari 5 IE 7 IE 10 Edge Chrome
并行连接 6 6 6 2 8 6 6

为什么开始尝试不打包

近几年时间,标准的确立、浏览器大厂和前端生态的跟进,使得「不打包」成为可能:

  • HTTP/2.0 多路并用
  • 各大浏览器逐一支持 ESM
  • 越来越多的 npm 包拥抱 ESM(尽管很多包的依赖并不是)

我们可以发现:

  • 通过打包来减少网络请求数量从而提高性能的优化手段理论上在 HTTP/2.0 下会变得不再必要;

  • ESM 标准的推广和各大浏览器的支持:

    • 让模块代码可以 直接在浏览器中运行
    • 原生的解决了 代码依赖和复用的问题
    • 会进一步推动越来越多的 npm 包支持 ESM,甚至会出现新的包管理或分发方式

Bundleless vs Bundle

模块加载的对比

如果是打包式构建,在模块加载时,实际上加载的是若干模块的集合。这种方式的优点是以少量的请求连接数完成 JS 脚本的下载。如果是无打包式构建,模块的加载则是基于原生模块方案,直接获取具体的模块脚本。

本地开发构建的对比

如果是打包式构建,无论是项目启动还是文件变更,都需要完整的走一遍打包过程。以 Webpack 为例,我们就会经历依赖分析、代码转译和打包的过程,哪怕我们只是简单的修改了一行文案。当然,Split chunk 会在一定程度上缓解这一问题,但粒度仍然偏大。

而无打包式构建,在启动过程中基本只是启动服务(当然不同的 Bundleless 方案可能还会做些其他的工作),而不用对业务代码进行依赖分析、打包,ESM 会帮助我们在浏览器中完成依赖的分析。当文件发生变更时,本地开发服务只是提供了文件的映射,只需要重新转译对应的文件,并重新替换即可。

结论

以上,我们可以知道:

  • 打包过程的必要性已降低
  • 拥抱 ESM 是未来趋势

社区在领域内的工作

概览

前端构建并不只是构建工具的问题。事实上,「构建」和「分发」共同组成了前端工程的构建,只不过通常情况下,我们是通过 npm install 将三方包下载下来,并打包到构建结果中实现的。

构建可以分为两种类型。

一种是基于服务的构建方式,通常服务于实际生产。我们可以再细分成本地服务构建和远端服务构建。本地服务构建就是我们常规的操作,目前基本已经被 Webpack 统治,是 Bundle 方案的代表;Snowpack、Vite、Web Dev Server 则是目前非常火的 Bundleless 方案,近一年的时间里势头迅猛。远端服务构建则是依托云能力的玩法,把构建过程放在服务端完成,从而把本地的开发流程搬到 Web 上,并给出于本地服务构建基本一致的体验。

另一种是基于浏览器的构建方式,通常面向 Demo 的快速搭建或预览方案。Codesandbox、StackBlitz、CodePen 和 Riddle 是业内较出色的方案,整体是在浏览器端实现代码的编译、打包、构建和运行。当然,具体到各个方案的细节,通常对服务还是有一定依赖。

目前来看,100% 在浏览器端进行打包、构建,现阶段并不是最理想的方案。随着 Bundleless 的发展,浏览器 Bundleless 和包分发平台的结合会得到进一步的发展,并逐步影响前端工程的架构。

以上是关于Bundle or Bundleless?一起来看看前端构建问题的主要内容,如果未能解决你的问题,请参考以下文章

Going Bundleless: ES Modules

前端构建这十年

Sonata Media Bundle 与 Sonata Admin Bundle 3.0(或 2.4)

前端构建这十年

Metro server (run ‘react-native start‘) or that your bundle ‘index.android.bundle‘ is packaged corre

Metro server (run ‘react-native start‘) or that your bundle ‘index.android.bundle‘ is packaged corre