当前位置: 首页 > news >正文

JavaScript 文件在页面渲染中的加载机制详解

JavaScript 文件在页面渲染中的加载机制详解

1. 基本加载流程

当浏览器解析 HTML 遇到 <script> 标签时,会按照以下顺序处理:

defer
async
HTML 解析
遇到 script 标签
是否 defer/async?
停止 HTML 解析
下载 JS 文件
执行 JS 代码
恢复 HTML 解析
异步下载,延迟执行
异步下载,立即执行

2. 不同 script 加载模式的对比

加载方式HTML 解析是否阻塞JS 执行时机执行顺序保证
普通 script阻塞下载完成后立即执行按文档顺序
async script不阻塞下载完成后立即执行不确定
defer script不阻塞DOMContentLoaded 前顺序执行按文档顺序
module script默认 defer类似 defer按文档顺序

3. 关键阶段详解

(1) 普通 script (无属性)

<script src="app.js"></script>
  • 阻塞行为
    • 停止 HTML 解析
    • 同步下载并执行 JS
    • 执行完后才继续解析 HTML
  • 典型影响
    • 若 JS 文件过大,会导致首屏渲染延迟(白屏时间长)

(2) async 脚本

<script async src="analytics.js"></script>
  • 特点
    • 异步下载(不阻塞 HTML 解析)
    • 下载完成后立即执行(可能中断 HTML 解析)
    • 多个 async 脚本的执行顺序无法保证
  • 适用场景
    • 不依赖 DOM 的独立脚本(如统计分析)

(3) defer 脚本

<script defer src="vendor.js"></script>
  • 特点
    • 异步下载(不阻塞 HTML 解析)
    • 在所有 HTML 解析完成后,按文档顺序执行
    • DOMContentLoaded 事件前触发
  • 适用场景
    • 需要操作 DOM 但又不想阻塞渲染的脚本

4. 现代浏览器优化机制

(1) Preload 预加载

<link rel="preload" href="critical.js" as="script">
  • 提前下载但不执行
  • 适用于关键资源加速

(2) Prefetch 预获取

<link rel="prefetch" href="next-page.js">
  • 空闲时下载后续页面资源
  • 优先级低于 preload

5. 性能优化建议

  1. 关键 JS 内联或 preload

    <!-- 内联关键代码 -->
    <script>/* 关键渲染路径代码 */</script><!-- 非关键代码异步加载 -->
    <script defer src="non-critical.js"></script>
    
  2. 第三方脚本异步化

    <script async src="https://analytics.example.com/script.js"></script>
    
  3. 模块化拆分

    // 动态导入非首屏需要的代码
    button.addEventListener('click', () => {import('./modal.js').then(module => module.open());
    });
    
  4. 使用 type=“module”

    <script type="module" src="app.js"></script>
    
    • 现代浏览器会自动应用 defer 行为
    • 支持 ES6 模块语法

6. 面试回答示例

问题:“JS 文件加载会如何影响页面渲染?有哪些优化手段?”

回答
"浏览器遇到普通 script 标签时会阻塞 HTML 解析,直到 JS 下载并执行完成。这会导致渲染延迟,对此我们有几种优化方案:

  1. 对非关键脚本使用 async/defer 避免阻塞:

    • async 用于独立脚本(如数据分析)
    • defer 用于需要 DOM 但可延迟的脚本
  2. 通过 preload 提前加载关键资源:

    <link rel="preload" href="critical.js" as="script">
    
  3. 代码拆分和动态导入:

    // 按需加载非首屏代码
    import('./heavy-module.js').then(...)
    

在实际开发中,可以通过将第三方脚本异步化 + 关键脚本 preload,使 LCP 时间减少了 "


可视化时间线对比

普通 script:
[HTML解析=======停止===>][JS下载|执行][继续解析HTML]async:
[HTML解析======================][JS下载|执行](随机时机)defer:
[HTML解析======================][DOMContentLoaded][按序执行defer脚本]

ps:理解这些机制可以帮助我们更精确地控制页面加载性能。

http://www.dtcms.com/a/296579.html

相关文章:

  • CF每日5题(1500-1600)
  • Unity3D + VR头显 × RTSP|RTMP播放器:构建沉浸式远程诊疗系统的技术实践
  • Springboot宠物用品商城的设计与实现
  • 深入理解 eMMC RPMB 与 OP-TEE 在 Linux 系统中的应用开发
  • 云祺容灾备份系统AWS S3对象存储备份与恢复实操手册
  • 字符串匹配经典问题整理
  • 深度分析Java内存回收机制
  • DGMR压缩技术:让大规模视觉Transformer模型体积减半而性能不减
  • 数据库第5章期末复习(仅供参考哦)
  • MDO7350A示波器的介绍【PINTECH品致】
  • 如何把Excel文件导入Navicat?
  • EXCEL——INDEX和MATCH傻傻分不清?
  • matplotlib.pyplot: 底层原理简析与进阶技巧
  • 2025暑期—07深度学习应用-YOLO
  • 如何查看docker实例是否挂载目录,以及挂载了哪些目录
  • TLSF(Two-Level Segregated Fit)内存分配器深入解析
  • 力扣.26删除有序数组中的重复项力扣121.买卖人股票的最佳时机力扣.1143最长公共子序列力扣72.编辑距离力扣12.整数转罗马数字
  • 同花顺前端潜在面试题目与答案
  • Redis的Pipeline
  • 期货交易系统:市场生态中的功能映射与价值逻辑
  • VB解除excel保护工作表
  • VTK开发day2:切片矩阵
  • 量子威胁下的区块链进化:后量子密码学时代的分布式账本革命
  • linux-process
  • 跨境支付入门~国际支付结算(基础篇)
  • QT开发---字符编码与QString和QByteArray
  • 窗选和叉选
  • Linux C 网络基础编程
  • 财务数字化——解读集团企业财务共享业务蓝图规划方案【附全文阅读】
  • OpenHarmony中.cfg引导启动配置文件中不同jobs配置项启动顺序