为什么将 defer 与 Google 映射 Javascript 一起使用?

Why use defer with Google Maps Javascript?

Google 地图 javascript 进行了一些繁重的 DOM 操作。即便如此,the fine docs 建议使用 defer 标志加载它:

<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap" async defer></script>

为什么要为执行 DOM 操作的脚本建议 defer 标志? 我要求了解 defer 标志和 Google 地图 API 因为我似乎对其中的哪一个有误解他们正在做。

通常,script 标记告诉浏览器停止解析 HTML,获取脚本,运行 它,然后才继续解析 HTML。这是因为脚本代码可能使用 document.write 输出到 HTML 令牌流。

async and defer 都是告诉浏览器可以继续并在下载脚本文件的同时继续解析 HTML 和 运行 脚本文件的两种机制稍后,不是马上。

虽然它们略有不同; HTML 规范的 WHAT-WG 版本 the script section 中的这张图对于设想差异很有用:

以上链接规范中的完整详细信息,但简而言之,"classic" 脚本(您习惯的那种;但模块脚本即将推出!):

  • asyncdefer 都允许 HTML 的解析继续进行,而无需等待脚本下载。
  • defer会让浏览器等待解析完成后再执行脚本。
  • async 只会让浏览器等待脚本下载完成,这意味着它可能 运行 脚本在解析完成之前或之后,取决于下载完成的时间(记住它可能来自缓存)。
  • 如果 async 存在并被浏览器支持,则它优先于 defer
  • async 脚本可以 运行 以任何顺序排列,无论它们在 HTML.
  • 中出现的顺序如何 一旦解析完成,
  • defer 脚本将 运行 按照它们在 HTML 中出现的顺序排列。
  • asyncdefer 即使在半现代浏览器中也得到了很好的支持,但在 IE9 和更早版本中没有得到正确支持,请参阅 here and here.

Why would the defer flag be suggested for a script that performs DOM manipulations?

两个原因:

  1. 它允许在下载脚本时继续解析,并且
  2. 这意味着在解析完成之前脚本不是运行。

如果您没有使用 defer 并且未将 script 标记放置在最佳位置,则使用 defer 可以让浏览器帮助 API 脚本正常运行在脚本尝试操作它之前完成 DOM 的构建。

很多人仍然将 script 标签放在文档的 head 部分,尽管那通常是放置它们的最糟糕的地方 除非您使用 defer(或 async)。在大多数情况下,最好的位置(除非你有理由做其他事情)是在 end,就在结束 </body> 标签之前,这样 A) 你的站点快速呈现,无需等待脚本;和 B) DOM 在您尝试操作它之前已完全构建。推荐 defer 可能会避免人们在 HTML.

中过早地放置 script 标签的支持麻烦

google 地图示例同时使用了 asyncdefer 标志。

  • async 标志允许脚本与 DOM 并行加载 解析,并在 API 准备就绪后立即执行。
  • defer 标志允许脚本与 DOM 并行加载 解析,但保证脚本不会执行,直到 DOM解析完毕

async 受现代 HTML5 浏览器支持,而 defer 支持是通用的。当这些标签一起使用时,defer 只是旧浏览器的回退,如果支持 async.

则将被忽略

在这些简单的示例中,asyncdefer 都可以,但都不是必需的。在这种情况下,它仅用于性能。

参考文献:
Speed up Google Maps(and everything else) with async & defer
async vs defer attributes - Growing with the Web