【问题标题】:Async load modules via knockoutjs with webpack通过带有 webpack 的 knockoutjs 异步加载模块
【发布时间】:2017-04-15 10:03:58
【问题描述】:

我目前正在使用 webpack 建立一个 knockoutjs 项目。我想要实现的主要方面之一是捆绑包的延迟加载。虽然我已经能够实现代码拆分,但它目前需要应用程序专门包含此代码,我想摆脱这个特定代码,因为我相信 knockoutjs 已经配备了必要的基础设施。

在应用设置期间,组件在 knockoutjs 中注册如下:

ko.components.register('form-page', { require: 'components/form-page/form' });

Knockout 将加载引用的模块,并仅使用组件表单页面的异步要求。

使用我的 webpack 设置,这将失败,因为

  • Webpack 没有检测到 components/form-page/form 存在依赖
  • 模块名称被 webpack 修改为一些短标识符,因此组件/表单页面/表单在运行时是未知的

理想情况下,我会让 webpack 将其检测为异步模块依赖项,但在第一步中,在保留模块名称的同时声明我希望在 webpack 配置中可用的模块就足够了,让 ko 需要它的依赖项根据需要。

知道如何做到这一点吗?

【问题讨论】:

    标签: knockout.js webpack webpack-2


    【解决方案1】:

    简短的回答是,我还没有找到动态执行此操作的方法。 不过,这里有另一种方法。

    src/components/Input/Input.js

    示例组件

    import ko from 'knockout';
    import FormComponent from '../../../classes/FormComponent';
    
    class InputControl extends FormComponent {
      constructor(params) {
        super(params);
      }
    }
    
    ko.components.register('input-control', {
      viewModel: InputControl,
      template: require('./Input.html')
    })
    

    src/components/index.js

    使用 webpack 内置的东西循环遍历每个组件文件夹以获取 ko.components.register

    const components = require.context('./', true, /\.js$/);
    
    components.keys().forEach(function(component) {
      const componentName = component.substr(2);
      require('./' + componentName);
    });
    

    src/app.js

    在 applyBindings 发生之前注册组件很重要,否则 ko 不会知道它们。

    require("./components");
    
    var PageModel = function() {...}
    model = new PageModel();
    
    ko.applyBindings(model);
    

    基本上创建所有组件并一次性包含它们。适用于热模块更换等。通常也很轻巧。

    【讨论】:

      【解决方案2】:

      您可以使用自定义组件加载器https://knockoutjs.com/documentation/component-loaders.html

      var myloader =  {
          loadComponent: function (name, componentConfig, callback) {
              if (!componentConfig.import) {
                  callback(null);
                  return;
              }
      
      
              componentConfig.import()
                  // Using the defaultLoader so we can support the different component configs knockout supports by default
                  .then(config => ko.components.defaultLoader.loadComponent(name, config, callback));
          }
      }
      

      并将其添加到淘汰赛装载机。使用 unshift 所以它是第一个加载器命中

      ko.components.loaders.unshift(myloader);
      

      现在您的组件注册更改为

      ko.components.register('form-page', { import: () => import(/* webpackChunkName: "form-page" */'components/form-page/form') });
      

      这利用了 Webpack 的 lazy loading。虽然要知道动态导入需要一些额外的 babel 插件。

      webpackChunkName 注释告诉 webpack 给它输出的 js 文件取什么名字。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-02-11
        • 2018-01-11
        • 2017-10-04
        • 2012-12-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多