JavaScript动态加载脚本的核心是创建script元素并插入文档,支持原生DOM方法和import()函数两种方式:前者兼容性好但需手动处理重复加载,后者专为ES模块设计且自动去重。

JavaScript 动态加载外部脚本,核心是创建 <script> 元素并插入到文档中。这种方式不阻塞页面渲染,适合按需加载、代码分割或运行时决定依赖的场景。
用原生 DOM 方法动态插入 script 标签
这是最基础也最通用的方式,兼容所有现代浏览器,包括旧版 IE(需注意 IE 的 onreadystatechange 事件)。
- 创建
script元素,设置src属性指向目标 JS 文件 - 监听
load(成功)和error(失败)事件,确保可感知加载结果 - 将 script 插入到
<head>或<body>中(推荐<head>,避免影响 body 渲染顺序)
示例:
function loadScript(src) {
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = src;
script.async = true; // 默认为 true,非阻塞加载
script.onload = () => resolve(script);
script.onerror = () => reject(new Error(`Failed to load ${src}`));
document.head.appendChild(script);
});
}
// 使用
loadScript('/path/to/module.js')
.then(() => console.log('Loaded'))
.catch(err => console.error(err));
用 import() 函数动态导入 ES 模块
ES2020 起支持顶层 import()(动态导入),返回 Promise,专为模块化设计,天然支持 tree-shaking 和异步依赖。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
- 只能用于 ES 模块(
type="module"的脚本或本地模块文件) - 路径可以是字符串变量,支持拼接、条件判断,比静态
import灵活得多 - 自动处理模块依赖、重复加载去重(同一 URL 只执行一次)
示例:
// 加载后可直接使用导出的成员
import('/path/to/utils.js')
.then(module => {
module.helper();
})
.catch(err => console.error(err));
// 也可配合 await 使用(在 async 函数内)
async function init() {
const { debounce } = await import('./debounce.js');
const debounced = debounce(() => console.log('done'), 300);
}
注意事项与常见问题
动态加载不是“扔进去就完事”,几个关键点容易踩坑:
-
CORS 限制:如果脚本跨域,服务端必须返回
Access-Control-Allow-Origin头,否则会静默失败(error事件仍会触发) -
执行时机:动态 script 默认异步执行,但其内部代码仍是同步执行的;多个动态 script 之间不保证执行顺序(除非链式加载或用
import()) - 重复加载:原生方式不会自动去重,多次调用可能重复执行;可用全局标记或 Map 缓存已加载 URL 来避免
-
调试困难:动态加载的脚本在开发者工具中可能显示为匿名或临时 URL,建议加
script.dataset.id = 'xxx'方便识别
简单封装一个可靠加载器
结合缓存 + Promise + 错误提示,日常够用:
const loadedScripts = new Set();
function loadJS(src) {
if (loadedScripts.has(src)) {
return Promise.resolve();
}
return new Promise((resolve, reject) => {
const script = Object.assign(document.createElement('script'), {
src,
async: true,
onload: () => {
loadedScripts.add(src);
resolve();
},
onerror: () => reject(new Error(`Script load error: ${src}`))
});
document.head.appendChild(script);
});
}

















