2012-08-22 13 views
29

En mi aplicación de red troncal, debo proporcionar un respaldo para cada archivo requerido, en caso de que el CDN que los entrega falle.RequireJS: respaldo local para si CDN falla

He tratado sobrescribiendo require.onError así:

require.onError = function (err) { 
    if (err.requireType === 'timeout') { 
     var url = err.requireModules; 

     if (!!~url.indexOf("jquery/")) 
      console.warn("CDN timed out, falling back to local jQuery.js") 
      require(["libs/jquery"]); 
      return; 
     if (!!~url.indexOf("jqueryui/")) 
      console.warn("CDN timed out, falling back to local jQueryUI.js") 
      require(["libs/jqueryui"]); 
      return; 
     if (!!~url.indexOf("underscore")) 
      console.warn("CDN timed out, falling back to local underscore.js") 
      require(["libs/underscore"]); 
      return; 
     if (!!~url.indexOf("backbone")) 
      console.warn("CDN timed out, falling back to local backbone.js") 
      require(["libs/backbone"]); 
      return; 
    } 
} 

El problema es que esto de forma asincrónica cargar los archivos de respaldo. Necesito que estos archivos se carguen en orden, al igual que la declaración require original, donde uso el complemento order!.

Con el onError reemplazado: cuando el CDN no se carga, la carga de respaldo se inicia, pero no se espera. Esto presenta un problema porque los scripts se ordenan para cargarse según sus dependencias. Aquí es un vistazo a mi require declaración original, que depende de la CDN:

require([ 
    "order!http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js", 
    "order!http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js", 
    "order!http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.3/underscore-min.js", 
    "order!http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min.js", 
    "order!utils/date", 
    "order!core/core", 
    "order!core/errors", 
    "order!core/constants" 
], function() { 
    ... 
} 
+0

Ambos de CDN no son terribles, sólo fallan en promedio una vez al día durante una ventana de alrededor de un minuto como máximo, y están libres. De todos modos, creo que este es un problema interesante de resolver. Siempre es bueno tener retrocesos, incluso si tiene un CDN perfecto, para preservar la experiencia del usuario. ¿Puedes sugerirnos cualquier otro CDN? – Austin

+0

Entiendo de dónde vienes, pero no estoy en condiciones de sugerir que se compre algo como esto para nuestra empresa sin proporcionar una amplia prueba de que he intentado todo para que el sistema actual funcione. Además, estoy interesado en cualquier proeza de programación, y puedo ver que esta solución particular es útil para muchas personas, ya que muchos desarrolladores (en particular, autónomos) no usan CDN de pago. – Austin

+1

CDN es realmente barato ahora ($ 2 a $ 3 por mes) ... Estoy usando AccuWebHosting.Com CDN y nunca experimenté ningún tiempo de inactividad. Bueno, si un servidor falla en CDN, el contenido se entrega inmediatamente desde el próximo POP más cercano ... Y generalmente hay de 40 a 50 POP en un buen CDN ... –

Respuesta

57

¿Qué versión de RequireJS está usando? Parece que quizás desee configurar el respaldo de jQuery como una ruta en su configuración, luego configure jQuery como una dependencia de los otros módulos que lo necesiten. Si está utilizando ~> 2.0, algo así (no probado):

// in your requirejs config 
requirejs.config({ 
    //To get timely, correct error triggers in IE, force a define/shim exports 
    // check. 
    enforceDefine: true, 
    paths: { 
     jquery: [ 
      'http://somecdn.com/jquery.min', // your cdn 
      'lib/jquery' // your fallback 
     ], 
     jqueryui: "http://somecdn.com/jquery-ui.min.js" 
    }, 
    shim: { 
     jqueryui: ['jquery'] 
    } 
}); 

// then in your requires 
require([jquery, jqueryui, foo, bar], function($) { 
    // stuff 
}); 

Hablan de cómo hacerlo in the wiki. Si no está usando v2.x, hay un método para manejar eso aquí también.

Si todos los módulos están configurados para especificar sus propias dependencias, tampoco debería preocuparse por las directivas order!.

+0

Pásame a la publicación por 2 minutos, pero sí, esta es la respuesta que elegí. – Austin

+0

Jaja ni siquiera. Creo que fueron unos 15 segundos. – numbers1311407

+2

¿Cómo se maneja esto una vez que ejecuta el optimizador? ¿Agrega etiquetas de script al html para los archivos excluidos? – sidonaldson

19

He encontrado una solución al problema provisto en RequireJS 2.x.x. Hubo una demanda de esta solución, por lo que, a su vez, RequireJS agregó un objeto paths a su configuración. Esto proporciona una funcionalidad alternativa para los CDN, en caso de que fallen.

También se debe tener en cuenta que el complemento order! ha quedado obsoleto en Require 2.0, por lo que también tuve que utilizar el objeto shim para definir dependencias. En realidad es una idea bastante interesante.

Aquí está mi nuevo require.config:

require.config({ 
    urlArgs: "ts="+new Date().getTime(), // disable caching - remove in production 
    paths: { 
     jquery: [ 
      "http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min", 
      "libs/jquery" 
     ], 
     jqueryui: [ 
      "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min", 
      "libs/jqueryui" 
     ], 
     underscore: [ 
      "http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.3.3/underscore-min", 
      "libs/underscore" 
     ], 
     backbone: [ 
      "http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.9.2/backbone-min", 
      "libs/backbone" 
     ] 
    }, 
    shim: { 
     'jqueryui': ['jquery'], 
     'underscore': ['jquery'], 
     'backbone': ['underscore'], 
     'core/core': ['underscore'], 
     'core/errors': ['core/core'], 
     'core/constants': ['core/core'] 
    } 
}); 
Cuestiones relacionadas