绝大多数情况下应将<script>放在</body>前,因其可确保DOM就绪且不阻塞首屏渲染;若需异步加载,依赖DOM或有执行顺序要求时用defer,独立脚本如统计代码则用async。

script 标签该放 还是 底部?
绝大多数情况下,<script> 放在 <head> 里会导致页面渲染阻塞——浏览器会暂停 HTML 解析,先下载、解析、执行 JS,再继续渲染。用户看到白屏的时间可能明显变长。
除非脚本满足以下全部条件,否则别默认往 <head> 里硬塞:
- 脚本体积极小(比如几行初始化逻辑)
- 不依赖 DOM 元素(即不操作
document.getElementById等) - 没有副作用或必须同步执行(比如某些 analytics 初始化)
更稳妥的做法:把 <script> 放在 <body> 最底部,紧贴 </body> 前。这样能确保 DOM 已就绪,且不阻塞首屏渲染。
用 defer 还是 async?关键看执行时机和依赖关系
defer 和 async 都能让脚本异步下载,但执行时机完全不同:
立即学习“前端免费学习笔记(深入)”;
-
defer:下载不阻塞 HTML,但执行会等到整个 HTML 解析完成、DOM 构建完毕后,按<script>出现顺序执行 -
async:下载不阻塞,一旦下载完立刻执行,不保证顺序,也不等 DOM 就绪
所以:
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
- 如果你的 JS 依赖其他 JS(比如先引入
lodash.js,再引入app.js),必须用defer,且两个<script defer>按顺序写 - 如果脚本完全独立(比如统计埋点、广告 SDK),用
async更合适 - 不要对同一个脚本同时加
defer和async——async优先级更高,defer会被忽略
路径写错导致 404 是最常见问题
引入失败时,打开浏览器开发者工具的 Network 标签页,看 JS 文件是否返回 404 或 403。原因往往不是语法错误,而是路径没写对:
- 相对路径以当前 HTML 文件位置为基准,不是以 JS 文件位置为准
-
./js/main.js表示同目录下js/文件夹里的文件 -
../assets/script.js表示上一级目录的assets/下的文件 - 建议统一用根路径:
/js/main.js(注意开头的/),避免嵌套层级深时路径混乱
顺便检查服务器是否真的部署了该文件,以及文件权限是否允许公开访问——有时候本地跑通,上线就 404,大概率是构建产物没拷贝过去或 Nginx 路由没配好。
现代项目中,直接写 script 标签越来越少见
如果你用的是 Webpack、Vite 或 Next.js 这类工具链,实际开发中几乎不会手写 <script src="...">。打包器会自动注入入口脚本,或者通过 import 动态加载。
手写 <script> 主要出现在以下场景:
- 静态站点、CMS 模板(如 WordPress 主题)
- 需要快速接入第三方 SDK(比如
umami.js、plausible.js) - 微前端子应用的入口挂载
这时候更要留意:第三方脚本是否支持 defer?是否自带 async?有没有提供模块化版本(type="module")?这些细节直接影响执行顺序和全局变量污染风险。


















