Skip to main content

Lazy Loading

Since RVS is written in React it means it will bring in React too which will add non-trivial weight to you page. Luckily this can be mitigated almost completely by lazy loading: Fox example you can the load it just time when the search input is focused.

The lazy loading is done using the dynamic import() statement and the provided loader tools.

To make things lazy loadable we must split the code into two files: main.js and valu-search.js for example. The main.js will contain triggers for the lazy loading and the dynamic import() statement. The valu-search.js will then contain the actual import to the ValuSearch class, its initialization and export as the default export:

valu-search.js:

import { ValuSearch } from "@valu/react-valu-search";

const vs = new ValuSearch({
customer: "<customer id>",
apiKey: "<api key>",
slots: {
modalHeader: () => null,
},
});

export default vs;

main.js:

// 👇 It's important to not import @valu/react-valu-search directly here but
// only the subpackage `lazy`. This ensures the main entry bundle won't get
// bloated by RVS.
import { LazyValuSearch, select } from "@valu/react-valu-search/lazy";

const loader = new LazyValuSearch({
// import the file exporting the ValuSearch instance as the default export
load: () => import("./valu-search"),
});

loader.init(() => {
// This init callback will be invoked on the DOMContentLoaded event so you
// can safely query the DOM.

// RVS provides small wrapper to the document.querySelector() which will
// assert that the returned element is what you expect
const input = select("#search-input-in-header", HTMLInputElement);

input.addEventListener(
"focus",
() => {
// Start lazy loading when the input is focused
loader.load();
},
false,
);

return vs => {
// This function returned from the init callback will be called when the
// lazy loading completes. The ValuSearch instance is passed to it which
// can be used to bind inputs.
vs.bindInput(input);
vs.initModal();
};
});

Full example:

https://github.com/valu-digital/react-valu-search-examples/tree/master/parcel-header-input-lazy

Fullscreen with opener​

The fullscreen example with the build-in search input would look like this when lazy loaded:

valu-search.js:

import { ValuSearch } from "@valu/react-valu-search";

const vs = new ValuSearch({
customer: "<customer id>",
apiKey: "<api key>",
});

export default vs;

main.js:

import { LazyValuSearch, select } from "@valu/react-valu-search/lazy";

const loader = new LazyValuSearch({
load: () => import("./valu-search"),
});

loader.init(() => {
const button = select("#open-button", HTMLButtonElement);

button.addEventListener(
"click",
() => {
// The activate() method lazy loads the valu-search.js file and
// calls .activate() on the ValuSearch instance as well as soon as
// possible. On subsequent calls when the module is already loaded it
// just activates the VS instance.
loader.activate();

// Since the lazy loading might take a second we add a class that
// visualizes the loading state via CSS if it is not loaded yet.
if (!loader.isLoaded()) {
button.classList.add("loading");
}
},
false,
);

return vs => {
// Once ready we can remove the loading indicator
button.classList.remove("loading");
vs.initModal();
};
});

Full example

https://github.com/valu-digital/react-valu-search-examples/tree/master/parcel-fullscreen-modal-lazy

Fullscreen with input as opener​

The fullscreen example with the build-in search input would look like this when lazy loaded:

valu-search.js:

import { ValuSearch } from "@valu/react-valu-search";

const vs = new ValuSearch({
customer: "<customer id>",
apiKey: "<api key>",
});

export default vs;

main.js:

import { LazyValuSearch, select } from "@valu/react-valu-search/lazy";

const loader = new LazyValuSearch({
load: () => import("./valu-search"),
});

loader.init(() => {
const input = select("#outside-input", HTMLInputElement);

return vs => {
// Input is not visible while RVS is active so you should NOT use .bindInput()
// as it binds the input as a part of the RVS. Instead use .bindInputAsOpener()
// which activates the RVS on keydown event or if there already was text in the
// input when lazy load completes. Input contents are set as search terms and
// the input is cleared. Focus will move automatically to full screen input
vs.bindInputAsOpener(input);
vs.initModal();
};
});

Full example

https://github.com/valu-digital/react-valu-search-examples/tree/master/parcel-fullscreen-modal-lazy-with-input

Polyfills​

The LazyValuSearch helper will automatically load and apply polyfills from our CDN when needed but if you provide your own you can disable this behaviour by marking the enviroment as modern:

const loader = new LazyValuSearch({
polyfill: {
isModern: true,
},
load: () => import("./valu-search"),
});

Executing custom vs code during lazy load​

Everything you export from main.js can be accessed in loader.init() callback.

Lazy valu-search.js should have minimum amount of code to keep it light as possible. Create pure functions in main.js and call then in loader.init() callback.

import { LazyValuSearch, select } from "@valu/react-valu-search/lazy";

const loader = new LazyValuSearch({
load: () => import("./valu-search"),
});

loader.init(() => {
const input = select("#outside-input", HTMLInputElement);

return (vs, module) => {
module.yourAwesomeFunction();
vs.bindInputAsOpener(input);
vs.initModal();
};
});