You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带defer属性的脚本导致Angular应用加载受阻问题咨询

问题描述

我有一个依赖某不稳定服务器脚本的Angular应用,该脚本加载时常耗时较久,因此我为其添加了defer属性,但发现应用仍会等待该延迟脚本下载完成后才加载。

根据调研,Angular应用应在DOMContentLoaded前渲染,我甚至在全新Angular应用中测试,将defer.js的加载延迟10秒,结果依旧如此。

初始HTML代码

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Untitled</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">

  <script src="http://localhost:8080/defer.js" defer></script>

</head>
<body>
  <app-root></app-root>
</body>
</html>

浏览器实际加载的HTML代码

<!doctype html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Untitled</title>
        <base href="/">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="icon" type="image/x-icon" href="favicon.ico">
        <script src="http://localhost:8080/defer.js" defer=""></script>
        <link rel="stylesheet" href="styles.css">
    </head>
    <body>
        <app-root></app-root>
        <script src="runtime.js" type="module"></script>
        <script src="polyfills.js" type="module"></script>
        <script src="styles.js" defer></script>
        <script src="vendor.js" type="module"></script>
        <script src="main.js" type="module"></script>
    </body>
</html>

测试环境:使用Chrome浏览器插件URL Throttler进行模拟测试


解决方案

问题根源在于浏览器对传统defer脚本和ES模块脚本的执行顺序规则:

  • 你添加的defer.js是传统延迟脚本,而Angular注入的核心脚本(runtime.js、polyfills.js等)都是type="module"类型的ES模块脚本。
  • 浏览器会优先执行所有传统defer脚本,再执行ES模块脚本。这就导致defer.js的延迟加载直接阻塞了Angular核心脚本的执行,进而让应用必须等它加载完成才启动渲染。

推荐两种解决方式:

  1. 将外部脚本改为ES模块类型
    ES模块默认具备类似defer的异步加载特性,修改后它会和Angular的模块脚本并行加载,不会互相阻塞执行:

    <script src="http://localhost:8080/defer.js" type="module"></script>
    
  2. 动态加载外部脚本
    在Angular应用启动后手动加载该脚本,完全不影响应用初始化过程,比如在AppComponent的ngOnInit中添加逻辑:

    ngOnInit() {
      const script = document.createElement('script');
      script.src = 'http://localhost:8080/defer.js';
      script.onload = () => {
        // 可添加脚本加载完成后的业务逻辑
      };
      document.body.appendChild(script);
    }
    

内容的提问来源于stack exchange,提问作者faragos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 07:15:42