按需加载[延迟加载]模块的模式

时间:2013-02-18 15:59:02

标签: boilerplatejs

在我的应用程序中,我需要在初始化阶段加载模块(通过在./modules/modules中枚举它们),但稍后根据某些条件(例如用户授权结果)按需加载。想象一下,我想用计算器模块提供用户A ,用文本编辑器模块提供用户B

为简单起见,我们将 boilerplatejs 示例应用程序视为应用程序,并假设sampleModule1sampleModule2将按需加载。

所以我从 src \ modules \ modules.js 中的初始加载序列中删除模块:

    return [
        require('./baseModule/module'),
        /*require('./sampleModule1/module'),
        require('./sampleModule2/module')*/
    ];

并将控件添加到摘要页面( src \ modules \ baseModule \ landingPage \ view.html )以按需加载它们:

<div>
    Congratulations! You are one step closer to creating your next large scale Javascript application!
</div>
<div>
    <select id="ModuleLoader">
        <option value="">Select module to load...</option>
        <option value="./modules/sampleModule1/module">sampleModule1</option>
        <option value="./modules/sampleModule2/module">sampleModule2</option>
    </select>
</div>

然后我修补 src \ modules \ baseModule \ module.js 以将上下文传递给 LandingPageComponent (由于某种原因它不在原始源代码中):

        controller.addRoutes({
            "/" : new LandingPageComponent(context)
        });

最后将加载代码添加到 src \ modules \ baseModule \ landingPage \ component.js

            $('#ModuleLoader').on('change', function(){
                require([this.value], function(mod){
                    moduleContext.loadChildContexts([mod]);
                    alert('Module enabled. Use can now use it.');
                });
            });

这似乎有效,但这是最好的方法吗?

它是否正确处理上下文加载?

如何防止加载同一模块两次?

2 个答案:

答案 0 :(得分:1)

您可以通过为更改事件使用命名函数来防止多次加载模块,并在执行后解除该函数的绑定。

答案 1 :(得分:1)

聪明的想法......我过去几天一直在努力将BoilerplateJS改进为延迟加载模块作为插件。我做了类似的事情,你可以访问POC代码:

https://github.com/hasith/boilerplatejs

在我做的POC中,我正在尝试同时实现'延迟加载'+'可配置ui'。

  • 每个屏幕(称为应用程序)都是放置在布局上的组件(插件)的集合。这些应用程序定义只是一个JSON对象,可以从服务器API动态返回,也可以静态定义为JSON文件(就像在POC中一样)。在POC中,应用程序定义存储在“/ server / application”中。

  • 现在可以按惯例动态调用这些应用程序。例如,“/ ## / shipping-app”将在“/ server / application”中查找具有相同名称的应用程序定义。

  • 应用程序加载通过'/ modules / baseModule / appShell'中的新组件进行。任何与'/ ## /'相关的内容都将被路由到此组件,然后它将尝试从“/ server / application”文件夹加载应用程序定义按惯例

  • 当'appShell'收到应用程序定义(作为JSON)时,它将尝试动态加载在其中定义的组件(插件)。这些可插入组件放在'src / plugins'中,也会按照惯例加载。

示例应用程序定义如下所示:

{
    "application-id" : "2434",
    "application-name" : "Order Application",
    "application-layout" : "dummy-layout.css",

    "components" : [    
        {
            "comp-name" : "OrderDetails",
            "layout-position" : "top-middle"
        },
        {
            "comp-name" : "ShippingDetails",
            "layout-position" : "bottom-middle"
        }
    ]

}

该方法的好处如下:

  • 应用程序接口是组件驱动的,可在运行时配置
  • 根据用户角色等(后端的逻辑),可能会向用户发送不同的应用程序定义
  • 可以通过组合现有组件即时创建应用程序
  • “框架”中不需要更改新的应用程序或组件,因为加载是基于约定的

这些是最初的想法。感谢任何反馈!