首页 > 解决方案 > JS - 如何将多个动态导入批处理为一个?

问题描述

我几乎同时从我的 JS 应用程序请求了两个独立但依赖的动态导入。如何避免进行两次导入调用或将它们批处理为一个?

标签: javascriptbatch-processingdynamic-import

解决方案


您可以结合URL.createObjectURL()动态导入的强大功能,在一次 HTTP 调用中导入多个文件。

服务器设置

您显然需要某种 api 来在一次 API 调用中获取多个文件。为此,您需要让服务器以某种方式在一个 HTTP 响应中发送多个文件。语法可能会有所不同,但对于这个示例,我使用的是 syntax GET /a.js+b.js,它将返回一个字符串。

示例:16 24;export default 3export default [2, 3, 5]。这有两个文件,一个带有16字符长度,一个带有24. 之前的数字;就像文件内容的元数据。您可能会将元数据放在标题或其他内容中,但此示例使用;分隔元数据和内容。

客户端代码

我创建了一个名为 的函数fetchMultiple,它类似于fetch,但它返回一个Promise<Array<Promise< the data exported by the files >>>.

// I created a syntax where it goes
// {length of file 1} {length of file 2} {...lengths of files};(no \n)
// {contents of file 1} {contents of file 2} {...contents of files}
const mockServerResponses = new Map()
  .set('a.js+b.js', '16 24;export default 3export default [2, 3, 5]')

// The real thing would fetch the files from the server
const fetchMultiple = async (...urls) => 
  mockServerResponses.get(urls.join('+'))

// You could probably optimize this function to load the first script as soon as it is streamed, so that the first script will be loaded while the second one is still being streamed.
const importMultiple = async (...urls) => {
  const result = await fetchMultiple(...urls)
  const semi = result.indexOf(';')
  const lengths = result.slice(0, semi).split(' ').map(str => 
    parseInt(str))
  const rawContents = result.slice(semi + 1)
  let currentIndex = 0
  const contents = []
  for (const length of lengths) {
    contents.push(rawContents.slice(currentIndex, currentIndex + length))
    currentIndex += length
  }
  return contents.map(content => 
    import(URL.createObjectURL(new Blob(
      [content], 
      { type: 'application/javascript' }
    ))))
}

importMultiple('a.js', 'b.js')
  .then(promises => Promise.all(promises))
  .then(console.log)

如果代码段停止工作(如内容安全策略更改),这里是 repl 的链接:https ://replit.com/@Programmerraj/dynamic-import-url#script.js 。

优化

可能使上面的示例变慢的是它等待整个两个(或更多)文件被获取,然后加载它们。由于文件是流式传输的file 1, file2, ...files,因此更快的代码将file 1在可用时立即加载,并在下载其他文件时加载它们。

我没有实现这个优化的流的东西,因为我没有设置一个流响应的服务器,但是你可以实现最大的效率。


推荐阅读