Parcel 2 beta 1
📦 Parcel 2 beta 1 - 改进的稳定性、树摇、源映射性能等!🚀
Parcel 团队非常高兴今天发布 Parcel 2 的第一个测试版!这标志着第一个比我们的夜间和 alpha 版本更稳定的 Parcel 2 版本,并且我们承诺避免更改大多数面向用户的 API。请尝试并在 GitHub 上给我们反馈!
自上次 alpha 版本发布以来已经有一段时间了,在此期间 Parcel 2 的开发一直非常活跃。我们一直专注于在准备稳定版 v2 发布时的稳定性、性能和可靠性,但我们也设法加入了一些新特性!
-
🌳 改进的树摇 — 自上次 alpha 版本以来,Parcel 的树摇实现已经有了巨大的改进。除了大量的 bug 修复和性能改进,Parcel 2 现在为树摇后的包生成源映射,并在引用未知符号时显示友好的错误消息。
-
🗺 更快的源映射生成 — Parcel 现在有一个全新的源映射模块,专门为我们的特定用例进行了调整。它用 C++ 编写以提高性能,在合并来自多个文件的源映射时快约 20 倍!
-
#️⃣ 改进的内容哈希 — Parcel 现在对包的长期可缓存性有了更可靠的内容哈希支持。此外,Parcel 2 现在通过仅更新入口包中的清单,而不是所有引用的包,来避免级联失效。
-
🚨 解析器诊断 — Parcel 2 现在在无法找到代码中引用的模块时支持友好的错误消息。这些消息包括显示错误发生位置的详细代码框,以及关于如何可能修复问题的建议。
-
📊 更准确的包报告 — Parcel 在生产构建结束时在 CLI 中生成的包报告现在更加准确。它们现在基于源映射,并排除在树摇和压缩期间被移除的代码,以获得更准确的文件大小。
-
🐞 大量 bug 修复和改进 — 此版本包括无数的 bug 修复和稳定性改进。团队一直在针对一些非常大的应用程序测试 Parcel 2,我们很高兴看看它对你的效果如何。
树摇
#构建生产 JavaScript 编译器极具挑战性。我们一直在改进 Parcel 的树摇实现自 2018 年以来,它已经有了巨大的进步。Parcel 2 默认启用树摇,我们最近一直在 Atlassian 和 Adobe 使用它在生产中部署一些非常大的应用程序。
Parcel 的树摇实现在打包器中是独特的。除了像许多其他工具一样支持 ES 模块外,Parcel 还原生支持 CommonJS 的树摇。虽然现在一些库提供 ES 模块,但 npm 上的大多数代码仍然是用 CommonJS 编写或在发布前转译为 CommonJS。CommonJS 可能很难进行静态分析,就像 JavaScript 的大部分代码一样,我们投入了巨大的努力使这一过程透明。在大多数情况下我们可以进行静态分析,并在执行不安全操作时自动退出并将模块包装在函数中。在过去的几个月里,我们发现并修复了树摇实现中的许多 bug 和边缘情况,并进行了广泛测试。我们很想听听它在你的应用程序中的表现!请报告你发现的任何 bug。
Parcel 现在还为树摇后的包生成源映射。这是自初始树摇发布以来的一个限制,对我们来说是一个主要挑战。由于树摇并不是简单地线性连接文件,因此以正确的方式组合源映射很困难。相反,我们现在在缓存中存储 AST,并将它们组合在一起。这保留了 AST 节点中的位置信息,可以在代码生成过程结束时用于生成最终的源映射。
除了源映射,位置信息还允许我们提供更准确的错误消息。我们现在能够为诸如从模块中导入不存在的导出等错误显示详细的代码框。
非常感谢 Niklas Mischkulnig 在改进 Parcel 的树摇编译器方面所做的所有工作。🙏
源映射
#生成源映射可能非常消耗 CPU 和内存,尤其是在合并来自多个文件的源映射时。我们之前使用 Mozilla 的 source-map 库来执行此操作,但在大型包上遇到了性能问题。
为了解决这个问题,我们实现了我们自己的库来合并和操作源映射。这是一个原生 Node 模块,用 C++ 编写,专门为 Parcel 的用例而构建。它利用 FlatBuffers 在工作进程和缓存之间进行序列化,这极大地降低了我们之前使用 JSON 时生成和解析的成本。总体而言,它在合并源映射时快约 20 倍于 JavaScript 实现。举个例子,之前需要 3 秒生成源映射的包现在只需 175 毫秒!
除了原生 Node 模块,还有同一个库的 WebAssembly 构建,允许它在 Web 浏览器等环境中使用。虽然不如原生绑定快,但能够重用相同的代码而不需要维护纯 JS 实现是很令人兴奋的。
感谢 Jasper De Moor 在 Parcel 源映射方面所做的出色工作!🥳
内容哈希
#自 v1.7.0 以来,我们就通过内容哈希文件名支持长期缓存。这些内容哈希历来是通过哈希包中包含的每个单独文件生成的。这确保了包中任何文件的更改都会导致文件名更新,并使浏览器和 CDN 缓存失效。然而,它并未考虑 Parcel 运行时代码本身发生变化的情况,而不是源代码。这可能发生在升级 Parcel 版本或稍后运行的插件(例如压缩器)时。
Parcel 现在根据完成所有打包和压缩后的包的最终内容生成哈希。这意味着即使 Parcel 注入的运行时代码发生变化,或者你的压缩器改变了编译代码的方式,内容哈希也会正确更新。
实现这一点是一个挑战,因为包可能作为代码的一部分引用其他包。由于最终名称要到代码生成后才能确定,Parcel 现在将占位符引用插入包的内容,而不是最终的包名。最后,在写入磁盘时,这些将被替换为最终名称。
除了更可靠的内容哈希,Parcel 现在在许多情况下避免了级联失效问题。链接的博客文章很好地阐述了这个问题,但本质上,由于包可能通过内容哈希文件名引用其他包,当叶子包更新时,所有通向该包的包也必须更新以使缓存失效。这导致缓存性能不佳。
与直接通过完整内容哈希名称引用包不同,Parcel 现在在每个入口包中包含一个清单。这个清单包括从稳定包 ID 到最终内容哈希文件名的映射。与直接引用其他包不同,只包含包 ID。当树中更下层的包更新时,由于包 ID 是稳定的,因此不再需要级联失效到中间包。只有入口包(包含清单)和已更改的包需要更新。这可以显著提高缓存命中率。
感谢 Maia Teegarden 和 Will Binns-Smith 在 Parcel 2 内容哈希方面的工作!
解析器诊断
#Parcel 现在在无法找到你在代码中引用的模块时提供改进的错误报告。这包括显示错误确切发生位置的代码框堆栈,以及导致问题的任何中间文件。
例如,下面的截图显示了一个通常只会包含第一行(从 './src/index.js' 无法解析 'invalid-entries')的错误,如果幸运的话可能还会显示第一个代码框。但这并不能告诉你错误实际发生在哪里。在这种情况下,invalid-entries 模块确实存在,但它在其 package.json 中指向一个不存在的文件。Parcel 现在为 package.json 显示第二个代码框,指向导致底层问题的确切行。
升级
#从之前的 Parcel 2 alpha 版本升级应该相当直接,但有几件事需要注意。
-
配置解析更改 — Parcel 现在仅支持在仓库根目录中有一个 .parcelrc 配置文件。出于性能原因,不再支持子目录中的其他配置文件。
-
配置更改 — 为了与其他插件保持一致,.parcelrc 中的
transforms
已重命名为transformers
。 -
目标解析更改 — 在单一仓库中,package.json 文件中定义的目标现在从项目根目录解析,而不是在指向文件而非包目录本身时从单个包解析。这意味着你可以跨多个包指向文件以构建单个目标,或指向包本身以构建每个包中定义的目标。更多信息请参见此处和此处的描述。
-
发布目录更改 — 默认情况下,Parcel 现在在服务模式下输出到项目根目录的 dist 目录,而不是缓存内部的隐藏目录。这使你可以更轻松地在开发期间检查构建的文件。你可以使用
--dist-dir
CLI 选项覆盖此设置。 -
插件 API 更改 — 有几处插件 API 更改。请查看下面链接的文档以获取更多详情。
文档
#我们一直在为 Parcel 2 开发新的文档网站!它仍然是一个正在进行中的工作,但我们计划涵盖从使用 Parcel 构建基本应用程序或库,到更高级的特性、配方和构建自己的插件的所有内容。请查看并给我们反馈!
稳定性
#如前所述,这是 Parcel 2 的第一个测试版。这意味着它比夜间或 alpha 版本更稳定,但在完全稳定发布之前仍然预期会有一些变化。特别是,测试版意味着我们不打算更改大多数面向用户的 API,如配置格式(在 package.json 和 .parcelrc 中)和 CLI 参数。在第一个发布候选版本之前,插件 API 仍可能有一些更改,但此时我们不希望有重大变化。
试用!
#如果你一直在等待尝试 Parcel 2,现在是个好时机!你可以通过运行 yarn add parcel@next
来安装。如果需要帮助,可以在 GitHub 讨论中提问,如果遇到 bug,请在 GitHub issues 上报告。你还可以在 Twitter 上找到我 @devongovett。我们真的很期待听到你的反馈!