Cargue bibliotecas JavaScript externas bajo demanda con Dojo 1.5

Y disminuya el tiempo de carga de las aplicaciones web

Dojo es una biblioteca ideal para crear aplicaciones de Internet enriquecidas. No obstante, las aplicaciones Web 2.0 complejas, por lo general, necesitan más de una sola biblioteca JavaScript y, cuando se cargan muchas bibliotecas al cargarse una página, el rendimiento puede verse afectado. En este artículo, aprenderá a cargar bibliotecas JavaScript de forma asincrónica y bajo demanda con dojo.io.script de Dojo. Con el código de ejemplo, podrá “encapsular” de forma concisa las cargas de las bibliotecas JavaScript externas.

Nick Maynard, Web 2.0 Consultant, IBM

Author photoNick Maynard forma parte del equipo de soluciones empresariales en el IBM Software Lab en Hursley, Reino Unido. Se especializa en Dojo, Ajax, programación web, servicios web y Linux. Puede contactar a Nick a través de nick.maynard@uk.ibm.com.



14-08-2012

Visión general

El kit de herramientas JavaScript de Dojo es una excelente biblioteca que ofrece casi todos los requerimientos para crear aplicaciones de Internet enriquecidas. Sin embargo, las bibliotecas JavaScript externas a veces deben utilizarse para requerimientos avanzados o de nicho de una aplicación. En esos casos, puede agregar la biblioteca a la aplicación usando el método HTML estándar, con el cual se agrega una etiqueta <script> adicional. Este procedimiento puede ocasionar una reducción del rendimiento. Afortunadamente, Dojo ofrece una alternativa a este método: dojo.io.script.

En este artículo, conocerá las ventajas y las desventajas del enfoque dojo.io.script. En el código de ejemplo, se muestra cómo evitar algunos de los errores más grandes. Puede descargar el código fuente utilizado en este artículo.

Dos métodos para cargar bibliotecas JavaScript externas

En la Tabla 1, se comparan dos métodos para cargar bibliotecas JavaScript externas.

Tabla 1. Etiqueta <script> y dojo.io.script
Etiqueta <script>dojo.io.script
Reducción de la velocidad de carga de una páginaPotencialmente alta; cuando se carga la biblioteca, se bloquea la inicialización de la página.Nula; la biblioteca se carga bajo demanda.
Reducción de la velocidad del códigoNula.El uso inicial provocará una demora mientras se carga la biblioteca.
ComplejidadSimple. Todos los códigos pueden utilizar la biblioteca de forma inmediata.Compleja. El código debe solicitar la biblioteca de forma inteligente y esperar a que esta se cargue.

El método dojo.io.script ofrece ventajas claras para las aplicaciones que solo utilizan una biblioteca externa en una rama de código específica. Y la carga diferida ofrece ventajas especiales. El método de la etiqueta <script> tiene la ventaja atractiva de ser simple cuando se utiliza la biblioteca en toda la aplicación. Es posible que prefiera dojo.io.script , ya que proporciona un tiempo de carga de página menor en todos los casos.


Uso de dojo.io.script

En el Listado 1, se muestra un ejemplo simple donde se utiliza dojo.io.script para cargar de forma asincrónica una sola biblioteca.

Listado 1. Invocación única de dojo.io.script
                dojo.require("dojo.io.script");

dojo.addOnLoad(function() {
    // Load the library.
    // dojo.io.script.get is asynchronous, so we get back a dojo.Deferred object
    var deferred = dojo.io.script.get({url : "url_of_library.js"});

    // Handle the deferred callback paths
    deferred.then(function() {
        // This function is called when the library is successfully loaded
        // You should place your application code that depends on the library here
    }, function() {
        // This function is called if an error occurs
    });
});

Uso avanzado

En el caso de las bibliotecas que tienen muchos módulos con dependencias entre módulos, es posible que deba encadenar invocaciones – similares a las descritas anteriormente – para obtener el comportamiento deseado durante el proceso de carga. En el Listado 2, se muestra un ejemplo más avanzado con invocaciones encadenadas.

Listado 2. Invocaciones encadenadas de dojo.io.script
 dojo.require("dojo.io.script");

dojo.addOnLoad(function() {
    // Load a JavaScript library consisting of two modules
    // We construct a partial function to load the second module; 
    // This simplifies the code path
    var deferred = dojo.io.script.get({url : "url_of_first_module.js"})
        .then(dojo.hitch(dojo.io.script, 'get', {url : "url_of_second_module.js"}));
    
    // Deferred handling goes here 
});

Administración de la complejidad

Cuando se cargan bibliotecas con muchos módulos con dojo.io.script o cuando se usan bibliotecas en diferentes ubicaciones del código, la administración de dojo.io.script y de los objetos diferidos resultantes puede ser compleja. Con los puntos de uso múltiple, se debe evitar particularmente que un módulo se cargue dos veces.

Si carga bibliotecas con muchos módulos o usa bibliotecas en diversas ubicaciones, considere usar métodos intermediarios.


libproxy

El método libproxy administra las dependencias entre módulos y asegura que los módulos se carguen solo una vez. En el código de muestra del Listado 3, se muestra cómo usar libproxy.

Listado 3. Uso de libproxy (libproxy_example.html)
dojo.require("proxy.jsv");

dojo.addOnLoad(function() {
    var jsvProxy = new proxy.jsv();
    
    jsvProxy.load('json-schema-draft-01').then(function() {
        // At this point, the JSV module for validating against draft 1 has been loaded.
        alert("loaded JSV draft 1");
    });
});

En el Listado 4, se muestra cómo usar libproxy para encapsular la carga de la biblioteca JSON Schema Validator (JSV) de Gary Court.

Listado 4. Carga encapsulada de la biblioteca JSV (proxy/jsv.js)
dojo.provide("proxy.jsv");

dojo.require("com.ibm.developerworks.libproxy");

/**
 * 
 */
dojo.declare("proxy.jsv", [com.ibm.developerworks.libproxy], {

    /**
     * In this file, we define the structure of our library,
     * and its inter-module dependencies
     */
    constructor : function() {
        var jsvRoot = "https://raw.github.com/garycourt/JSV/master/lib";
      
        this.modules = {
            '_uri' : { 
                sources : [{url : jsvRoot + "/uri/uri.js"}]
            },
            'base' : { 
                sources : [{url : jsvRoot + "/jsv.js"}], 
                deps : ['_uri']
            },
            'json-schema-draft-01' : { 
                sources : [{url : jsvRoot + "/json-schema-draft-01.js"}], 
                deps: ['base']
            },
            'json-schema-draft-02' : { 
                sources : [{url : jsvRoot + "/json-schema-draft-02.js"}], 
                deps: ['base'] 
            },
            'json-schema-draft-03' : { 
                sources : [{url : jsvRoot + "/json-schema-draft-03.js"}], 
                deps: ['base'] 
            }
        };
    }
    
});

En el Listado 5, se muestra el código libproxy.

Listado 5. Implementación básica para el encapsulado de bibliotecas (com/ibm/developerworks/libproxy.js)
dojo.provide("com.ibm.developerworks.libproxy");

dojo.require("dojo.io.script");
dojo.require("dojo.DeferredList");

/**
 * Do not directly use this class; instead, extend it and redefine the
 * modules field in the constructor
 */
dojo.declare("com.ibm.developerworks.libproxy", [], {

    constructor : function() {
        this._moduleDeferreds = [];
    },

    /**
     * Holds the modules of the library (and optional references to their
     * dependencies).
     * 
     * NB: 'sources' and 'deps' arrays will be loaded in parallel. If you need
     * to serialise this, add another module layer. ie. uri.js MUST be loaded
     * before jsv.js below
     * 
     * The 'sources' array holds objects that are passed in their entirety to
     * dojo.io.script.get()
     * 
     * Example, { 'module1Ref': { sources: [{ url: "module1.js" }] },
     * 'module2Ref': { sources: [{ url: "module2.js" }], deps: ['module1'] } };
     */
    modules : null,

    /**
     * Returns a dojo.Deferred object whose callback/errback fires when the
     * module is ready for use. Callback chain will contain the module
     * reference.
     * 
     * Example usage: load('module2').then(function() {});
     */
    load : function(/* String */moduleRef) {
        var F = this.declaredClass + ".";
        console.debug(F + "load()", arguments);

        // Check cache - have we loaded this library module before?
        if (this._moduleDeferreds[moduleRef]) {
            return this._moduleDeferreds[moduleRef];
        }

        // Create a new deferred and cache it
        var deferred = this._moduleDeferreds[moduleRef] = new dojo.Deferred();

        var module = this.modules[moduleRef];
        if (module) {
            deferred.callback(moduleRef);
            if (module.deps) {
                // Load dependencies in parallel
                deferred = deferred.then(dojo.hitch(this,
                        function(/* Array */dependencies) {
                            var defs = dojo.map(dependencies, dojo.hitch(this,
                                    'load'));
                            return new dojo.DeferredList(defs, false, true);
                        }, module.deps));
            }
            // Load sources in parallel
            deferred = deferred.then(dojo.hitch(this,
                    function(/* Array */sources) {
                        var defs = dojo.map(sources, dojo.hitch(dojo.io.script,
                                'get'));
                        return new dojo.DeferredList(defs, false, true);
                    }, module.sources));
        } else {
            deferred.errback("Unknown module reference.");
        }

        return deferred;
    }
});

Resumen

La administración del tiempo de carga de una página cuando utiliza muchas bibliotecas y kits de herramientas JavaScript puede convertirse rápidamente en un problema. En este artículo, conoció una alternativa a las etiquetas <script>. Puede usar el recurso dojo.io.script de Dojo para acelerar los tiempos de carga de una página cargando bibliotecas de forma diferida. Ante la complejidad presentada por este enfoque, aprendió a usar libproxy como intermediario para administrar las dependencias y las cargas.


Descargar

DescripciónNombretamaño
Sample, wrapping JSV library using libproxysample.zip4KB

Recursos

Aprender

Obtener los productos y tecnologías

Comentar

Comentarios

developerWorks: Ingrese

Los campos obligatorios están marcados con un asterisco (*).


¿Necesita un IBM ID?
¿Olvidó su IBM ID?


¿Olvidó su Password?
Cambie su Password

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


La primera vez que inicie sesión en developerWorks, se creará un perfil para usted. La información en su propio perfil (nombre, país/región y nombre de la empresa) se muestra al público y acompañará a cualquier contenido que publique, a menos que opte por la opción de ocultar el nombre de su empresa. Puede actualizar su cuenta de IBM en cualquier momento.

Toda la información enviada es segura.

Elija su nombre para mostrar



La primera vez que inicia sesión en developerWorks se crea un perfil para usted, teniendo que elegir un nombre para mostrar en el mismo. Este nombre acompañará el contenido que usted publique en developerWorks.

Por favor elija un nombre de 3 - 31 caracteres. Su nombre de usuario debe ser único en la comunidad developerWorks y debe ser distinto a su dirección de email por motivos de privacidad.

Los campos obligatorios están marcados con un asterisco (*).

(Por favor elija un nombre de 3 - 31 caracteres.)

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


Toda la información enviada es segura.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=90
Zone=WebSphere
ArticleID=829936
ArticleTitle=Cargue bibliotecas JavaScript externas bajo demanda con Dojo 1.5
publish-date=08142012