向新型浏览器提供新式代码,以提高网页加载速度

构建可在所有主流浏览器上顺畅运行的网站是 Google Cloud 的一项核心原则, 开放式网络生态系统不过,这意味着需要执行额外的工作,才能确保 您打算定位的每个浏览器都支持您编写的代码。如果您 想要使用新的 JavaScript 语言功能,您需要将这些 功能转换为向后兼容的格式,适用于尚不支持的浏览器 。

Babel 是编译代码时最常用的工具 包含新版语法的代码 (如 Node)能理解的对象。本指南假定您使用的是 Babel, 您需要按照设置说明操作 请将其添加到您的应用中(如果尚未添加)。选择“webpack” (如果您在 Build Systems 中将 webpack 用作模块打包器)。

要使用 Babel 仅转译用户需要的内容, 需要:

  1. 确定要定位的浏览器。
  2. @babel/preset-env 与适当的浏览器目标搭配使用。
  3. 使用 <script type="module"> 停止向不需要使用转译代码的浏览器发送转译代码。

确定您要定位的浏览器

在开始修改应用中代码的转译方式之前, 您需要确定哪些浏览器在访问您的应用。分析哪些浏览器 以及计划定位的用户 做出明智的决策。

使用 @babel/preset-env

转译代码通常会导致文件大于 原始形式。通过尽可能减少编译工作量 来减小网页包的大小,以提高网页性能。

无需添加特定插件即可选择性地编译某些语言 当前使用的许多功能,Babel 提供了许多预设,可将插件打包 。请使用 @babel/preset-env 以便仅包含您打算使用的浏览器所需的转换和 polyfill 定位条件。

在 Babel 的 presets 数组中包含 @babel/preset-env .babelrc

{
 "presets": [
   [
     "@babel/preset-env",
     {
       "targets": ">0.25%"
     }
   ]
 ]
}

使用 targets 字段指定要涵盖的浏览器版本 向 browsers 字段添加适当的查询。@babel/preset-env 集成了 browserlist,一个在不同网页共用的开源配置, 用于定位浏览器的工具。如需查看兼容查询的完整列表,请参阅 browserslist 文档。 另一种方法是使用 .browserslistrc 文件列出环境 广告资源尺寸

">0.25%" 值指示 Babel 仅包含转换 需要支持占全球市场 0.25% 以上的浏览器 。这可确保您的 bundle 不包含不必要的转译 只有极少数用户使用的浏览器。

在大多数情况下,这比使用以下 配置:

  "targets": "last 2 versions"

"last 2 versions" 值会将您的代码转译为 每个浏览器的最近两个版本, 这表示支持 Internet Explorer 等已停用的浏览器。 否则,这可能会使 app bundle 的大小不必要地增加 访问您的应用所需的资源。

最后,您应当选择合适的查询组合 定位符合您需求的浏览器。

启用新式 bug 修复

@babel/preset-env 将多个 JavaScript 语法功能分组到集合中并启用/停用 根据指定的目标浏览器来屏蔽它们。虽然这种方法效果很好, 语法功能会在目标浏览器包含只有一项功能的错误时进行转换。 这通常会导致转换的代码超出所需的范围。

此预设最初是作为单独的预设开发而成的, @babel/preset-env 中的问题修复选项 通过将一些浏览器中已损坏的现代语法转换为最接近 同等语法,该语法在这些浏览器中未损坏。结果是几乎完全相同的现代代码 对语法进行了一些细微调整,以确保兼容所有目标浏览器。要使用此 请确保您已安装 @babel/preset-env 7.10 或更高版本,然后设置 将 bugfixes 属性设置为 true

{
 "presets": [
   [
     "@babel/preset-env",
     {
       "bugfixes": true
     }
   ]
 ]
}

在 Babel 8 中,bugfixes 选项默认处于启用状态。

使用 <script type="module">

JavaScript 模块(简称 ES 模块)是 所有主流浏览器。您可以使用模块 创建可以从其他模块导入和导出的脚本, 也可将其与 @babel/preset-env 一起使用,以仅定位支持的浏览器, 。

与其查询特定的浏览器版本或市场份额,不如考虑 在 .babelrc 文件的 targets 字段中指定 "esmodules" : true

{
   "presets":[
      [
         "@babel/preset-env",
         {
            "targets":{
               "esmodules": true
            }
         }
      ]
   ]
}

已支持许多使用 Babel 编译的更新的 ECMAScript 功能 在支持 JavaScript 模块的环境中。完成上述操作后 简化确保只使用转译代码的过程 。

支持模块的浏览器会忽略具有 nomodule 属性的脚本。 反之,不支持模块的浏览器会忽略带有 type="module"。这意味着您可以添加一个模块以及一个已编译的回退。

理想情况下,包含应用的两个版本脚本,如下所示:

  <script type="module" src="main.mjs"></script>
  <script nomodule src="compiled.js" defer></script>

支持模块的浏览器会提取并执行 main.mjs 并忽略 compiled.js。 不支持模块的浏览器则恰好相反。

如果您使用 webpack,可以在配置中为两个网站分别设置不同的目标 应用的不同版本:

  • 仅适用于支持模块的浏览器的版本。
  • 包含可在所有旧版浏览器中使用的已编译脚本的版本。此文件较大,因为转译需要支持更广泛的浏览器。

在此非常感谢 Connor Clark 和 Jason Miller 给出的评价。