Skip to content

Dive Deeper

Performance

The eSales Lifestyle components are displaying critical content (e.g. search results). It is therefore important that the script is not blocked by other JavaScript code.

Performance tips

  • Use the defer attribute on all non-critical other script tags.
  • Include the eSales Lifestyle scripts as early as possible, before any non-critical scripts.
  • Keep the number and size of synchronous script tags low

Within this context, non-critical scripts refers to code that does not produce any critical visual change for content above the fold. For example, scripts for social sharing features and visitor tracking can often be delayed until the page is rendered before they run.

Differential loading

The pattern called Differential Loading by the Angular framework is an approach where modern browsers will download and use a more optimized JavaScript bundle. It is accomplished by taking advantage of the fact that only more recent browsers implement a feature called JavaScript Modules (often referred to as esm for ECMAScript Modules).

When using differential loading, browsers supporting JavaScript Modules will use modern ECMAScript features, saving approximately 15% script size for eSales Lifestyle. The legacy bundle will transform the code to support older browsers.

<head>
  <script src="https://cdn.esales.apptus.com/integration/v1/esales-lifestyle.js" type="module"></script>
  <script src="https://cdn.esales.apptus.com/integration/v1/esales-lifestyle.es5.js" nomodule defer></script>
  <script src="init-esales-lifestyle.js" defer></script>
</head>
  • type="module": This marks a script tag as a JavaScript Module. It enables import/export syntax in the code and is fetched with defer by default.
  • nomodule: This attribute on a script tag will make a browser that implements JavaScript Modules ignore the script tag. Older browsers, such as Internet Explorer 11, will ignore it and execute the script normally.

Deferring scripts

Due to module script tags always being deferred, defer must also be used in the script that runs the esales.init() code to bootstrap components. This also means that the eSales Lifestyle components will not be rendered until the DOM has been completely parsed (right before DOMContentLoaded event).

The amount of time before e.g. search results are rendered on a page depends a lot on the surrounding site when using defer. See the following performance suggestions.

  • Use the defer attribute to avoid having synchronous scripts as much as possible.
    Synchronous JavaScript blocks rendering of a web page, both CSS and HTML. One of the most important features for displaying a page quickly, other than having less JavaScript, is to make sure that non-critical JavaScript is not blocking page rendering. Critical JavaScript may be anything that displays content "above the fold". Non-critical JavaScripts should ideally use the defer attribute so that it executes when the document is fully parsed and ready. For more information about how browsers parse HTML, see the Mozilla blog.
  • Use as few scripts as possible (with defer or not) before esales-lifestyle.js.
    In general eSales Lifestyle displays important content, such as search results, category navigation, recommendations, and more. To reduce the time until such content is rendered, it is best to add the eSales Lifestyle scripts and initialization early. The sooner the script executes, the faster requests are sent to the server returning content to render.

Defer separate script via attribute

Keep the initialisation in its own script file, and load the scripts in the correct order through using defer. Scripts with type="module" are fetched with defer by default.

<head>
  <script src="https://cdn.esales.apptus.com/integration/v1/esales-lifestyle.js" type="module"></script>
  <script src="https://cdn.esales.apptus.com/integration/v1/esales-lifestyle.es5.js" nomodule defer></script>
  <script src="init-esales-lifestyle.js" defer></script>
</head>
// esales-init.js

esales.init({
  // ...
});

Defer inline script via event

The DOMContentLoaded event can be used to preserve the correct execution order, since defer has no effect on inline scripts. The defer scripts are executed right before DOMContentLoaded. This way inline scripts can be paused until the deferred scripts have run.

<script src="https://cdn.esales.apptus.com/integration/v1/esales-lifestyle.js" type="module"></script>
<script src="https://cdn.esales.apptus.com/integration/v1/esales-lifestyle.es5.js" nomodule defer></script>
<script>
window.addEventListener('DOMContentLoaded', function() {
  esales.init({
    // ...
  });
});
</script>

Web components

The term "web components" is an umbrella term that refers to several technologies working together. The main parts of this are "custom elements", "HTML template tags" and "shadow DOM". The webcomponents.js includes all these in the bundle it provides. The polyfills for the main component libraries for modern and legacy browsers also include these features.

  • Custom elements - A way to package lifecycle hooks and logic into a re-usable tag, e.g. <product-card>.
  • HTML template tags - A <template> element contains inert content. That means it will not be rendered and links/sources will not be fetched. The content can be easily cloned and inserted into the DOM.
  • Shadow DOM - Provides a way to encapsulate DOM content inside a node, so that outside styling will not affect it.

Support for these three features needs to exist natively in the browser or be provided by webcomponents.js for eSales Lifestyle components to work correctly.

Slots

A <slot> is a way for web components (with Shadow DOM) to display content inside them. This allows custom content to be displayed in various locations or states of web components that support slots. The slot attribute is used with the slot id, to determine what slot (location or state) to display the content, e.g.

<p slot="[slot-identifier]">

Hiding slot content on load

The content of the slot may become visible before the component library is loaded. The standard way of avoiding this is to hide the content of the slot as long as the element is not defined. This is done by using a style tag outside of the component. The following example hides the Navigation assistant component.

<style>
esales-navigation-assistant:not(:defined) {
    display:none;
}
</style>

Browser support

The modern bundle is built for, and will be used by, all modern browsers. Modern browsers are "evergreen", i.e. often updated and automatically rolled out to all users. Testing and maintenance will apply to versions listed below only.

  • Last 10 versions of Chromium (Chrome, Edge, etc.)
  • Last 4 versions of Safari
  • Last 5 versions of Firefox

Legacy browsers

The list below shows which legacy browsers are currently supported with the .es5.js version of the library. Older browsers, including Microsoft IE11 and Legacy Edge, are not actively supported or tested against.

  • Google Chrome v49 to v60
  • Mozilla Firefox v46 to v59
  • Apple Safari v9 to v10

Polyfills

Polyfills are bits of code that are meant to fill in support for features that may not be available in all browsers yet. This is typically done by performing a check whether the API exists and possibly check that it is implemented correctly. If not, the script will add the API manually so that it will exist for forthcoming code.

The needed polyfills for each browser are automatically downloaded via differential loading.

Feature Package / Repository Legacy (es5) Modern
URL url-polyfill
URLSearchParams url-polyfill
KeyboardEvent.key Custom (based on keyboardevent-key)
es2015 API core-js/es6
array.includes() core-js/es7.array.includes
Object.entries() core-js/es7.object.entries
fetch() whatwg-fetch
IntersectionObserver IntersectionObserver
Web Components webcomponentsjs

Last update: April 27, 2021
×
Copyright

This online publication is intellectual property of Apptus Technologies. Its contents can be duplicated in part or whole, provided that a copyright label is visibly located on each copy and the copy is used in conjunction with the product described within this document.

All information found in these documents has been compiled with utmost attention to detail. However, this does not guarantee complete accuracy. Neither Apptus Technologies nor the authors shall be held liable for possible errors or the consequences thereof.

Software and hardware descriptions cited in these documents might be registered trademarks. All trade names are subject to copyright restrictions and may be registered trademarks. Apptus Technologies essentially adheres to the manufacturer’s spelling. Names of products and trademarks appearing in this document, with or without specific notation, are likewise subject to trademark and trade protection laws and may thus fall under copyright restrictions.

CLOSE