Component based clientlibs AEM - javascript

Is it better to split up clientlibs by components if it means more calls to the server?
I.e. using
<%#taglib prefix="ui" uri="http://www.adobe.com/taglibs/granite/ui/1.0" %>
<ui:includeClientLib categories="mqd.component.accordion" />
in the <component>.jsp instead of compiling all the CSS in a single stylesheet.

From what I know, this is more of a decision based your use case, there is no one approach which fits all the scenarios -
Loading CSS at component level
When you load CSS at the component level, it is not available in the HEAD section when the page rendering process kicks off. It will only render your component CSS when it encounters it somewhere in the body tag.
Conditionally loading CSS based on the component is not available by default, you would have to write custom logic to achieve this.
From this post,
One 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.
Also, with component level CSS, you would have to ensure the styles
for a component don't affect styles for another component, i.e. you
would have to use narrow selectors to do this and ensure you don't
break anything else in the process.
Also, with component level CSS, you would have to ensure the styles for a component don't affect styles for another component, i.e. you would have to use narrow selectors to do this and ensure you don't break anything else in the process.
Other approaches
Using page components - If you have a component which has a lot of styles and you don't want this to get loaded on every other page, you can look at using page components(different templates) to achieve this. Each page component can load a different group of clientslibs based on its use.
Using deferred clientlibs - If your layout constantly changes and you’re worried about how big your clientlibs file has become, deferred clientlibs might be a better option. Example from the link listed below -
… [Navigation component logic]
<ici:js-defer>
<cq:includeClientLib js=”icidigital.components.navigation”/>
</ici:js-defer>
[Navigation component end]
… [Sitemap component logic]
<ici:js-defer>
<cq:includeClientLib js=”icidigital.components.siteMap”/>
</ici:js-defer>
[Sitemap component end]
becomes…
<div class=”footer” />
<script type=”text/javascript” src=”path/to/programmatically/combined/deferred/clientlib.js”></script>
</div>
Whatever approach you take, ensure caching, page load times, maintenance, performance, etc are taken into account.
Further read
Best approaches to clientlibs in AEM
CSS best practices in clientlibs

Related

Customizing native web components styling by the consumer

I've got a bunch of web components built where a consumer may be consuming one or many of these components.
They are used by adding a script tag to the components minified JS and then using the web component in your code like so: <my-cool-component data="someData" />.
CSS is built into these components, however, I need to add functionality to allow the consumers to customize the color theme, and I'm wondering if my approach here could be improved, or if there is a better approach all together.
Right now I have it setup so that when someone consumes any of the components, like my-cool-component and they have a window.coolComponentOptions set like this:
window.coolComponentOptions = {
PRIMARY_BUTTON_BACKGROUND_COLOR: 'tomato',
PRIMARY_BUTTON_COLOR: '#fff',
URL_COLOR: 'tomato',
FONT: 'Arial',
SECONDARY_BUTTON_BACKGROUND_COLOR: 'lightblue',
... // Obviously this could grow tremendously
}
I do a check inside of my-cool-component and see if the coolComponentOptions exist and if so I map them to the CSS variables and use them inside of any of the components.
Alternatively I could make these values props on the component itself like <my-cool-component primary-btn-color="tomato" /> but this could cause the consumer to have an element with tons of attributes, and when they consume <other-cool-comp /> they will need to repeat these attributes again.
I'm curious if there are any other (better) options than the way I am doing it with the window variable, or if that approach could be improved upon or is completely acceptable?
CSS variables can be global CSS definitions.
And shadowParts give you even more global CSS / shadowDOM styling.
Very good explainer by Monica Dinculescu, former Google Web Components team member
https://meowni.ca/posts/part-theme-explainer/

How to deal with components inside dynamic html strings in Sapper & Svelte?

I am trying to make my first Sapper site and I'm populating the content similarly to how it's done in the template here.
My problem is that I want to allow usage of custom components in the content of {#html post.html}. Currently it doesn't work, the HTML is just inserted there without being treated like a component, even if I import the component in [slug].html and it works if used directly somewhere besides that {#html post.html}.
The behaviour is kind of expected as the content is fetched after svelte has finished it's work, but I am not sure what should I do then. I want a couple of custom components like <FancyButton> to be usable in the user generated content.
Can I ask the [slug].html component to look at the post.html or just whole content after insertion and create an instance of child component wherever it should be? Or should I somehow compile the string beforehand on the server?

Using Vue-cli, is it possible to build the CSS -into- the `dist/vue-COMPONENT_NAME.js` file?

TLDR: Does anyone know of an elegant way to make sure a component injects its own <style>{...everything in ./dist/vue-COMPONENT_NAME.css}</style> element into the page, but only once? SSR friendly too?
I've been on the hunt for a good solution to this for over 2 days now; I'm building a Vue component that is likely to be used by mostly non-built, client side environments, included in the page via script tag:
<script src="https://unpkg.com/vue-COMPONENT_NAME/dist/vue-COMPONENT_NAME.js"></script>
And, normally you would just use a link tag to get the styles in there:
<link rel="stylesheet" href="https://unpkg.com/vue-COMPONENT_NAME/dist/vue-COMPONENT_NAME.css">
..but I would like remove the requirement to add the additional (possibly forgotten) link tag to the page. I would like for this component to be able to automatically inject its required styles into the page, so it is never displayed in an un-styled state.
This is a graphics focused component using a Canvas for display, and some of its internal logic is built on analyzing the clientBoundingRect of the top level DOM node - So having the styles that set its size and proportions at mount is imperative.
I am also planing on using this component myself via Nuxt, so I'm going to have to make sure that whatever solution I come to avoids the dreaded "The client-side rendered virtual DOM tree is not matching server-rendered content." error message.
So far, I have been loving how low-configuration the build with vue-cli has been:
vue build vue-COMPONENT_NAME.vue --prod --lib VueCOMPONENT
...but its output is always the two files:
./dist/vue-COMPONENT_NAME.js
./dist/vue-COMPONENT_NAME.css
Is there an argument or configuration prameter for vue-cli that would cause it to build the styles into ./dist/vue-COMPONENT_NAME.js? Has anyone done anything like this with vue-cli?

Adding content to react elements

I am new to react.js and I have heard that this js library reacts badly to anything that modifies it's component structure.
Is there any specific procedure to add content into react elements using Jquery. For example, if we want to add content into react's div field, can we directly use Jquery append method to insert text to that div or is there any other way to implement things?.
The idea is that you either use a traditional approach, or you ditch jQuery and use react and this means using the react rendering tree, probably build tasks, client-side router/SPA.
You should not modify the DOM generated by react components from outside it since it maintains an internal state and a virtual DOM that would become out of sync. You either use one ecosystem or another; they are two very different approaches to writing a website.
If you want to introduce react on a small part of the website first, I would suggest to gather all your data with jquery and then transmit the data into the react component.
Roughly
// gather data with jquery or whatever
var data_array = gatherData();
ReactDOM.render(<MyCustomComponent data={data_array}/>, $('#my-react-root')[0])
Rendering changes during runtime can be managed the same way. Just gather the data again and change the state of the react component accordingly.
If you don't want to extract the data or the html is to complex, you can use dangerouslySetInnerHTML to just path a plain text html string.
From the docs:
<div dangerouslySetInnerHTML={{__html: getMarkup()}} />
Best wishes
Andreas

How to implement an Enterprise-grade JavaScript "framework" for web designers?

I have been tasked with improving the current mess that is our JavaScript "strategy"; we're an online shopping company and my boss has given me time to do this properly. He is very keen on keepin this modular and increase the reusability of the components.
Our HTML is being rendered with JSP and we have lots of custom tags writing out, for example, information about products without the web designers needing to worry about it.
Now, we want to do similar things with JavaScript. The web designers should be given a set of custom tags, like, say,
<foo:draggable>
... some HTML here ...
</foo:draggable>
that will wrap the HTML in a <div> with a drag bar at the top and a close button.
My idea is to mark the div with a unique namespaced CSS class name, like foo_draggable, and then put all my functions in a single JS file. That JS file then sees if there are elements with the CSS class foo_draggable in the DOM and if it finds any it will attach the required event handlers.
However, I am worried about scaling problems, and wondering whether it is a good idea to have lots of selector queries running when they quite often aren't going to be used.
The first alternative would be to initiate each draggable item explicitly but that would mean putting <script> tags all over the place. The second approach would be to not put all UI function in one file but rather just download the ones I need, but that would mean lots more HTTP requests and slower page load speed.
Has anyone got experience with this?
What about having two classnames?
<div class='foo fooDragable'></div>
<div class='foo fooSortable'></div>
You add the class 'foo' to all your elements that require javascript modification.
Your javascript has to check the dom only once for foo.
var $foo = $('.foo');
Afterwards you can search within this array which should be way smaller than the complete dom.
var $dragAble = $foo.filter('.fooDragable');
Have you considered or taken a look to JSF? I know it's a major change if you aren't using JSF yet. But there are lot of ready-to-use JSF component libaries with an ajaxical sauce, for example RichFaces, IceFaces, PrimeFaces, etc. It's almost a waste of time to create components/tags for it yourself.
Alternatively you can replace all Javascripts to use the great jQuery JS framework.
Depending on how many separate components you have, the extra overhead of running the selectors might not be a big deal. You can initialize all the components just the once, when the page is loaded. Anything that's not present on the page simply won't get initialized, and will incur no further overhead. In most JavaScript frameworks, selecting by classname (or tag name) is pretty fast. It's only the complex selectors, which aren't natively supported by the browser, that are slow.
If you have a few commonly used components, and then a set of less commonly used ones, it may be worth splitting those up. Keep the commonly used components in a single JavaScript file (minified, served with compression and aggressive caching), and load that in every page, regardless of whether it's needed or not. Caching will ensure it's only downloaded once, and it'll only be one small HTTP request. For the less common components, keep them in separate files (ideally, one per component), and add a script tag on pages that use them.
I'm not entirely familiar with how JSP works, but it might be possible to do this automatically - if a tag is included in the document, add a script tag for foo_widget.js in the document header, or something like that.

Categories

Resources