Skip to content
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

Run blocks inside lazy loaded files don't get executed #89

Closed
vlad-nica opened this issue Nov 9, 2014 · 21 comments
Closed

Run blocks inside lazy loaded files don't get executed #89

vlad-nica opened this issue Nov 9, 2014 · 21 comments

Comments

@vlad-nica
Copy link

Hi,

I've noticed that run blocks defined in lazy loaded files never get executed.
For demo I've put a run block that defines a template into $templateCache but because the specified block never gets executed, when a directive requires the defined template, it fails: "Failed to load template: printCapitalizedLazyLoaded.html"
Demo: http://deiweb.net/ocLazyLoad

Thanks for the awesome job you're doing!

@ocombe
Copy link
Owner

ocombe commented Nov 9, 2014

It is not a bug, the run & config blocks are executed when the module is loaded for the first time.
Here you lazy load a run block into an existing module, that's why it is not executed.
If you want it to run, two possibilities: lazy load a new module (instead of puting everything into the main one), or use the option reconfig: true (but since it is your main module, it will also call config and try to redefine your app config, including your routes, which will throw an error).

@ocombe ocombe added the invalid label Nov 9, 2014
@vlad-nica
Copy link
Author

Ah, ok. It would be useful to mention this in the documentation (about the run blocks).

Thanks!

@ocombe ocombe added bug and removed invalid bug labels Nov 9, 2014
@ocombe
Copy link
Owner

ocombe commented Nov 9, 2014

Hmm I checked, reconfig only works for config.
I need to add a parameter for rerun :)

@vlad-nica
Copy link
Author

I believe if you have multiple run blocks in a file for the same module, not all of them get executed (at least at a first look). I'll test later to be sure. Thanks and sorry for being a pain in the ass :)

@ocombe
Copy link
Owner

ocombe commented Nov 9, 2014

Eheh no problem, it's cool when someone find edge cases like this and takes the time to make a bugged version online that I can inspect and fix.
It makes the lib better for all the silent users who will never take time to report a bug.

And the run blocks should all be executed, there is a foreach loop.

@ocombe
Copy link
Owner

ocombe commented Nov 9, 2014

It's available in 0.4.0 !

@ocombe
Copy link
Owner

ocombe commented Nov 9, 2014

Woops there is a bug, a new run block will be added each time and they will all be runed (1 block the first time, 2 blocks the second time, ...).
Every time you load a .run function it will be added but the previous one won't be removed... I need to find a way to avoid this.

@vlad-nica
Copy link
Author

I discovered a problem regarding register function. If you load multiple modules, when register function is called in then callback of fileLoader function (line 564), params remains instantiated with last module params, therefore multiple problems arise because of this. In my case, rerun was not done if I had 2 modules and only the first one was set to be rerun.

@ocombe
Copy link
Owner

ocombe commented Nov 9, 2014

Hmmm I have a problem: the rerun parameter is supposed to allow the run blocks to be executed again, it works as expected. But if you reload the module and it readds the run block a second time, you will have 2 run blocks, which is not the expected behavior.
I can remove a run block when I execute it and the newly added run block can be executed as expected, but if someone wants to rerun it later (without adding a new run block), it won't work since it will not exist anymore...

There are two use case:

  • use rerun to rerun an existing run block
  • use ??? to allow the run block to be defined a second time

Do you think that I should store the old run blocks, and if there is the rerun parameter but that no new run block has been defined I should use the previous run block ?

As for the params remaining instantiated, I'll take a look, thanks.

@vlad-nica
Copy link
Author

I'm not sure I've understood the problem but from my point of view, when using angularjs as it is, run blocks are meant to be executed only once after module's has been configured. So in my opinion, a run block should be executed only once, otherwise, I suppose it's bad design. But you can choose any approach you think is the best and wait for other's opinions.

@ocombe
Copy link
Owner

ocombe commented Nov 9, 2014

Ok both problems are fixed in 0.4.1 ! Damn, 3 releases in one day :)

@vlad-nica
Copy link
Author

It's me again :) Rerun not working anymore. Check http://deiweb.net/ocLazyLoad/

@ocombe
Copy link
Owner

ocombe commented Nov 9, 2014

Damn ! What did I dooooo ?
Let's check.

edit: ok it's because of the params, the rerun param from the config object is not extended into the param object (that means that it would probably have failed with requirejs too !)

ocombe added a commit that referenced this issue Nov 9, 2014
@ocombe
Copy link
Owner

ocombe commented Nov 9, 2014

Ok, can you check master please? And if it's good I'll make yet another release :)

@ocombe
Copy link
Owner

ocombe commented Nov 9, 2014

Ok time to go to bed, I released 0.4.2 (let's hope everything is ok this time).

I really should take the time to do those unit tests...

@vlad-nica
Copy link
Author

It works now 👍

@amaschas
Copy link

amaschas commented Oct 10, 2016

I am still running into this problem, in the guise of the issue cited in the linked bug report for Webpack's ng-template-loader. The run block executes fine without ocLazyLoad in the mix, but fails even with rerun: true set if I'm lazy loading a module. The block that fails to run looks like this:

window.angular.module('ng').run(['$templateCache', function(c) { c.put(<path>, "<markup>") }]);

I tried it without the window.angular invocation (just angular.module) and go the same error.

@jwhitmarsh
Copy link

@amaschas did you get anywhere with this?

@amaschas
Copy link

amaschas commented Oct 9, 2017

@jwhitmarsh unfortunately no, we actually abandoned Angular entirely.

@AirBorne04
Copy link

AirBorne04 commented Nov 9, 2017

I just had a look at this issue as i depend on it for code splitting. As it seems to me there is the issue that only run block from the new module are executed, while webpack is adding the templates to the "ng" module. Therefor i came up with a strategy to run "ng" run blocks which are newly added after a file load. This could be handled in the core loader i would assume, though it is webpack specific it does not add much overhead to non webpack instances.

Here is my solution:

function lazyLoadProducts($transition$) {
  
  var $ocLazyLoad = $transition$.injector().get('$ocLazyLoad');

  // run functions before
  var before = angular.extend([], angular.module("ng")._runBlocks );

  // start the import
  return System.import(/* webpackChunkName: "products" */ "../../products/products").then(
    (mod) => {

      // run functions after lazy load
      var after = angular.module("ng")._runBlocks;

      angular.forEach(after, fn => {
        if (before.indexOf(fn) === -1) {
          $transition$.injector().native.invoke(fn);
        }
      });

      $ocLazyLoad.load(mod.PRODUCT_MODULE); }
  );
}

@DickLemm
Copy link

If you add the correct module name to the loader, it will also work fine.
{
loader: "ngtemplate-loader",
options: {
module: 'yourModuleName',
relativeTo: (path.resolve(__dirname, 'src')) + '/'
}
}

end use rerun when loading the module:
$ocLazyLoad.load(mod.default, {rerun:true});

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

No branches or pull requests

6 participants