【问题标题】:Using dynamic imports to handle dependencies similar to AMD/requirejs使用动态导入来处理类似于 AMD/requirejs 的依赖项
【发布时间】:2021-03-09 15:27:11
【问题描述】:

我正在拼命寻找一种将静态导入(捆绑)与动态导入 (amd) 相结合的方法。作为 Bundler,我目前正在使用 webpack+babel-env 进行 polyfills(顺便说一句:我厌倦了所有的配置、所有的限制和发生的所有神奇的事情,我很乐意摆脱 webpack)。

使用 webpack 创建 AMD 模块并不令人满意,因为 requirejs 使调试变得非常复杂,而且 webpack 不喜欢模块化构建/多个入口点的想法。澄清一下:我有许多将使用一些共享库的入口点。对于 webpack,它始终是“一个包”的概念,它控制着一切。我阅读了有关动态导入的信息,并认为它是面向未来的方式。

所以我最终有了这个想法:

const library = await import("library.js");

export default function() {
    return library.foo("bar");
}

或者对于多个依赖项某种

const depenencies = await Promise.all([
    import("library1.js"),
    import("library2.js")
]);
const library1 = dependencies[0];
const library2 = dependencies[1];

export default function() {
    return library1.foo("bar") + library2.bar("baz);
}

当然,我开始实现自己的加载器函数以使语法更好

const [library1, library2] = await load('library1.js', 'library2.js');

但是所有这些都不起作用,因为导出是在导入 Promise 解决之前定义的。所以我需要预先分析目标模块以找出依赖关系并将特殊处理添加到我的加载函数中。而且我仍然处于异步上下文中,所以它有可能 - 即使那样 - 它也不起作用。

我想实现与 AMD 非常相似的东西,我可以在其中定义一个模块,该模块依赖于另一个模块,应该由浏览器以异步方式加载。

我的主要目标是一种直观的编码方式,因为源代码将用于中等技能的团队。我不想为每个模块添加一个异步初始化函数,这将加载它的依赖项,因为这会导致代码很难理解。

想象一下,我提供了一些 preact 组件(或其他),并希望在多个模块之间共享通用/通用组件。每个模块都需要导入 preact-core,所以 - 当然 - 我希望将 preact 核心作为单独的模块(vendor/preact.js)提供。

但我仍然想编写如下代码:

const Preact = await import("vendor/preact");

export default class StatefulComponent extends Preact.Component {
    render() {
        return "hello world";
    }
}

使用 ES6 我需要执行以下操作:

export default async function init() {
    return new Promise(resolve => {
        const Preact = await import("vendor/preact.js");
        class StatefulComponent extends Preact.Component {
            render();
        }
        resolve(StatefulComponent);
    });
}

那真是又傻又丑……

import() api 不适合依赖管理,对吗? 是我唯一的选择 AMD/requirejs 和删除 webpack 吗?

如果解决方案超级简单,而我只是愚蠢地看到它,那是因为我在最后几天用 AMD/UMD/CommonJS/ES6/andsoonandsoforth 折磨了我的大脑,而且我现在对 JavaScript 很生气.

【问题讨论】:

    标签: javascript webpack module js-amd


    【解决方案1】:

    没有必要弄得那么乱,但是如果您确实有依赖于import 的导出,那么它们将需要是async(基于承诺)。

    我会做这样的事情:

    //mylibrary.js
    export default (async function(){
        let dep1 = await import('1');
        let dep2 = await import('2');
        //so on and so on...
    
        return {
            myClassThatDependsOnDep1,
            myFunctionThatDependsOnDep2,
        }
    })();
    

    然后您可以以类似的方式使用它:

    (async function(){
       let myLibrary = await import('mylibrary.js')
                       .then(m => m.default);
    
       //You use `myLibrary` here
       //                      v
       
    })();
    

    使用 TLA,可以在此处放弃 async IIFE。

    【讨论】:

      猜你喜欢
      • 2011-06-20
      • 1970-01-01
      • 1970-01-01
      • 2013-03-17
      • 2017-04-24
      • 2013-04-21
      • 2014-09-22
      • 2014-07-29
      • 1970-01-01
      相关资源
      最近更新 更多