0

我有一个应用程序,它可以从更大的多页乐谱中转录和分析短乐谱。每个分数都可以从下拉选择中单独提供给用户。一次只加载一个分数,用户通常只会对任何给定会话中的少量分数感兴趣。最近我开始使用 Webpack,每个乐谱都使用动态导入分离到自己的包中。即使我有大量的分数(>50),应用程序的增量性质意味着它们仍然需要分解成自己独立的包,可以在运行时单独加载。

我遇到的问题是每个分数也有自己的数据,这些数据是通过 API 请求从后端(Django)拉下来的。所以现在当用户为给定分数加载模块时(至少在第一次),我有两个请求被执行:模块的包,然后是一个额外的 API 请求来获取数据:

import(/* webpackChunkName: '[request]' */ "./someChunkName").then(module => {
  //...API request to get data...
});

我怎样才能避免这种情况?理想情况下,我希望将数据与请求的块捆绑在一起,完全放弃 API 请求,但是有没有办法使用 Webpack 来做到这一点?或者可能将 import 语句和 API fetch 都包装在 Promise 中?

4

1 回答 1

1

很确定没有办法完全按照你的要求做,因为你试图将编译时拥有的代码(你的 webpack 块)与你在运行时获取它之前不会“拥有”的数据(你的 Django 后端数据)。Webpack 块是在编译时创建的,而在运行时发生的只是 webpack 加载它们以便它们可以执行。

将导入和运行时数据提取包装在 Promise 中应该是可行的,但根据规范,您必须使用require而不是import-- import,不能嵌套在代码块中。require可以,所以你应该能够做类似的事情

const promisifiedRequire = new Promise((resolve, reject) => {
  require.ensure('scores/score-foo', (require) => {
    resolve();    
  });
});

const promisifiedDataFetch = new Promise((resolve, reject) => {
  fetchBackendDataForScoreSomehow().then(() => {
    resolve();
  }).catch((e) => {
    console.log('error fetching data from backend');
    reject(e);
  });
});

Promise.all([ promisifiedRequire, promisifiedDataFetch ]).then(() => {
  // everything is loaded, render stuff etc. now
});

我敢肯定这会更干净、更优雅,但希望它能给你这个想法;在这里,您将有两个并行请求。您是否担心两个并行请求会很慢,而认为拥有所有信息的请求会更快?我不会认为这是理所当然的,并且会在尝试优化之前对其进行测试,但如果是这种情况并且您有充分的理由只对每个分数提出一个请求,那么可能有一种方法可以解决这个问题:

如果我真的想将分数和数据捆绑到一个只需要一个 http 请求的资产中,我将为分数 JS 文件编写一个自定义加载器,它将分数数据捆绑或插入到它返回的分数代码中。如果您以前没有编写过加载器,它基本上只是一个获取源代码并返回其他内容的函数,链中的最后一个加载器通常返回纯 JS。

当然,要在编译时捆绑数据,您需要 Django 应用程序中的数据在编译时可用。可以想象,您的自定义加载器可以向您在进行 webpack 构建时在本地设置的 django 后端实例发出实时请求,但这会很奇怪和尴尬。理想情况下,您首先将数据库中的数据提取到文件中,然后在编译时让您的自定义加载器从这些文件中读取,以获取数据并将其与您的代码捆绑在一起。如何选择以这种方式将检索到的数据插入到您的代码中取决于您,并且很大程度上取决于设计决定。这种方法意味着当您在运行时获取一个块时,该块已经以您决定的任何模式/格式包含您将从 Django 获取的数据,并且不再需要对 Django 进行第二次调用。

于 2018-06-16T21:14:44.937 回答