Skip to main content
Level 2
May 2, 2018
Solved

Component specific ClientLibs?

  • May 2, 2018
  • 14 replies
  • 12191 views

Hey folks,

I haven't seen a way to do this, but is there a way to load CSS/JS in your <head> conditionally when a specific component is on page?

The use-case is that we have a component with quite a bit of CSS/JS that is ONLY used on a given page or two, so rather than load that CSS/JS everywhere, we only want to load it when that component is on-page.

I'm sure I could query the page I'm on and see if the component is on page, but I was wondering if there's a more performant/built in way to do this.

Thanks!

This post is no longer active and is closed to new replies. Need help? Start a new post to ask your question.
Best answer by joerghoh

By default this is not possible. The standard rendering process starts from the top of the page and all generated markup is immediately written to the output buffer, and then sent to the client. That means at the point when you reach your component the header is already written and comitted.

The only way to achieve this is to intercept that behaviour. Use a filter and buffer *all* data written to the output buffer in memory. Then you can render safely all components and if you encounter your special component you can set a flag in the request attributes. The filter can then check for these attributes, change the buffer accordingly and then send everything out.

That approach is a bit risky, because it *can* consume a lot of memory. And it changes the rendering performance and behaviour of your page. But it might be worth a try.

Jörg

14 replies

Rima_Mittal
Level 4
May 2, 2018

Why don't you have a specific category for the component clientlibs and include the clientlibs in the component jsp/html file itself?

Level 2
May 2, 2018

I don't think that's exactly what I want because then the JS/CSS would be in the page body where the component is, and not in the <head>.

smacdonald2008
Level 10
May 2, 2018

There is no way to put a client lib - say in a page header and have it only load if a certain component is dropped onto the page. As Rima suggested - if you only want a clientlib to load for a specific component - add the HTL synatx to the component -- ie:

<sly data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html" data-sly-call="${clientlib.css @ categories='bannerComponent'}"/>

Also - make no difference if call is made in body to head - it still gets loaded either way. In other words - if you only need a specific Clientlib in a component - no advantage to load it within the head section.

VeenaVikraman
Community Advisor
Community Advisor
May 2, 2018

I would like to agree with scott and rima. I had tried this few times but could neva figure out a solution . As of now my answer would be no.

joerghoh
Adobe Employee
joerghohAdobe EmployeeAccepted solution
Adobe Employee
May 2, 2018

By default this is not possible. The standard rendering process starts from the top of the page and all generated markup is immediately written to the output buffer, and then sent to the client. That means at the point when you reach your component the header is already written and comitted.

The only way to achieve this is to intercept that behaviour. Use a filter and buffer *all* data written to the output buffer in memory. Then you can render safely all components and if you encounter your special component you can set a flag in the request attributes. The filter can then check for these attributes, change the buffer accordingly and then send everything out.

That approach is a bit risky, because it *can* consume a lot of memory. And it changes the rendering performance and behaviour of your page. But it might be worth a try.

Jörg

Level 2
May 2, 2018

These answers confirmed what I suspected, so I'm trying something a bit different where at the page level, I run a query against the children JCR nodes looking for the component, then if I find it, I add the clientlib on the template...

Thoughts?

smacdonald2008
Level 10
May 2, 2018

That apprach sounds like it will impact performance. Why  again is adding clientlib to the actual HTML of the component not a good solution for you?

yogeshVaidya
Level 2
May 3, 2018

Though adding component level client library should be a perfect solution for your case, the only problem I am seeing is that the time required to load JS and CSS of that component.

People prefer to load CSS at the head and JS just before end of body because they want to show static stylized content as soon as possible. If this(size of CSS and JS files) is not the problem then you can use component level client library.

Are you using specific editable template(s) for those pages? if yes then will adding client library of that component in page design solve your problem?

Level 2
May 3, 2018

Typically we're trying to load alot of our critical path first and blocking things that aren't styled, but I've been looking into it and maybe this is the route we want to go.

The only thing that is concerning is the JS that would be part of the component, rather than trying to pull everything to the top of the head, Is there a way to defer the JS load for particular components to the bottom of the body?

smacdonald2008
Level 10
May 3, 2018

" Is there a way to defer the JS load for particular components to the bottom of the body?" - no that is not possible.