Skip to content

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);
                });
            }
        });

    }());