从Blob加载ES Module时相对模块路径无法解析的问题
问题解答
这是预期行为吗?
没错,这属于浏览器的正常预期行为。
当你通过URL.createObjectURL(blob)生成的Blob URL加载模块时,这个模块的解析基准URL是Blob URL本身,不是当前页面的域名origin。浏览器会以blob:协议的URL为起点去解析模块里的导入路径:
- 根路径
/lib.js会被解析成blob:xxx/lib.js(显然不存在这个资源) - 相对路径
./lib.js会被解析成blob:xxx/./lib.js,同样无效
这就是你遇到TypeError: Error resolving module specifier "/lib.js"错误的原因。
更优解决方案
方案1:预处理模块内容,自动替换路径为绝对路径
在把模块内容转成Blob之前,自动把模块里的根路径/相对路径替换成基于当前origin的绝对路径。这样既能保留静态import的写法(不丢编辑器智能提示),也不用改模块源代码:
修改你的blob_from_url函数:
async function blob_from_url(url) { const res = await fetch(url); let content = await res.text(); // 替换根路径开头的导入语句 content = content.replace( /(import\s+.+\s+from\s+['"])(\/[^'"]+)(['"])/g, `$1${window.location.origin}$2$3` ); // 额外处理相对路径(比如./lib.js) content = content.replace( /(import\s+.+\s+from\s+['"])(\./[^'"]+)(['"])/g, (match, prefix, path, suffix) => { // 基于当前页面URL和模块原路径生成绝对地址 const absoluteUrl = new URL(path, window.location.origin + new URL(url).pathname).href; return `${prefix}${absoluteUrl}${suffix}`; } ); return new Blob([content], { type: 'application/javascript;charset=utf-8' }); }
这个方法的好处:
- 模块源代码不用改,静态import写法保留,编辑器智能提示不受影响
- 自动适配根路径和相对路径的导入场景
方案2:用Import Maps(适合固定路径的模块)
如果你的导入路径是固定的,可以在页面里加Import Map,把相对/根路径直接映射成绝对URL。这样模块里的静态import会自动按映射规则解析:
在页面<head>里添加:
<script type="importmap"> { "imports": { "/lib.js": "https://你的域名/lib.js", "./utils.js": "https://你的域名/path/to/utils.js" } } </script>
注意:Import Map要放在所有模块加载之前,现代浏览器都支持,IE不兼容。
关于你的临时方案
你现在用的动态导入拼接window.location.origin的方法虽然能跑,但确实有冗余代码、丢智能提示的问题,上面两个方案可以完美规避这些缺点。
内容的提问来源于stack exchange,提问作者orca
相关产品推荐
相关产品推荐

