U4-2265 - Macro cacheing doesn't respect RegisterJavaScriptFile/RegisterStyleSheetFile/AddJquery/RegisterClientScriptBlock

Created by Mike Chambers 24 May 2013, 08:32:53 Updated by Shannon Deminick 21 Jun 2017, 07:57:25

umbraco.library.RegisterStyleSheetFile("RoyalStylesCSS", "/css/royal-styles.css"); umbraco.library.AddJquery(); umbraco.library.RegisterJavaScriptFile("RoyalJS", "/scripts/vendor/royalslider.min.js");
umbraco.library.RegisterClientScriptBlock("Slider", @scriptBlock, true);

if you have macro cacheing enabled, but within that macro you also use any of the js/css/jquery registration in that macro. When the macro is called from the cache it fails to re-inject those registrations...

Any workarounds, other than including all my required JS/CSS and jquery in the template for every page on the site?


Shannon Deminick 31 May 2013, 00:06:55

Generally speaking XSLT shouldn't be used for registering server side stuff it should really just be used for outputting markup. There's really no way around this because these methods are trying to register something in the current page lifecycle but since it is cached it cannot interact with the current page lifecycle. My suggestion would be to shy away from using XSLT for any interaction with server side methods. In fact it's best to not use any cached macros or output cached controls when interacting with server side methods as you'll run into the same problem.

Mike Chambers 31 May 2013, 08:09:53

Actually it's a razor script macro ;-) but I understand your documented shortcomings.. Guess that means anything that is modular, eg only add this javacsript (say a gallery jquery plugin) include for this macro can't be cached ;-)

So what's your approach with umbraco macros for only including js includes as required for the specific functionality of a macro.. don't register in the header but put in line then you can't use the if already registered don't register again.. just don't use caching... Or do you include all js required for any macro on the site on all pages?


Shannon Deminick 31 May 2013, 14:44:55

ah sorry, but pretty much the same idea and has to do with macro caching.

This all comes down to how you want to manage your scripts on your site I guess. Generally you can include certain scripts/styles based on template by having a header content section that you can override in your templates to add custom stuff. For macro based stuff though, since you can probably add any type of macro to any content type that has an RTE, I'd just include those styles/scripts on all pages. This is better for client side caching too. Once the client receives that file it generally won't make a request for it again unless you are changing your etags in the headers or are doing ctrl+f5 to force reload content.

Lastly if you are worried about request size or number of requests you can implement resource mgmt frameworks like Client Dependency, Cassette, or by using .Net's built in System.Web.Optimization libraries, there's a few of these kinds of frameworks around that all have different benefits.

Mike Chambers 31 May 2013, 15:41:03

actually we steer clean of macros in the RTE, legacy because of the aw snap issue with chrome and not being able to render a view representation with medium trust. macro insertions by the client are via the macro container datatype into specific areas of the template. (or by the designers direct into the template.) We also tried client depenadcy but had issues with being not being able to separate css in the header and js in the footer (http://issues.umbraco.org/issue/U4-1279).

Whilst a pattern of including all js/css on every page is one route.. when you have several items such different image sliders, lightboxes, other jqueru plugins (so including all could be several hundreds of unneeded kilobytes) etc.. which this being a cms the client may never use any of those macros ... but on the other hand could suddenly decide to add.. the macro structure is great for modularising and wouldn't adding include in the client dependancy also fall foul of the same chache limitation.. as you say cacheing doesn't fit into this model of macro and complete modularisation, which is a pity

Shannon Deminick 01 Jun 2013, 00:18:33

Hey Mike, In webforms you can use the CDF placeholder provider to separate your JS/CSS to render wherever you like, in older versions this was not possible. See here: https://github.com/Shandem/ClientDependency/wiki#rendering-cssjavascript-in-your-page-1 (I've also replied to that other CDF issue you mentioned)

But anyways, having any sort of caching on a component that makes any server side call during it's rendering will never make that server side call after it is cached, that's just the nature of things. Only thing I can think of that 'might' be possible is if we had a MacroRendering event (not sure if this exists or not), then you could handle that event, determine which macro is executing and then inject your dependencies server side and then let the macro render, whether it is cached or not. That would mean that you'd have to code up your associated dependencies outside of your macro views which might not be ideal.

Another way when you are using macros would be to have a nested macro. The outer macro is not cached which contains any dependency calls needed to register with the server, then this renders an inner macro which is cached. In our MVC implementation you could just render a cached partial instead of rendering an inner macro.

Sebastiaan Janssen 01 Jun 2013, 14:25:40

Sorry about that, someone is marking a bunch of issues as fixed (they're now banned).

Shannon Deminick 21 Jun 2017, 07:57:25

Closing issue due to inactivity - see blog post for details https://umbraco.com/blog/issue-tracker-cleanup/

Priority: Normal

Type: Bug

State: Closed


Difficulty: Normal


Backwards Compatible: True

Fix Submitted:

Affected versions: 4.11.6, 4.11.8

Due in version:


Story Points: