Open wsafight opened 4 years ago
当谈到前端构建工具,就不得不提的功能强大的 Webpack, 尤其是在最新版本中提出了 Module Federation 功能,该功能进一步增强了 Webpack 的实际作用。我相信凭借 Webpack 这几年的积累,恐怕未来几年内没有哪一个打包工具能够与之媲美,但是这并不妨碍我们探讨一下新的工具 Snowpack。
使用 Snowpack,当您构建现代的 Web 应用程序(使用React,Vue等),无需使用类似于 Webpack,Parcel 和 Rollup 等打包工具。每次您点击保存时,都无需等待打包程序重新构建。相反,所有的文件更改都会立即反映在浏览器中。
请关注立即这个词语, bundleless ? 这个究竟有什么意义?为什么我会这么重点关注这一个工具。
对于一些项目与开发者而言,可能对此没有太大的感触,但是对于我来说,开发中打包曾经是一个噩梦。几年前,我从头开发一个前端 Sass 项目,该项目开始时候就使用 Vue 以 Webpack 根据业务线构建多页面。几个月的时间过去,模块有了十几个。当我修改一个很小的地方时候,需要近一分钟的时候才能热更新完成。当时,我们只能在项目开启的时候设置那些页面需要编译。在忍受了一周后,我们不得不开始拆分项目,因为开发人员和项目开发效率的原因,我们不可能根据业务拆分项目。我们只能把项目中改动较少的的基础服务以及封装的业务组件给提取出去。利用 Webpack 的 externals 来辅助开发。这个方案很好的解决了项目当时的痛点。同时,这件事也让我对于模块划分和性能优化有了一定的认识和见解。
所以,在我看来,bundleless 解决了大部分前端开发者 的一大痛点,就是心流。当一个程序员被打搅后,他需要 10 - 15 分钟的时间才能重新恢复到之前的编程状态。当你在完成一小块功能时候,想要去查看结果时候,发现当前的项目还在构建状态,这个时候很有可能就会中止心流。
当然,还有一些高明的程序员是完成整块功能再去查看结果。同时开发的 bug 也非常少。该工具对于此类程序员的帮助也不大。谈到这里,我很想要多说两句,虽然程序员在开发中需要学习和使用大量的工具辅助开发,事实上很多工具也确实能够提升效率,但是有时候需要逼自己一把,把自己置身于资源不那么足够的情况下,因为只有这样才能真正的提升能力。这里我推荐一篇博客 断点单步跟踪是一种低效的调试方法,不管大家是认可还是否认,我认为都可以从这篇博客中得到思考。
就目前成熟的前端框架来说,都会提供一套脚手架工具以便用户使用。之前我们也是把项目直接从 Webpack 转到了 Vue Cli 3。因为 Vue Cli 3 内部封装了 Webpack, 基本上在开发中已经不需要进行 Webpack 基础性配置,同时我们所需要的依赖项目也大大减少了,底层的依赖升级也转移到了 Vue Cli 上,这也变相的减少了很多的开发量。
在探讨 Snowpack 这个新的构建工具之前,我要抛出一个问题,我们究竟为什么要使用 Webpack?
一个当然是因为 Webpack 确实提供了很多高效有用的工程实践为前端开发者赋能。如果让我们自行研究与使用,需要投入的时间以及掌握的知识远远高于配置学习成本。第二个就是因为它本身是一个静态的 JavaScript 应用程序的静态模块打包工具,首要的重点就在于工具为前端提供了模块与打包。
当年的 JavaScript 设计之初为了保持简单,缺少其他通用语言都具有的模块特性。而该特性正是组织大型,复杂的项目所必须的。但当年的 JavaScript 的工作就是实现简单的提交表单,寥寥几行代码即可实现功能。即使 Ajax 标志 Web 2.0 时代的到来阶段,前端开发的重点还是放在减少全局变量上,于是我们开始使用 IIFE(立即调用函数表达式)来减少全局变量的污染, 而 IIFE 方法存在的问题是没有明确的依赖关系树。开发人员必须以准确的顺序来组织文件列表,以保证模块之间的依赖关系。由于当时网页短暂的生命周期以及后端渲染机制保证了网页的依赖是可控的。
在之后,Node.js 出世,让 JavaScript 可以开发后端,在 Node.js 的许多创新中,值得一提的是 CommonJS 模块系统,或者简称为CJS。 利用 Node.js 程序可以访问文件系统的事实,CommonJS 标准更具有传统的模块加载机制。 在 CommonJS 中,每个文件都是一个模块,具有自己的作用域和上下文。当然,虽然这种机制也底层来自也来自于 IIFE(立即调用函数表达式)。这种创新的爆发不仅来自创造力,还来自于自于必要性:当应用程序变得越来越复杂。 控制代码间的依赖关系越来遇难,可维护性也越来越差。我们需要模块系统以适应那些扩展以及变更的需求,然后围绕它们的生态系统将开发出更好的工具,更好的库,更好的编码实践,体系结构,标准以及模式。终于,伴随模块系统的实现,JavaScript 终于具有了开发大型复杂项目的可能性。
虽然在此之后开发了各式各样的模块加载机制,诸如 AMD UMD 等,但是等到 ES6 的到来。JavaScript 才正式拥有了自己的模块,通常称为ECMAScript模块(ESM)。也是 SnowPack 依赖的基础,这一点我们后面展开来说。
相比于CommonJS , ES 模块是官方标准,也是 JavaScript 语言明确的发展方向,而 CommonJS 模块是一种特殊的传统格式,在 ESM 被提出之前做为暂时的解决方案。 ESM 允许进行静态分析,从而实现像 tree-shaking 的优化,并提供诸如循环引用和动态绑定等高级功能。同时在 Node v8.5.0 之后也可以在实现标准的情况下使用 ESM,随着Node 13.9.0 版本的发布,ESM 已经可以在没有实验性标志的情况下使用。
Webpack 一方面解决了前端构建大型项目的问题,另一方面提供了插件优化 Web 前端性能。例如从资源合并以及压缩上解决了 HTTP 请求过程的问题,把小图片打包为 base64 以减少请求量,提供 Tree-Shaking 以及动态导入。伴随着 HTTP 协议的升级以及网速的不断加快,我也希望日后这些工作慢慢变成负担。
SnowPack 是基于 ESM 的工具。想要通过一次安装来替换每次更改时候重建的构建步骤。ESM 现在可以在浏览器中使用了! 我们可以使用 [Can i use]()了解一下 ESM 的可以使用性。
可以看到,基本上现代浏览器都已经提供了支持,事实上我们也不需要等到所有的浏览器提供支持。
我们不需要为所有浏览器提供一致性的体验,我们也做不到这一点。事实上,我们在这件事情上是可以做到渐进增强的。对于不支持的浏览器,完全无法理解该语句,也不会去 js 加载。例如可以提供页面预加载的前端库 instant.page。该库在不支持 ESM 的浏览器上压根不会执行。
同时对于暂时不支持的浏览器来说,依然可以加载 js ,唯一需要做的就是为不支持 Githubissues.
当谈到前端构建工具,就不得不提的功能强大的 Webpack, 尤其是在最新版本中提出了 Module Federation 功能,该功能进一步增强了 Webpack 的实际作用。我相信凭借 Webpack 这几年的积累,恐怕未来几年内没有哪一个打包工具能够与之媲美,但是这并不妨碍我们探讨一下新的工具 Snowpack。
现代打包工具的问题
使用 Snowpack,当您构建现代的 Web 应用程序(使用React,Vue等),无需使用类似于 Webpack,Parcel 和 Rollup 等打包工具。每次您点击保存时,都无需等待打包程序重新构建。相反,所有的文件更改都会立即反映在浏览器中。
请关注立即这个词语, bundleless ? 这个究竟有什么意义?为什么我会这么重点关注这一个工具。
对于一些项目与开发者而言,可能对此没有太大的感触,但是对于我来说,开发中打包曾经是一个噩梦。几年前,我从头开发一个前端 Sass 项目,该项目开始时候就使用 Vue 以 Webpack 根据业务线构建多页面。几个月的时间过去,模块有了十几个。当我修改一个很小的地方时候,需要近一分钟的时候才能热更新完成。当时,我们只能在项目开启的时候设置那些页面需要编译。在忍受了一周后,我们不得不开始拆分项目,因为开发人员和项目开发效率的原因,我们不可能根据业务拆分项目。我们只能把项目中改动较少的的基础服务以及封装的业务组件给提取出去。利用 Webpack 的 externals 来辅助开发。这个方案很好的解决了项目当时的痛点。同时,这件事也让我对于模块划分和性能优化有了一定的认识和见解。
所以,在我看来,bundleless 解决了大部分前端开发者 的一大痛点,就是心流。当一个程序员被打搅后,他需要 10 - 15 分钟的时间才能重新恢复到之前的编程状态。当你在完成一小块功能时候,想要去查看结果时候,发现当前的项目还在构建状态,这个时候很有可能就会中止心流。
当然,还有一些高明的程序员是完成整块功能再去查看结果。同时开发的 bug 也非常少。该工具对于此类程序员的帮助也不大。谈到这里,我很想要多说两句,虽然程序员在开发中需要学习和使用大量的工具辅助开发,事实上很多工具也确实能够提升效率,但是有时候需要逼自己一把,把自己置身于资源不那么足够的情况下,因为只有这样才能真正的提升能力。这里我推荐一篇博客 断点单步跟踪是一种低效的调试方法,不管大家是认可还是否认,我认为都可以从这篇博客中得到思考。
前端项目的演进
就目前成熟的前端框架来说,都会提供一套脚手架工具以便用户使用。之前我们也是把项目直接从 Webpack 转到了 Vue Cli 3。因为 Vue Cli 3 内部封装了 Webpack, 基本上在开发中已经不需要进行 Webpack 基础性配置,同时我们所需要的依赖项目也大大减少了,底层的依赖升级也转移到了 Vue Cli 上,这也变相的减少了很多的开发量。
在探讨 Snowpack 这个新的构建工具之前,我要抛出一个问题,我们究竟为什么要使用 Webpack?
一个当然是因为 Webpack 确实提供了很多高效有用的工程实践为前端开发者赋能。如果让我们自行研究与使用,需要投入的时间以及掌握的知识远远高于配置学习成本。第二个就是因为它本身是一个静态的 JavaScript 应用程序的静态模块打包工具,首要的重点就在于工具为前端提供了模块与打包。
当年的 JavaScript 设计之初为了保持简单,缺少其他通用语言都具有的模块特性。而该特性正是组织大型,复杂的项目所必须的。但当年的 JavaScript 的工作就是实现简单的提交表单,寥寥几行代码即可实现功能。即使 Ajax 标志 Web 2.0 时代的到来阶段,前端开发的重点还是放在减少全局变量上,于是我们开始使用 IIFE(立即调用函数表达式)来减少全局变量的污染, 而 IIFE 方法存在的问题是没有明确的依赖关系树。开发人员必须以准确的顺序来组织文件列表,以保证模块之间的依赖关系。由于当时网页短暂的生命周期以及后端渲染机制保证了网页的依赖是可控的。
在之后,Node.js 出世,让 JavaScript 可以开发后端,在 Node.js 的许多创新中,值得一提的是 CommonJS 模块系统,或者简称为CJS。 利用 Node.js 程序可以访问文件系统的事实,CommonJS 标准更具有传统的模块加载机制。 在 CommonJS 中,每个文件都是一个模块,具有自己的作用域和上下文。当然,虽然这种机制也底层来自也来自于 IIFE(立即调用函数表达式)。这种创新的爆发不仅来自创造力,还来自于自于必要性:当应用程序变得越来越复杂。 控制代码间的依赖关系越来遇难,可维护性也越来越差。我们需要模块系统以适应那些扩展以及变更的需求,然后围绕它们的生态系统将开发出更好的工具,更好的库,更好的编码实践,体系结构,标准以及模式。终于,伴随模块系统的实现,JavaScript 终于具有了开发大型复杂项目的可能性。
虽然在此之后开发了各式各样的模块加载机制,诸如 AMD UMD 等,但是等到 ES6 的到来。JavaScript 才正式拥有了自己的模块,通常称为ECMAScript模块(ESM)。也是 SnowPack 依赖的基础,这一点我们后面展开来说。
相比于CommonJS , ES 模块是官方标准,也是 JavaScript 语言明确的发展方向,而 CommonJS 模块是一种特殊的传统格式,在 ESM 被提出之前做为暂时的解决方案。 ESM 允许进行静态分析,从而实现像 tree-shaking 的优化,并提供诸如循环引用和动态绑定等高级功能。同时在 Node v8.5.0 之后也可以在实现标准的情况下使用 ESM,随着Node 13.9.0 版本的发布,ESM 已经可以在没有实验性标志的情况下使用。
Webpack 一方面解决了前端构建大型项目的问题,另一方面提供了插件优化 Web 前端性能。例如从资源合并以及压缩上解决了 HTTP 请求过程的问题,把小图片打包为 base64 以减少请求量,提供 Tree-Shaking 以及动态导入。伴随着 HTTP 协议的升级以及网速的不断加快,我也希望日后这些工作慢慢变成负担。
ESM (ecmascript module) 已经到来
SnowPack 是基于 ESM 的工具。想要通过一次安装来替换每次更改时候重建的构建步骤。ESM 现在可以在浏览器中使用了! 我们可以使用 [Can i use]()了解一下 ESM 的可以使用性。
可以看到,基本上现代浏览器都已经提供了支持,事实上我们也不需要等到所有的浏览器提供支持。
我们不需要为所有浏览器提供一致性的体验,我们也做不到这一点。事实上,我们在这件事情上是可以做到渐进增强的。对于不支持的浏览器,完全无法理解该语句,也不会去 js 加载。例如可以提供页面预加载的前端库 instant.page。该库在不支持 ESM 的浏览器上压根不会执行。
同时对于暂时不支持的浏览器来说,依然可以加载 js ,唯一需要做的就是为不支持 Githubissues.