首页 > 解决方案 > 在浏览器中使用带有外部 URL 的动态导入

问题描述

是否有 Babel 插件或 polyfill 将转换动态导入调用,因此以下代码将在浏览器中工作:

const namespace = await import('https://example.com/bundle.js');

console.log(namespace.exportedSymbol);

如果不是,也许可以将其转换为 SystemJS 导入,因此可以在运行时使用 SystemJS 加载器来加载外部包?

// transformed code:

import System from 'systemjs';

const namespace = await System.import('https://example.com/bundle.js');

console.log(namespace.exportedSymbol);

我不想用 XHR/Fetch 自己实现动态加载,我希望源代码尽可能接近 EcmaScript 的发展方向(未来兼容性)。

标签: javascriptlazy-loadingbabeljspolyfillsdynamic-import

解决方案


一般说明

首先我要提到的是,它import是 EcmaScript 中的一个特殊关键字,因此不可能透明地填充它。

唯一的选择是调用另一个函数,该函数将检测本地是否支持动态导入并相应地切换实现。

好消息是Rollup有一个选项output.dynamicImportFunction,它允许在编译期间重命名动态导入,因此您可以在源代码中使用标准导入。

因此,如果您使用SystemJS,您可以将其设置为:

{ 
  output: {
    dynamicImportFunction: 'System.import',
  },
}

Webpack 具有用于转换动态导入的内置机制,但它更适合代码拆分用例,并且不适用于外部导入。我相信您可以告诉 Webpack 使用该import(/* webpackIgnore: true */ 'https://example.com/bundle.js');构造忽略此类导入,但您还需要import使用文本替换插件或类似的东西将函数名称替换为其他名称。

填充物

看起来动态导入的最佳 polyfill 是 GoogleChromeLabs 的dynamic-import- polyfill。

你可以在你的入口点像这样初始化它:

import dynamicImportPolyfill from 'dynamic-import-polyfill';

dynamicImportPolyfill.initialize();

您还可以传递一个基本 URL,将从中解析相对 URL,以及__import__()默认情况下应该填充的函数的名称(它是 )。

为了将它与 Rollup 一起使用,您将需要以下配置:

{ 
  output: {
    dynamicImportFunction: '__import__',
  },
}

或者您需要使用import()替换__import__()插件在 Webpack 中替换为。

这个 polyfill 的缺点是它依赖于一些旧版浏览器不支持的 ESM 功能,因此它无法在Internet Explorer 11中运行。

此外,它使用动态创建的脚本,代码内容作为 blob src 传递。如果您使用CSP 策略,则应更新它们以允许使用blob:URL。


推荐阅读