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

动态使用URL.createObjectURL结合import()时根路径模块解析失败的问题求助

动态使用URL.createObjectURL结合import()时根路径模块解析失败的问题求助

我最近碰到一个头疼的问题:当我用URL.createObjectURL生成Blob URL来动态导入模块时,没办法从网站根目录相对导入其他模块,但同样的根路径导入/some-path.js在静态导入里完全正常。

我的代码是这样的:

const fileContents = `import { test } from "/some-path.js"`;

const blob = new Blob([fileContents], {
  type: "application/javascript"
});
const moduleUrl = URL.createObjectURL(blob);
try {
  const importedModule = await import(moduleUrl);
} catch (err) {
  console.error(err);
} finally {
  URL.revokeObjectURL(moduleUrl);
}

运行这段代码后,会抛出这个错误:

TypeError: Failed to resolve module specifier "/some-path.js". Invalid relative url or base scheme isn't hierarchical.

我试了各种方法都没搞定,静态导入根路径完全没问题,有没有大佬能给我点建议怎么解决这个问题呀?


问题根源

其实这个问题的核心是Blob URL的解析基准和网站根目录不一样:通过URL.createObjectURL生成的URL是blob:协议开头的,它的解析基准是这个Blob自身的URL,而不是你的网站的http/https协议根目录。静态导入时浏览器会自动以当前网站的origin作为解析基准,所以根路径能正常工作,但动态Blob模块就不行了。

解决方案

这里给你两个简单可行的解决方法:

方法一:把根路径导入替换为基于网站origin的绝对路径

直接在生成Blob内容时,把根路径拼接上网站的origin,让导入路径变成完整的绝对URL:

const siteOrigin = window.location.origin;
// 把根路径替换成带origin的绝对路径
const fileContents = `import { test } from "${siteOrigin}/some-path.js"`;

const blob = new Blob([fileContents], {
  type: "application/javascript"
});
const moduleUrl = URL.createObjectURL(blob);
try {
  const importedModule = await import(moduleUrl);
} catch (err) {
  console.error(err);
} finally {
  URL.revokeObjectURL(moduleUrl);
}

方法二:使用new URL()统一解析根路径(适合多个根路径导入的场景)

如果你的Blob模块里有多个根路径导入,可以在模块开头定义一个解析函数,批量处理路径转换:

const fileContents = `
// 定义根路径解析函数
const resolveRoot = (path) => new URL(path, window.location.origin).href;
import { test } from resolveRoot("/some-path.js");
// 其他根路径导入也可以用这个函数
import { utils } from resolveRoot("/utils/helper.js");
`;

// 后面的Blob和导入代码不变
const blob = new Blob([fileContents], {
  type: "application/javascript"
});
const moduleUrl = URL.createObjectURL(blob);
try {
  const importedModule = await import(moduleUrl);
} catch (err) {
  console.error(err);
} finally {
  URL.revokeObjectURL(moduleUrl);
}

这样不管有多少个根路径导入,都可以用这个函数统一解析,避免重复拼接origin。

额外提示

如果你的项目使用了前端构建工具(比如Vite、Webpack),也可以考虑通过配置模块别名来处理,但这种方式更适合静态代码的场景,像你这种动态生成Blob的情况,还是上面两种方法更直接有效。

备注:内容来源于stack exchange,提问作者Bart Louwers

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 18:29:27