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

Flask render_template中JavaScript加载顺序疑问

关于带type="module"的JavaScript脚本加载执行顺序规则解析

核心原因是模块脚本(type="module")和普通脚本的加载执行逻辑完全不同,这直接导致了你看到的输出顺序不符合预期。以下是具体规则和对你代码的分析:

1. 普通脚本(无type="module")的执行逻辑

  • 内联普通脚本:浏览器解析到它时会立即执行,阻塞后续HTML解析,直到脚本执行完毕。
  • 外部普通脚本:默认会先下载脚本文件,下载完成后立即执行,同样阻塞HTML解析(可通过async/defer修改行为,但你代码中的内联脚本未使用这些属性)。

2. 模块脚本(type="module")的核心特性

  • 自动延迟执行:无论模块脚本放在<head>还是<body>,浏览器都会先完成整个HTML的解析,再执行模块脚本——这是模块脚本的默认行为,等价于给普通脚本添加defer属性。
  • 异步加载:模块脚本的下载过程是异步的,不会阻塞HTML解析,下载完成后会等待HTML解析完毕再执行。
  • 顺序执行:所有模块脚本会按照它们在HTML文档中出现的先后顺序执行(如果有导入依赖,会先加载依赖再执行当前模块)。

结合你的代码的执行流程

  1. 浏览器解析HTML,遇到<head>里的<script type="module" src="scripts.js">,开始异步下载该脚本,但不阻塞HTML解析。
  2. 继续解析到<body>内的<script>console.log('start base 1html')</script>,立即执行,控制台输出start base 1html。
  3. 继续解析HTML内容(包括加载navbar、sidebar等模板片段),随后遇到<script>console.log('start base2 html')</script>,立即执行,控制台输出start base2 html。
  4. 整个HTML解析完成后,浏览器按顺序执行之前下载好的模块脚本:先执行<head>中的scripts.js,再执行<body>末尾的script_body.js。

因此你实际看到的控制台输出顺序应该是:

start base 1html
start base2 html
[scripts.js中的console.log内容]
[script_body.js中的console.log内容]

调整执行顺序的可选方案

如果需要让模块脚本在普通脚本之前执行,有两种方式:

  • 移除模块脚本的type="module"属性,将其改为普通脚本(但会丢失模块的import/export等特性)。
  • 给普通内联脚本添加type="module"属性,让所有脚本都延迟到HTML解析完成后按文档顺序执行,此时输出顺序会变为:scripts.js → start base 1html → start base2 html → script_body.js。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 15:10:04