【问题标题】:Dynamic System.import with webpack?动态 System.import 与 webpack?
【发布时间】:2016-07-06 08:16:17
【问题描述】:

我正在尝试移植一些我编写的使用 systemjs + Babel 的 ES6 代码。

我在移植大部分代码时没有任何问题。

但是,我有一些代码需要动态加载 ES6 模块,如下所示:

function load(src) {
    System.import(src).then(function() {});
}

src 是一个外部 ES6 模块,它也可能有依赖项(静态导入)。

如何将此代码移植到 Webpack ?如果我尝试使用 require 语句,我会收到一个警告,根据 Webpack 文档,这似乎是正常的。

【问题讨论】:

    标签: webpack es6-module-loader


    【解决方案1】:

    你在 webpack 中没有“动态加载”之类的东西(因为捆绑器需要深入到你所有的模块依赖项)。最接近您想要实现的目标(以及在 webpack 中实现它的正确方法)是使用 require.ensure - see documentation

    将 SystemJS 代码转换为 webpack 的一种方法是:

    function load(moduleName) {
        switch (moduleName) {
            case 'foo':
                require.ensure([], require) => {
                    const foo = require('./foo.js');
                    // do something with it
                }
                break;
            case 'bar':
                require.ensure([], require) => {
                    const bar = require('./bar.js');
                    // do something with it
                }
                break;
        }
    }
    

    我建议您创建一个封装每个 require.ensure 的加载函数(您可能希望以不同的方式管理回调)。

    您可以查看示例here

    【讨论】:

    • 不幸的是我不能使用 switch/case:我不知道文件名。
    • 为什么不知道文件名?这在 WebPack 中没有意义。在 WebPack 中,您捆绑您的文件,因此您的所有文件都需要在您的文件系统中。因此,您需要预先了解您的文件,以便它们出现在您的源代码中,对吧?
    • “你在 webpack 中没有“动态加载”之类的东西(因为捆绑器需要深入到你所有的模块依赖项)”。这是完全错误的。 require.ensure 进行真正的动态加载。检查开发控制台中的网络选项卡:正在触发对实际附加捆绑文件的实际请求。这是这个结构的全部意义:允许 Webpack 做code splitting
    • 我建议您制作一个封装每个 require.ensure 的加载函数(您可能希望以不同的方式管理回调)。 这实际上是个坏建议。尽管代码本身很麻烦,但尝试封装它只会让事情变得更糟,因为 Webpack 需要文字模块名称,以便它可以进行条件加载。不要做require.ensure([myVariable], ...,而是做require.ensure(['./my/module'], ...
    【解决方案2】:

    您可以尝试使用像 little-loader 这样的库来处理这个问题。示例:

    var load = require('little-loader');
    
    load('<src>', function(err) {
        // loaded now, do something
    });
    

    【讨论】:

    • 我想我确实必须使用某种外部加载器。但我需要得到脚本执行的结果:我不确定 little-loader 是否支持。
    • 你可以在项目中询问。在某些情况下,一个有趣的替代方法是通过 ajax 和 eval 在基于 iframe 的沙箱中加载代码。然后从那里捕获结果。不过,对于您的目的而言,这可能有点矫枉过正。
    • 鉴于您的 src 可以拥有自己的依赖项(静态导入),这可能不是一个完全可以解决的小问题。您甚至需要在尝试评估要加载的模块之前加载这些导入。
    【解决方案3】:

    Webpack 1 不支持 System.import,您可以通过使用 Webpack 的 require.ensure 动态加载模块来解决这个问题。可以在此处找到该方法的详细信息:https://webpack.github.io/docs/code-splitting.html#es6-modules

    根据你想要做什么,你可能还需要使用 Webpack 的 context 功能,请参阅此处了解更多信息 https://webpack.github.io/docs/context.html

    Webpack 2 应该会解决这些问题,因为它将直接支持 ES6 和 System.import。

    【讨论】:

      【解决方案4】:

      之前的答案是正确的,但现在在 webpack 2.2 + babel 中(在撰写本文时,v2.2.0-rc.3 是最新版本)我们可以做到这一点。我没有测试过自己,但也只是做了引导我到这里的研究。

      从 webpack 文档中阅读:Code Splitting with es2015

      该部分的正下方是Dynamic Expressions,在此示例中:

      function route(path, query) {
        return import("./routes/" + path + "/route")
          .then(route => new route.Route(query));
      }
      // This creates a separate chunk for each possible route

      请务必注意,正如文档所述,您需要安装 Syntax Dynamic Import plugin

      【讨论】:

      • import 是否优于 System.import()
      • @notgiorgi 这取决于您的 IMO 用例。如果您只需要导入一个文件并且它不需要是动态的,那么只需执行System.import webpack 只会构建一个额外的包,从而缩短构建时间。如果您执行动态import,webpack 将为它在您的情况下可以找到的每个潜在路径构建一个捆绑包,这可能会使构建时间更长。
      • 我没有看到记录在案的行为。 function getStatic() { return import("./component) }function getDynamic(path) { return import("./" + path) }getStatic() // works finegetDynamic('component') // throws error: Cannot find module
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-04
      • 2020-08-31
      • 2015-11-08
      • 1970-01-01
      • 1970-01-01
      • 2017-12-04
      • 2020-03-08
      相关资源
      最近更新 更多