Component specific ClientLibs? | Community
Skip to main content
New Participant
May 2, 2018
Solved

Component specific ClientLibs?

  • May 2, 2018
  • 14 replies
  • 12120 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

joerghoh
Employee
April 19, 2019

To make this work, you would need to traverse the page's resource tree first and scan all included components for the clientlibs they require. That can be a complex task if you need to handle content fragments/experience fragments, iparsys etc as well. If you have an idea, which is both easy to implement and maintain and also does not have a performance impact on page rendering, please let me know :-)

But instead I would recommend to have the JS/CSS of the majority of components being contained in a single clientlib. You are probably delivering more than required on that page, but you reduce the development overhead significantly. And in the end you need to balance these 2: client rendering time vs development effort.

New Participant
April 18, 2019

Do you think if this is possible by somehow populating a property on page level with what all components are there in the page (either by traversing nodes in the page or, adding listener on drop to add component category) and dynamically then adding these values in the categories value here in the headlibs/footlibs html?

data-sly-call="${clientlib.all @ categories='properties.componentCategoriesInPage'}"

joerghoh
Employee
May 3, 2018

Hi,

you can split the JS of a component into 2 different clientlibs: a "head-CL" and and a "bottom-CL"; the head-CLs are loaded in the head, and the rest at the bottom. Then you can decide for each component which part of the JS is loaded earlier than the rest.

Jörg

New Participant
May 3, 2018

Is this call smart enough to not load the CSS/JS twice if the same component is used twice on the same one page?

smacdonald2008
New Participant
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.

New Participant
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?

yogeshVaidya
New Participant
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?

smacdonald2008
New Participant
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?

New Participant
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?

joerghoh
joerghohAccepted solution
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