New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to lazy load a DLL bundle? #3115

Closed
IAMtheIAM opened this Issue Oct 10, 2016 · 11 comments

Comments

Projects
None yet
7 participants
@IAMtheIAM

IAMtheIAM commented Oct 10, 2016

Require.ensure is awesome. But when I lazy load a huge javascript library, such as Kendo UI which is 3MB itself, it adds 10 seconds to my build time.

What I would like is to require.ensure a DLL bundle. I got my DLL bundle working fine, but webpack seems to expect to load it at runtime, and I havent figured out how to lazy load a DLL bundle.

I tried loading with script-loader

       require('script!../../../wwwroot/js/dlls/kendo.dll.bundle.js');
      SubscriberComponent.prototype.loadKendoUIGrid();

But kendo is undefined (which is normally set in the bundle)
I also tried scriptjs, which just appends the given script to the head at execution.

const loadScript = require('scriptjs');

      loadScript('/dlls/kendo_jquery.dll.bundle.js', () => {
        SubscriberComponent.prototype.loadKendoUIGrid();
    });

But kendo is still undefined.

If I do a normal require.ensure, it works perfectly

      // Async load KendoUI for jQeury, with webpack require.ensure
      require.ensure(['jquery'], function(require) {


         /** These are for the jQuery version of Kendo UI */
         // require('lib/kendoui/styles/kendo.material.min.css');
         require('../../lib/kendoui/styles/kendo.common.min.css');
         require('../../lib/kendoui/styles/kendo.default.min.css');
         require('../../lib/kendoui/js/kendo.web.min.js');
         require('../../lib/kendoui/js/kendo.core.min.js');
         require('script!../../lib/kendoui/js/kendo.grid.min.js'); // must pass through "script-loader"

         // Must call the prototype function, because 'this' is undefined inside the require.ensure during runtime
           HomeComponent.prototype.loadKendoUIGrid();

      }, "kendo.for.jquery") // 3rd parameter is the name of the chunk during compilation output - chunk.name.js

But again, it forces webpack to rebuild the same library every time.

So how can I lazy load a DLL bundle correctly at runtime?

@sokra

This comment has been minimized.

Show comment
Hide comment
@sokra

sokra Oct 12, 2016

Member

Use the scriptjs approach. Try a different output.libraryTarget.

Member

sokra commented Oct 12, 2016

Use the scriptjs approach. Try a different output.libraryTarget.

@IAMtheIAM

This comment has been minimized.

Show comment
Hide comment
@IAMtheIAM

IAMtheIAM Oct 12, 2016

I tried all 6 of the options listed here and they didn't work for me. I got, "define is not defined", "module is not defined", "exports is not defined", which caused the entire app to break.

Using "var", "this", or "umd" made no difference, the app loads but still "kendo is not defined".

Can you elaborate a little more about how to configure this correctly? When I try debugging, none of the breakpoints inside my dll bundle kendo_jquery.dll.bundle.js get hit, except the first line

var kendo_jquery_lib =
webpackJsonp_name__lib([1],{

/***/ 0:
/***/ function(module, exports) {

module.exports = function() { throw new Error("define cannot be used indirect"); };

(rest of modules here)
/***/ },

It seems like its not executing any of the modules, which need to set a global var kendo.

IAMtheIAM commented Oct 12, 2016

I tried all 6 of the options listed here and they didn't work for me. I got, "define is not defined", "module is not defined", "exports is not defined", which caused the entire app to break.

Using "var", "this", or "umd" made no difference, the app loads but still "kendo is not defined".

Can you elaborate a little more about how to configure this correctly? When I try debugging, none of the breakpoints inside my dll bundle kendo_jquery.dll.bundle.js get hit, except the first line

var kendo_jquery_lib =
webpackJsonp_name__lib([1],{

/***/ 0:
/***/ function(module, exports) {

module.exports = function() { throw new Error("define cannot be used indirect"); };

(rest of modules here)
/***/ },

It seems like its not executing any of the modules, which need to set a global var kendo.

@sokra

This comment has been minimized.

Show comment
Hide comment
@sokra

sokra Oct 17, 2016

Member

If that's the content of your dll bundle there is something incorrect with you dll build. The dll bundle should contain the webpack runtime.

Member

sokra commented Oct 17, 2016

If that's the content of your dll bundle there is something incorrect with you dll build. The dll bundle should contain the webpack runtime.

@gaganjakhotiya

This comment has been minimized.

Show comment
Hide comment
@gaganjakhotiya

gaganjakhotiya Oct 17, 2016

I've been trying to do something similar. After digging a bit inside the bundled DLL file, I've come to understand that DLL bundles do not execute any modules by themselves. The execution of the first module in DLL bundle is being done (in my case) inside a progressively built bundle.

I tried a diff of the bundle w/o DLL and with DLL. Here's what I found:

Bundle in normal build:

/* 0 */
/***/ function(module, exports, __webpack_require__) {

    __webpack_require__(1);
    module.exports = __webpack_require__(337);


/***/ },
/* 1 */

Same code in DLL bundled - manifest build:

/* 0 */
/***/ function(module, exports, __webpack_require__) {

    module.exports = __webpack_require__;

/***/ },
/* 1 */

And, somewhere in a progressively built bundle, I find this:
__webpack_require__(1)

I've some code in module 1 that helps me dynamically load different assets for my website. But, due to this, I've implemented a nasty workaround -- to load module 1 -- that I don't like at all.

gaganjakhotiya commented Oct 17, 2016

I've been trying to do something similar. After digging a bit inside the bundled DLL file, I've come to understand that DLL bundles do not execute any modules by themselves. The execution of the first module in DLL bundle is being done (in my case) inside a progressively built bundle.

I tried a diff of the bundle w/o DLL and with DLL. Here's what I found:

Bundle in normal build:

/* 0 */
/***/ function(module, exports, __webpack_require__) {

    __webpack_require__(1);
    module.exports = __webpack_require__(337);


/***/ },
/* 1 */

Same code in DLL bundled - manifest build:

/* 0 */
/***/ function(module, exports, __webpack_require__) {

    module.exports = __webpack_require__;

/***/ },
/* 1 */

And, somewhere in a progressively built bundle, I find this:
__webpack_require__(1)

I've some code in module 1 that helps me dynamically load different assets for my website. But, due to this, I've implemented a nasty workaround -- to load module 1 -- that I don't like at all.

@IAMtheIAM

This comment has been minimized.

Show comment
Hide comment
@IAMtheIAM

IAMtheIAM Nov 2, 2016

If that's the content of your dll bundle there is something incorrect with you dll build. The dll bundle should contain the webpack runtime.

I separated the webpack runtime out of dll bundle into commons.bundle.js which is loaded before any dlls. Like this:

   <script type="text/javascript" src="js/commons.bundle.js.gz?8609335d43fa570a3897"></script> <--- (webpack runtime is here)
   <script type="text/javascript" src="dlls/polyfills.dll.bundle.js.gz?8609335d43fa570a3897"></script>
   <script type="text/javascript" src="dlls/vendors.dll.bundle.js.gz?8609335d43fa570a3897"></script>
   <script type="text/javascript" src="js/app.bundle.js.gz?8609335d43fa570a3897"></script>

Is that still wrong? I thought it would take the runtime in commons and execute bundles inside dlls?

IAMtheIAM commented Nov 2, 2016

If that's the content of your dll bundle there is something incorrect with you dll build. The dll bundle should contain the webpack runtime.

I separated the webpack runtime out of dll bundle into commons.bundle.js which is loaded before any dlls. Like this:

   <script type="text/javascript" src="js/commons.bundle.js.gz?8609335d43fa570a3897"></script> <--- (webpack runtime is here)
   <script type="text/javascript" src="dlls/polyfills.dll.bundle.js.gz?8609335d43fa570a3897"></script>
   <script type="text/javascript" src="dlls/vendors.dll.bundle.js.gz?8609335d43fa570a3897"></script>
   <script type="text/javascript" src="js/app.bundle.js.gz?8609335d43fa570a3897"></script>

Is that still wrong? I thought it would take the runtime in commons and execute bundles inside dlls?

@mnzaki

This comment has been minimized.

Show comment
Hide comment
@mnzaki

mnzaki Nov 17, 2016

How did you go about solving this? I'm facing a related (but fairly different) issue.
Have you tried placing your module imports, that are supposed to be resolved by the DllReference, inside a require.ensure block?

mnzaki commented Nov 17, 2016

How did you go about solving this? I'm facing a related (but fairly different) issue.
Have you tried placing your module imports, that are supposed to be resolved by the DllReference, inside a require.ensure block?

@IAMtheIAM

This comment has been minimized.

Show comment
Hide comment
@IAMtheIAM

IAMtheIAM Dec 6, 2016

I have yet to solve this, and I do not know how to proceed at the moment. I'm hoping we can get some more input from a webpack wizard who can shine some light on this. Hint hint @sokra :-)

IAMtheIAM commented Dec 6, 2016

I have yet to solve this, and I do not know how to proceed at the moment. I'm hoping we can get some more input from a webpack wizard who can shine some light on this. Hint hint @sokra :-)

@mnzaki

This comment has been minimized.

Show comment
Hide comment
@mnzaki

mnzaki Dec 7, 2016

Related issue: #2592

mnzaki commented Dec 7, 2016

Related issue: #2592

@pstephenwille

This comment has been minimized.

Show comment
Hide comment
@pstephenwille

pstephenwille Mar 5, 2017

I had the same basic problem which was due to loading order. Once I moved require.js, which defines 'define' and 'require', into the header I was able to require my modules using Webpacks libraryTarget of 'amd'.

pstephenwille commented Mar 5, 2017

I had the same basic problem which was due to loading order. Once I moved require.js, which defines 'define' and 'require', into the header I was able to require my modules using Webpacks libraryTarget of 'amd'.

@webpack-bot

This comment has been minimized.

Show comment
Hide comment
@webpack-bot

webpack-bot Sep 4, 2017

This issue had no activity for at least half a year.

It's subject to automatic issue closing if there is no activity in the next 15 days.

webpack-bot commented Sep 4, 2017

This issue had no activity for at least half a year.

It's subject to automatic issue closing if there is no activity in the next 15 days.

@webpack-bot

This comment has been minimized.

Show comment
Hide comment
@webpack-bot

webpack-bot Sep 19, 2017

Issue was closed because of inactivity.

If you think this is still a valid issue, please file a new issue with additional information.

webpack-bot commented Sep 19, 2017

Issue was closed because of inactivity.

If you think this is still a valid issue, please file a new issue with additional information.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment