Loader Plugins(中文版)

JobbyM edited this page Apr 25, 2018 · 5 revisions

插件加载器(Loader Plugins)

以下还是草案, 未完结

插件加载器是AMD规范的延生,它允许使用非传统的方法加载 JavaScript依赖。

本API规范将允许使用插件加载器作为一种优化手段,将那些对该插件加载器敏感的插件资源加载到文本中。 出于兼容性考虑,一个插件加载器应该设计成能够在众多JavaScript环境下使用. 例如 browser, Node 或者 Rhino.

术语

插件依赖(plugin dependency) 是指按照AMD规范的插件加载器来加载的依赖. 它的格式如下:

[Plugin Module ID]![resource ID]

插件模块 ID(plugin module ID) 是一个普通的AMD模块ID名,它是实现了插件加载器API的JavaScript模块, 资源 ID(resource ID) 是一个特定的插件标示字符串,它的作用是让插件加载器知晓如何去解析这个资源.

插件加载器例子

下面是一个用 text 插件加载器去加载一份HTML模板.

    define(['text!../templates/start.html'], function (template) {
        //do something with the template text string.
    });

下面是另外一个使用更加复杂的资源ID结构。这是一个人为的例子.它只选择第一个匹配到索引数组的模块ID名。因此,下面的impl变量的结果是'./b'所代表的模块:

    define(function (require) {
        var impl = require('index!1:./a:./b:./c');
    });

API 使用说明

load: function (resourceId, require, load, config)

load是用来加载资源的函数。为了能够加载插件,这是一个必需要实现的API方法。我们假设资源ID不需要特别的normalization (参见normalize() method),下面是该方法的详细描述。

  • resourceId: 字符串类型. 待加载的插件资源ID名。该ID名必须是标准化(normalized)后的。
  • require: 函数类型. 一个用来加载其他模块的本地require函数。该require函数拥有如下属性:
  • load: 函数类型.当资源可用时,该函数将会且仅会被调用一次。它将插件加载完成的信息反馈给插件加载器。
  • config: 对象类型, 可选。一个配置对象。 它给优化工具和web app提供了一种传递配置信息的方法。 如果编译插件作为优化工具的一部分时,优化工具可以通过设置编译的属性配置为真来编译插件。

下面是一个普通的js模块加载,没做其他任何事情:

    define({
        load: function (name, req, load, config) {
            //req has the same API as require().
            req([name], function (value) {
                load(value);
            });
        }
    });

normalize: function (resourceId, normalize)

一个将传入的资源ID标准化的函数。模块ID的标准化通常指转换相对路径,比如将'./some/path' 或者 '../another/path'转化成不含相对路径的绝对模块ID名。这对于使用缓存和优化来说将非常有用,但是只在如下情况下需要实现:

  • 资源ID的标准化过于复杂。
  • 只在资源名不是模块名时需要。

如果插件没有哦实现normalize,那么加载器将默认它是规则的模块ID,并且试图标准化该模块ID。

需要标准化的参数:

  • resourceId: string类型. 待标准化的资源ID.
  • normalize: Function类型.一个依照当前加载器的配置,使用标准的模块相对路径转化规制,将传入的字符串ID转化成标准化模块ID的函数。

例如: 假设有个index!加载器,它将根据给出的模块名序列加载模块。这是一个反例,仅仅又来验证假设。This is a contrived example, just to illustrate the concept. 一个模块可能依赖于加载器提供的依赖,如下所示:

    define(['index!2?./a:./b:./c'], function (indexResource) {
        //indexResource will be the module that corresponds to './c'.
    });

在这个例子中,已经标准化的IDs'./a', './b', 以及 './c'将决定是否加载这个资源. 由于加载器不知道怎样去分析'index!2?./a:./b:./c',并将其标准化为 './a', './b', 以及 './c', 它需要插件来提供信息。这就是调用标准化函数的目的。

通过标准化的资源名称,这将使得加载器缓存值得到有效利用,并在优化器中正确地构建一个优化构建层。与此同时,加载器也可以将标准化ID传递到插件load方法中。

index!插件也可以这么使用:

    (function () {

        //Helper function to parse the 'N?value:value:value'
        //format used in the resource name.
        function parse(name) {
            var parts = name.split('?'),
                index = parseInt(parts[0], 10),
                choices = parts[1].split(':'),
                choice = choices[index];

            return {
                index: index,
                choices: choices,
                choice: choice
            };
        }

        //Main module definition.
        define({
            normalize: function (name, normalize) {
                var parsed = parse(name),
                    choices = parsed.choices;

                //Normalize each path choice.
                for (i = 0; i < choices.length; i++) {
                    //Call the normalize() method passed in
                    //to this function to normalize each
                    //module ID.
                    choices[i] = normalize(choices[i]);
                }

                return parsed.index + '?' + choices.join(':');
            },

            load: function (name, require, load, config) {
                require([parse(name).choice], function (value) {
                    load(value);
                });
            }
        });

    }());
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.