www w3org spec section official etiquetas javascript webpack amd commonjs

javascript - w3org - w3c etiquetas html



Require.ensure() sin bloqueo (4)

Si tenemos paquetes diferentes creados por webpack y requerimos. Asegurarnos de que se transfiera y evalúe dinámicamente en un momento posterior, esto sucede a través de jsonPadding y algunos webpack js magic. Si tenemos

require.ensure([ ], ( require ) => { console.log(''before...''); var data = require( ''./myModule.js'' ); console.log(''after...''); }, ''myModule'')

"after..." se encontrará cuando el módulo se transfiera y evalúe por completo. Si resulta que este trozo / módulo es bastante grande, contiene imágenes, css y todo eso, la carga casi bloqueará un navegador mientras que el código javascript del paquete web desempaqueta el paquete con todos sus componentes.

Pregunta : ¿Hay alguna forma de "enganchar" a eso que require magia? Por ejemplo, sería un escenario de sueño tener devoluciones de llamada para:

  • Todo el archivo / trozo fue transferido
  • imagen [1] fue evaluada
  • css [1] fue evaluado / estilo de etiqueta fue inyectada
  • javascript fue evaluado

y así sucesivamente, suponiendo que nuestro paquete transferido contiene una gran cantidad de datos. En general, me molesta bastante tener una buena opción para transferir dinámicamente paquetes enteros dinámicamente, pero aún así tengo que cargar ese paquete de manera totalmente sincronizada / bloqueada.


Permítanme comenzar diciendo que sé que esta podría ser una respuesta ''molesta'', porque no responde directamente a su pregunta, pero ofrece una solución alternativa, pragmática, al problema del navegador. Yo mismo utilicé este patrón para administrar la carga de activos en el contexto de un gran juego web en 3D.

Estoy escribiendo esto como una respuesta y no como un comentario, por lo que podría servir a otros que se encuentren con el mismo problema. Si esto responde a su caso, me complacerá proporcionar el código real para implementar y generar este tipo de módulos.

Si comprendo correctamente, esencialmente lo que desea es una forma de dividir MyModule en componentes discretos que se pueden cargar y evaluar de forma atómica en el contexto de un require.ensure . require.ensure , pero manejar la evaluación para que no todo se evalúe de una vez, lo que da como resultado un navegador. colgar.

Una forma diferente de ver esto es usar los métodos require y ensure como los mecanismos de carga / evaluación. Considere MyModule.js , que es un módulo de carga enorme con las dependencias Css1, Css2, ... CssN , así como JS1, JS2, ... JSN e imágenes.

Mi sugerencia es SuperMyModule.js en SuperMyModule.js que requiere MyModuleLogic.js , así como todo el CSS, las imágenes y JS.

Nodo, en SuperMyModule.js puedes hacer:

let myModuleLogic = require("myModuleLogic"); console.log(''JS was evaluated''); require.ensure([''image1.png''], ( require ) => { let data = require( ''./images1.png'' ); console.log(''image[1] was evaluated''); // register that resource was evaluated/fire event }) require.ensure([''style1.css''], ( require ) => { let data = require( ''./style1.css'' ); console.log(''css[1] was evaluated''); // register that resource was evaluated/fire event }) //after all resources evaluated/fire callback or event

Luego en tu archivo original, como solicitaste:

require.ensure([ ], ( require ) => { console.log(''before...''); let myModule = require( ''./superMyModule.js'' ); console.log(''after...''); })

Y si configura la instancia de su módulo como un emisor de eventos, posiblemente se enganche en la carga de recursos de la siguiente manera:

require.ensure([ ], ( require ) => { let myModule = require( ''./superMyModule.js'' ); myModule.on("loadResource", myCallback) })


Puede descargar el subproceso principal y evitar el bloqueo utilizando el cargador de trabajo.

Desventaja: hay un mensaje extra que se debe hacer entre la ventana principal y el trabajador.

https://github.com/webpack/worker-loader

También puede intentar emitir eventos de carga en el módulo grande para realizar un seguimiento del progreso más granular.

Referencia adicional:


Si desea iniciar la carga del paquete de JavaScript asíncrono a través de require.ensure y otras Promesas, aquí le indicamos cómo puede lograrlo:

const requireEnsurePromise = new Promise((resolve) => { require.ensure([''./modulePath''], function (requireEnsure) { console.log(''The module is fetched but not evaluated yet''); resolve(requireEnsure.bind(null, require.resolve(''./modulePath''))); }); }); Promise.all([ fetch(''/api/relevant/stuff'').then(response => response.json()), requireEnsurePromise, ]).then((values) => { if (values[0]) { // DO STUFF } console.log(''right before module is evaluated''); const evaluatedModule = values[1](); });

El paquete web determinó de forma estática cuál es la ruta del módulo que corresponde a la representación interna del paquete web (podría ser un entero o una cadena). Cada vez que Webpack reconoce el requisito require.ensure require.ensure([], fn) , mira el cuerpo de la función de la devolución de llamada fn y lo hace. Para retrasar el tiempo de evaluación después de obtener el paquete de JavaScript de forma Prometida, require(''./modulePath'') no puede estar presente dentro de la devolución de llamada de require.ensure success ya que evaluará el módulo. Webpack traduce require(''./modulePath'') a algo como __webpack_require__(2343423) , por eso le gustaría evitar usarlo en este escenario.


Supongo que yo mismo estaba confundido sobre el tema, por lo que mi pregunta probablemente no fue lo suficientemente precisa como para recibir una respuesta adecuada. Sin embargo, mi malentendido en todo el contexto de "carga del módulo dinámico commonJS" fue que require.ensure() simplemente transferirá el Código del Módulo (respectivamente el fragmento que creó el paquete web) a través del cable. Después de eso, el Chunk transferido, que básicamente es solo un gran archivo ECMAscript, se queda en el navegador, guardado en caché pero aún no evaluado. La evaluación de todo el fragmento se realiza solo en la llamada a require() real.

Dicho esto, está totalmente en sus manos cómo desacoplar y evaluar las partes individuales de un Módulo / Chunk . Si, por ejemplo, como en mi pregunta original, un módulo requires() en algunos archivos CSS , algunas imágenes y algo de HTML , que todo se transfiera de forma asíncrona en la llamada require.ensure() . De qué manera usted require() (y, por lo tanto, evalúe ) esas partes depende completamente de usted y usted puede desacoplarlas si es necesario.

Por ejemplo, un módulo se parece a esto:

Module1.js

"use strict"; import { io } from ''socket.io-client''; document.getElementById( ''foo'' ).addEventListener(''click'', ( event ) => { let partCSS = require( ''style/usable!./someCoolCSS.css'' ), moarCSS = require( ''style/usable!./moarCoolCSS.css'' ), tmpl = require( ''./myTemplate.html'' ), image1 = require( ''./foo.jpg'' ), image2 = require( ''./bar.png'' ); }, false);

Por supuesto, todos estos archivos ya están contenidos en el fragmento que se transfiere al cliente, cuando algún otro módulo llama:

require.ensure([ ''Module1.js'' ], ( require ) => { }, ''Module1'');

Esto es donde estaba mi confusión. Así que ahora, solo podemos jugar con las llamadas require() dentro de module1.js . Si realmente necesitamos muchos archivos de esa manera, incluso podríamos usar un setTimeout ejecución setTimeout / setImmediate para desacoplar la evaluación sincrónica entre cada llamada require() si es necesario o deseable.

En realidad una respuesta larga para una historia bastante simple.

TL; DR: " require.ensure transfiere una parte entera por el cable. Esta parte contiene todos los archivos que forman parte de una llamada require() dentro del Módulo asegurado. Pero esos archivos no se evalúan automáticamente. Eso sucede solo cuando el real require() llamada require() coincide en tiempo de ejecución (que está representada por una llamada webpackJSONP en este punto) "