Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Require.ensure() non-blocking

If we have different bundles created by webpack and we require.ensure something to dynamically transfer+eval it at a later point in time, it happens via jsonPadding and some webpack js magic. If we have

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

"after..." will get encountered when that module was entirely transferred and evaluated. If it happens to be that this chunk / module is pretty big, contains images, css and whatnot, the loading will pretty much lock down a browser while the webpack javascript code unpacks the bundle with all its components.

Question: Is there any way to "hook" into that require magic? For instance, it would be a dream scenario to have callbacks for:

  • whole file / chunk was transferred
  • image[1] was evaluated
  • css[1] was evaluated / style tag was injected
  • javascript was evaluated

and so forth, assuming that our transferred bundle contains a lot of data. In general it just bothers me pretty hard to have a nice option to asynchronously transfer whole bundles dynamically, but still have to load that very bundle in full sync / blocking fashion.

like image 597
jAndy Avatar asked Aug 17 '16 13:08

jAndy


People also ask

Does webpack use CommonJS?

Webpack supports the following module types natively: ECMAScript modules. CommonJS modules.

What is require context?

require. context is a special feature supported by webpack's compiler that allows you to get all matching modules starting from some base directory.


1 Answers

Let me preface by saying I know this might be an 'annoying' answer, because it doesn't answer your question directly but offers an alternative, pragmatic, solution to the browser hanging problem. I used this pattern myself to manage asset loading within the context of a heavy 3D web game.

I'm writing this as an answer and not as a comment so it might serve others who come across the same problem. If this does answer your case, I'll be happy to provide actual code to implement and generify these sort of modules.

If I understand correctly, essentially what you want is a way to break down MyModule into discrete components which can be atomically loaded and evaluated within the context of one require.ensure, but handle evaluating so that not everything is evaluated in one go resulting in browser hang.

A different way to look at this is to use the require and ensure methods themselves as the loading/evaluation mechanisms. Consider MyModule.js, which is a huge-loading module with the dependencies Css1, Css2, ... CssN as well as JS1, JS2, ... JSN and images.

My suggestion is to break it down into SuperMyModule.js which requires MyModuleLogic.js as well as all the CSS, images and JS.

Node, in SuperMyModule.js you could do:

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

Then in your original file, like you requested:

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

And if you set up your module instance as an event emitter possibly hook into the loading of resources like so:

require.ensure([ ], ( require ) => {
    let myModule = require( './superMyModule.js' );
    myModule.on("loadResource", myCallback)
  })
like image 140
OpherV Avatar answered Oct 19 '22 21:10

OpherV