模块热刷新核心是用url对象动态添加时间戳或哈希参数强制重载,需复用原始路径、避免手动拼接;应导出dispose清理副作用,并注意cors与mime限制。

在模块脚本(type="module")中实现按需热刷新,核心不是靠框架或构建工具的监听机制,而是利用浏览器原生 URL 对象动态生成带唯一查询参数(如时间戳、哈希或版本号)的模块 URL,从而绕过缓存强制重新加载模块。这适用于开发阶段快速验证、无构建环境的轻量调试,或配合简单服务端做最小化热更新。
用 URL 构造器动态添加时间戳参数
每次需要刷新模块时,基于当前模块原始路径构造一个带 t= 时间戳的新 URL,浏览器会视其为全新资源,触发重新获取和执行。
- 确保原始模块路径可被复用(建议存为变量或从
import.meta.url解析) - 使用
new URL(...)安全拼接,自动处理相对路径、协议、基础路径等边界情况 - 避免手动字符串拼接,防止
?/&错误或编码问题
示例:
// main.js(主模块)
let currentModule = './feature.js';
async function reloadFeature() {
const url = new URL(currentModule, import.meta.url);
url.searchParams.set('t', Date.now()); // 动态加时间戳
const freshModule = await import(url.href);
// 执行新模块导出的初始化函数,或替换现有逻辑
freshModule.init?.();
}
用哈希值替代时间戳提升稳定性
时间戳可能因高频调用导致重复(尤其毫秒级),且无法反映模块内容真实变更。改用模块内容哈希(需服务端支持)或客户端简易校验(如上次修改时间),更贴近“按需”语义。
- 若服务端提供
/feature.js?_v=abc123接口,可先 fetch 头信息获取ETag或自定义X-Content-Hash - 若仅前端,可用
localStorage缓存上次加载时的哈希或版本,对比后决定是否重载 - 仍通过
URL对象注入参数,保持路径构造健壮性
配合模块卸载与副作用清理
单纯重载模块不会自动清除旧模块的全局监听、定时器、DOM 绑定等副作用。必须在新模块加载前主动清理。
- 约定模块导出
dispose()函数,在 reload 前调用 - 将定时器 ID、事件监听器引用等挂载到模块作用域外(如
window.__MODULE_STATE__)便于查找释放 - 利用
AbortController管理 fetch 或 Promise 链,中止旧请求
注意跨域与 MIME 类型限制
动态 import() 加载的模块必须满足:同源或服务端设置 Access-Control-Allow-Origin;响应头 Content-Type 为 application/javascript 或 text/javascript。
- 若模块路径是跨域 CDN,需确保 CORS 配置允许,否则报错
TypeError: Failed to fetch dynamically imported module - 使用
URL构造时,传入的 base 必须是合法 URL(import.meta.url总是有效) - 不支持 data URL 或 blob URL 直接用于
import()(多数浏览器限制)











