生产中的ES模块:我到目前为止的经验

2020-10-26 21:49:33

在过去的一年里,我一直在生产中运行一个由ES模块提供支持的单页Web应用程序。

这是一款javascript应用程序,但它不使用巴别塔、webpack、Rollup或任何其他工具来进行转换或捆绑。我在开发中编写的文件与在生产中提供给最终用户的文件相同。

这个应用程序是针对副项目…的。一个在线音乐盒歌曲制作工具。它不是一个庞大的应用程序,但也不算小--目前大约有60个JavaScript模块,这些模块混合了组件、实用程序和第三方库。代码库看起来很像一个ReactJS项目,但是它没有使用Reaction。它使用普通的JavaScript替代方案,将抽象(如JSX)替换为原生JavaScript特性(如模板字符串)。这个框架与这篇文章的目的无关,但如果你感兴趣,可以在我之前的文章中阅读更多关于它的内容。

当我在2019年8月发布这款应用时,业界的共识是,在生产中使用非捆绑的ES6模块是一个坏主意。Khan Academy尝试拆分他们的主页JS,并得出结论,这降低了他们最初的页面加载速度。那是五年前的事了,我至今还不知道有谁认真考虑跳过捆绑包,在生产中使用ES6模块。*。

这太糟糕了,因为现在浏览器对ES模块的支持非常好,似乎只需编写浏览器能够理解的JavaScript就可以避免很多无稽之谈(至少对于有意义的项目是这样)。

我一直在寻找人们这样做的例子,但我很难找到他们,所以我决定试一试,看看到底有多糟糕。这是我的发现:

开发经验。我原以为开发体验会很棒,事实也的确如此。没有安装说明,没有启动延迟。无需查看文件、生成源映射或等待重新编译。只需保存文件并刷新即可。✨。

部署。部署非常简单。我所需要做的就是按原样将代码复制到服务器。我的网络主机netlify使得在git推送上实现这一点变得很容易(不过,公平地说,netlify甚至可以让最复杂的设置也很容易部署)。

开发/生产奇偶校验。每次我发现生产缺陷时,我都能在本地复制它。这不是一个主要目标,但非常方便。

依赖项不支持ES模块。我经常发现我想使用的库,结果却发现它们不支持ES模块。它们通常支持CommonJS,这意味着我不能使用它们。起初,我通过加载使用浏览器全局变量的库版本(通过脚本标记或副作用导入)来解决这个问题。这很管用,但感觉并不理想。

最后,我开始使用SnowPack,它可以导入不支持ES模块的依赖项,并生成支持ES模块的一次性构建。它工作得非常好,我已经开始在其他项目中使用它。

环境变量。通常,我会在构建时分配这些参数,但在没有构建时就不能了。幸运的是,科里·豪斯有一个很棒的帖子描述了所有的选择。我最终使用了环境嗅探,这感觉有点奇怪,但最终对我的应用程序来说并不是什么大不了的事。

CSS组织。我使用传统的CSS,使用BEM约定,这很好。不过,我仍然想拆分我的文件,所以我使用了一个带有一堆@Imports的main.css文件。这感觉好多了,但是后来我有一个阻塞请求,延迟了页面呈现,所以我将@Imports移到了内联样式标记中。我不确定我是否喜欢,所以我可能会继续重复这一点。

缓存无效。我担心我在使缓存的CSS或JavaScript无效时会遇到麻烦(因为我不能依赖捆绑程序为我的资产指定缓存破坏的文件名)。事实证明,eTags是解决这个问题的一个很好的解决方案(特别是因为我的web主机有一个快速而简单的可靠实现)。我听说破坏缓存的文件名可能比eTag快一点,但我觉得Netlify的实现相当快。

性能。我听到的每一件事都说ES模块的性能会很糟糕,即使是使用HTTP2。所以我和…都做好了准备。这真是太棒了。除了确保我的初始HTML文件具有一些良好的默认标记之外,我甚至没有做任何优化。我怀疑性能很好,因为我的应用还没有大到可以开始遇到任何瓶颈(这项研究说,如果你低于几百个模块就可以了,这一点似乎得到了坊间的证实)。这让我意识到,我的直觉偏离了一款应用程序的“太大”。在您需要一次加载300-500个文件之前,您可以走很长一段路。至少,我觉得我的应用程序不太可能达到这些限制。

我有点担心没有缩小我的JavaScript。这不是节省了大量字节吗?事实证明,当您的文件以gzip(或brotli压缩,就像我的例子)提供服务时,差别要小得多。通过重命名变量和去掉注释,缩小仍然会使我的文件更小,但是差别比我预期的要小。

浏览器支持。因为我没有使用Babel,所以我预计会有很多跨浏览器的问题,但它们很少见。**事实证明,一旦你放弃了对IE11的支持,浏览器对现代JS特性的支持就真的很好了。箭头函数、const/let、模板字符串、ES6类和FETCH等都有超过95%的全局支持(包括IE11)。我唯一一次没有使用我真正想要的JS特性是可选的链运算符,该特性在未来一两年内可能会有95%的支持。长青浏览器是一个功能强大的东西。

我很惊喜。如果这是一个典型的、捆绑的、单页面的应用程序,我现在就需要处理一两个主要的工具升级。取而代之的是,我能够专注于功能。原生网络技术FTW!

如果我的模块数量太大,性能开始明显下降,我很有信心能够使用SnowPack来解决这个问题。从他们的文档中:

SnowPack将捆绑视为可选的生产优化,这意味着您可以自由地跳过捆绑的额外复杂性,直到需要为止。您应该能够使用捆绑器,因为您想这样做,而不是因为您需要这样做。

也许ES模块并不适用于每个项目,但它们在我的项目中工作得很好。如果说有什么根本性的缺陷,我还没有找到。

老实说,现在我很难想象以其他方式构建一个副业。