前端构建工具的未来
前端构建工具对于现代前端开发人员的工作流程至关重要,原因有很多,包括改善开发人员和用户体验。从开发者的角度来看,前端工具为我们提供了:编写模块的能力、用于本地开发的开发服务器、在开发模式下缩短反馈循环的热模块替换(HMR)、使用polyfills针对传统浏览器的能力、处理除JavaScript以外的一系列文件类型,等等。
因此,用户可以享受能力更强、功能更丰富的应用程序,通过代码分割、缓存、预取和其他资源优化技术保持性能--有些应用程序甚至能够离线工作。
今天,前端工具为我们提供了如此之多的东西,以至于很难想象曾经有一段时间甚至根本不需要它。回忆一下,可以帮助我们理解我们是如何走到今天的。
过去
在前端应用程序变得像今天这样复杂之前,所有的JavaScript都是用来为其他简单的HTML文档添加基本的交互性的--类似于Adobe的Flash的使用方式。
当时没有复杂的 "JavaScript重度 "应用,所以也不需要任何工具来使JavaScript的编写和传输变得更好,但这种情况不会一直存在。
随着时间的推移,我们开始在网络上创造更多的用户体验,我们从更多的静态网页转向服务于用户特定数据的高度动态网络应用。这些应用程序比传统的应用程序需要更多的JavaScript,而使用JavaScript的局限性也变得更加明显。
在浏览器中,有两种主要的方法来加载JavaScript。一种是用脚本标签引用JavaScript文件,另一种是将你的JavaScript直接写在HTML的脚本标签里:
<script src="my-javascript-file.js"></script>
<script>
var a = 1;
var b = 2;
var result = a + b;
</script>
当你有大量的JavaScript需要加载时,这种对加载JavaScript的限制就成为一个瓶颈。同时加载许多JavaScript文件有浏览器的限制,而拥有一个巨大的JavaScript文件也有可维护性的问题(比如文件大小、范围问题、命名空间碰撞等等)。
我们想出了一些解决方案,如立即调用函数表达式(IIFEs),以帮助解决封装和一些范围问题,之后,我们获得了在许多不同文件中编写JavaScript的能力。然后,我们需要一种方法,将这些文件合并成一个文件,在浏览器中提供服务。
现在
由于能够用IIFEs将我们的JavaScript分割成不同的文件,我们似乎只需要一种方法将这些文件连接起来,然后将一个文件送到浏览器中。在这种需求下,Gulp、Grunt、Brocolli等工具应运而生。然而,我们很快意识到,我们的想法可能有点过于简单。
随着我们的应用程序变得更加复杂,诸如缺乏死代码的消除、小改动的全面重建以及其他性能问题使我们意识到,我们需要的不仅仅是连接的东西。这就催生了更现代的捆绑器,如Webpack、Parcel等。
随着前端领域的发展步伐没有放缓,我们已经开始观察到现代构建工具的差距和问题。
一些主要的限制包括:
- 一些现有捆绑工具的复杂设置和配置。
- 随着应用程序的增大,构建时间也在增加。
- 开发模式下的次优性能。
在JavaScript生态系统中,事物变化的速度往往让人感到疲惫,但好处是社区能迅速发现问题,并着手解决潜在的解决方案。我们的目标是提高前端工具的性能,新一代的构建工具正在开发中。
未来
当今主流构建工具的局限性导致了一些尝试,以重新想象一个前端构建工具应该是什么,做什么,今天有相当多的新构建工具在野外。
仔细观察会发现,这些新工具似乎采取了两种主要方式来解决问题(不一定相互排斥):范式的改变和平台的改变--两者都由网络开发生态系统的新进展所驱动。
重置平台
前端构建工具传统上都是用JavaScript构建的,最近则是用Typescript。这是有道理的,因为JavaScript是网络语言,用同样的语言编写网络构建工具,可以让更多的人参与进来,并围绕这些工具建立一个社区。不过,这种方法也有固有的问题。
作为一种高级语言,JavaScript无法达到原生的性能水平。这意味着建立在这个平台之上的工具在性能上有一个上限。因此,为了突破这个限制,新的构建工具正在建立在低级别的、内在性能更强的语言上,比如Rust。
像Rust和Go这样的语言已经成为编写下一代构建工具的热门选择,并强烈强调性能。特别是Rust,不仅因其性能而受欢迎,还因其令人印象深刻的开发者体验--在Stack Overflow开发者调查中连续六年被评为 "最受喜爱的 "编程语言。
在谈到用Rust构建罗马(构建工具而不是城市)的决定时,Jamie Kyle说。
"在我们之前,许多人已经传达了Rust在性能、内存和安全方面的好处--我们只能说所有说过Rust好的人都是正确的。然而,我们最关心的是我们自己的生产力。 [......]然而,经过一些原型设计,我们很快意识到我们实际上可能在Rust中更有生产力。"
SWC项目是将Rust用于前端构建工具这一想法的最前沿。它现在正在为Next.js的新编译器、Deno、Parcel等项目提供动力--其性能比其他现有的构建工具高出许多个数量级。
像SWC这样的项目证明,随着底层平台的改变,构建工具的性能可以得到显著提高。
范式的转变
今天,典型的前端构建管道的工作方式是,你在许多不同的文件中编写JavaScript模块,运行一个命令,构建工具收集这些模块,将它们捆绑成一个模块,将它们转换为浏览器能够理解的格式,然后在浏览器中提供该文件。
为了提高开发模式下的性能,很多需要更多时间才能完成的优化被排除在外,而是在我们捆绑生产应用时运行。这就确保了在开发模式下运行我们的应用程序并取得成效时,需要尽可能少的时间来启动一个开发服务器。
但捆绑过程仍然需要相当长的时间,而且随着项目的发展,构建时间(即使在开发中)也会越来越长。如果我们能以某种方式完全跳过捆绑,同时还能像往常一样编写模块,并让浏览器了解如何使用它们,那不是很好吗?一组新的构建工具正在采用这种方法,被称为 "非捆绑式开发"。
捆绑式开发很好。它解决了现有构建工具的一个主要问题:即使是微不足道的代码修改,它们也经常需要重建你的应用程序的整个部分,而且随着应用程序的增长,构建时间也越来越长。我们失去了快速的反馈--这对愉快的开发体验至关重要。
有人可能会问,如果非捆绑式开发如此之好,为什么它不是今天的常态呢?有两个主要的原因导致非捆绑式开发才开始受到重视:尖端功能的浏览器兼容性和处理节点模块导入。
1.浏览器对尖端功能的兼容性
捆绑式开发由ES模块(ESM)提供支持,它为JavaScript带来了一个标准化的模块系统--在包括浏览器在内的多个运行时中得到原生支持。有了这种新的能力,我们可以把我们的脚本标签标记为模块,从而可以使用我们都熟悉的import 和export 关键字:
<script type="module" src="main.js"></script>
<script type="module">
/** JavaScript module code goes here */
</script>
ES模块已经存在了很长时间了。尽管如此,我们仍然只能在非捆绑式开发等方面开始利用它,主要是因为它的标准化在网络生态系统的所有参与者中花了多长时间。
在她关于ES模块的文章中,在Mozilla Hacks上,Lin Clark说。
"ES模块为JavaScript带来了一个官方的、标准化的模块系统。不过,它花了一些时间才走到这一步--将近10年的标准化工作。"
浏览器支持或缺乏支持的问题已经困扰了前端开发很长时间了。这就是为什么我们的CSS要有供应商的前缀,有时是polyfills的原因,为什么我们要花时间确保我们的网络应用的跨平台支持,以及为什么我们有时需要相当长的时间才能在日常工作中利用最新和最伟大的网络功能。
试着用Safari浏览器访问StackBlitz项目,你会看到以下屏幕,说明在非基于Chromium的浏览器中缺乏对WebContainers的支持。
各个浏览器供应商采用功能的速度并不一样,而且不同供应商实现某些功能的方式也常常有差异。然而,随着Interop 2022等倡议的提出,未来的前景是光明的。
2.处理节点模块导入
我们今天编写的大多数(如果不是全部)前端应用程序都依赖于NPM的外部库。对于一个典型的react应用,我们会在组件文件的顶部像这样导入react。
import React from 'react'
/** The rest of your component code */
试图在浏览器中直接加载这个,就像我们在非捆绑式开发中需要做的那样,会导致两个问题。首先,浏览器不知道如何解析路径以找到react ;其次,react库是作为通用JS(CJS)模块发布的--不经过一些预处理,它不能在浏览器中原生运行。
后者是这里更大的问题,因为有可能,甚至是微不足道的,简单地用特定文件的相对路径替换我们的节点模块导入。然而,大多数NPM包是以更适合Node JS而不是浏览器的模块格式编写的,这就要求我们对NPM的依赖关系进行特殊处理,以促进非捆绑式开发。
特别是Snowpack,它通过将应用程序的依赖关系处理成独立的Javascript文件,然后可以直接在浏览器中使用。更多关于Snowpack如何做到这一点的信息可以在这里找到。
随着ES模块成为大多数现代浏览器的主流,以及对NPM依赖的巧妙变通,像Vite和Snowpack这样的构建工具可以提供非捆绑式开发的选择,并大幅提高性能,快速构建,以及超快的HMR。
最后的思考
前端开发已经走过了漫长的道路,我们的需求也在不断地发展和增加复杂性。构建工具是我们构建前端应用程序的一个重要部分,而现有的工具已经不能满足要求了,这就引发了新工具的开发,重新设想了构建工具应该如何设计。
随着对性能、易用性和不太复杂的配置的极大关注,新一代的构建工具准备在未来一段时间内为雄心勃勃的前端应用提供动力。
你对这个领域的最新发展感到兴奋吗?请在评论中告诉我你对即将到来的创新和目前的情况有何看法。
