Go to main content Go to main navigation Go to footer
Back to overview

Let your web app breathe: improve your web performance with lazy modules.

A fast, high-performing web app is more important today than ever. Yet many applications still load all JavaScript at once, regardless of whether the user needs everything right away. This can be done much faster and more efficiently. In this article, Roy, developer at Cube and creator of the LazyModule, explains how a simple approach can achieve a lot of gains.

Roy Teusink - Javascript Developer bij Cube - Oldenzaal
Author Full Stack Developer
Reading time
4 min

That could be done more quickly.

You build a modern web app. Everything works - but the performance? Meh. The initial load time is too long, users are waiting for scripts they may never need, and you know: there must be a better way. Imagine modules that are loaded only when they are needed, right before elements come into view. No wasted requests. No off-screen logic. Only what the user sees, exactly when they want to see it.

That's exactly what the lazy module package from Cube does.

In this blog post, Roy shows how to use lazy module to make your webapp faster, lighter and smarter.

Lazy loading module door Roy Teusink - Open Source Software

What is a lazy module?

In this context, a lazy module is a JavaScript module that is loaded and executed only when needed, when the corresponding HTML element becomes visible in the viewport or when it interacts with it. Instead of loading all modules immediately upon loading the page (which takes a lot of resources), a lazy module is "delayed loaded" (lazy loaded). This means:

  • The script is only fetched when the user needs it.

  • The module is then applied to the linked DOM element.

Why is that convenient?

Lazy modules ensure that you only load the code you need at the time. This has many advantages:

  • Faster initial load time of your web app

  • 📉 Lower data consumption (especially important on mobile)

  • 🧠 Lower memory consumption and better performance

  • 📦 Better bundles by using code-splitting

In large web apps or dynamic websites, this can make the difference between a slow or lightning-fast experience.

Why this LazyModule?

Although many frameworks support lazy loading, it often involves a lot of configuration work. That is why Roy has developed his own Open Source LazyModule. Lazy loading ensures faster loading times, less data consumption and better performance - especially with larger web apps or dynamic content. With the LazyModule, you add that convenience without having to write a complex setup yourself.

The LazyModule is designed for developers working with modern build tools like Vite who want to further optimise their application. Whether you work with vanilla JavaScript, frameworks such as Vue or React, or a combination, the LazyModule is flexibly deployable.

Image without description
Image without description

What can you expect in this article?

Installation

Step-by-step instructions on how to install and configure the lazy module in your project.

Link

How to link modules to make them function properly within your application.

Lifecycles

Modules go through lifecycle phases from none to unmounted. We show how you can capitalise on this with TailwindCSS.

Best Practices

Tips for optimal use of the module, including preload and interaction observation plugins.

Edge Cases

Common problems and how to avoid them when using the lazy module.

Voordelen

Faster loading times and a better user experience by optimising the loading process.

Let's get started: Installatie en setup

Install the package via npm or yarn:

                        npm install @cube-nl/lazymodule
# of
yarn add @cube-nl/lazymodule
                    

Then add this to your tsconfig.json:

                        {
  "compilerOptions": {
    "target": "ES2020",
    "module": "ES2020",
    "types": ["vite/client"]
  }
}
                    

Your first lazy module

Start by creating the lazy loader:

                        import { createLazyLoader } from '@cube-nl/lazymodule';

createLazyLoader({
  modules: import.meta.glob('./lazymodules/**/*.ts'),
}).start();
                    

In the HTML, place an element with a data-lazy-module attribute, the value should match the filename of the lazy module:

                        <button data-lazy-module="counter">0</ button>
                    

Example module (lazymodules/counter.ts):

                        import type { LazyModule } from '@cube-nl/lazymodule';

export default class Counter implements LazyModule {
  private value: number = 0;
  
  constructor(public element: HTMLElement) {}

	private increment() {
	  this.element.textContent = `${++this.value}`;
	}

  public *onMount() {
    this.element.addEventListener('click', this.increment);
    console.log('mounted');
  }

  public onUnmount(wasMounted: boolean) {
    this.element.removeEventListener('click', this.increment);
    console.log('unmounted');
  }
}
                    

Aanvullende first party plugins

preloadModules

Loads modules "silently" in the background with low priority. As soon as a data-lazy module appears in the DOM and the module is already preloaded, it is loaded from memory.

                        import { preloadModules } from '@cube-nl/lazymodule/plugins';

createLazyLoader({...})
  .use(preloadModules)
  .start();
                    

observeInsertions

Keep an eye on the DOM for dynamically added data-lazy-module elements. Perfect for content with data-lazy-module attributes created via JavaScript.

                        import { observeInsertions } from '@cube-nl/lazymodule/plugins';

createLazyLoader({...})
  .use(observeInsertions)
  .start();
                    

observeInteractions

Suppose you have a 'Like' button in your DOM, but the click logic is not loaded until the button comes into view. With observeInteractions, the user doesn't miss that first click. The lazy module remembers the interaction and plays it nicely as soon as the module finishes

HTML:

                        <div data-lazy-module="like">
  <button data-lazy-interact="click">Like</button>
</div>
                    

JavaScript:

                        import { observeInteractions } from '@cube-nl/lazymodule/plugins';

createLazyLoader({...})
  .use(observeInteractions)
  .start();
                    

Lifecycle

Each module goes through these stages:

  • none – module is not yet loaded

  • loading – module is picked up

  • mounting – initialisation is taking place

  • mounted - module is active

  • unmounted - module has been removed or deactivated

Embarking on a lifecycle phase

The lifecycle phase of a lazy module is tracked on a data-lazy-state attribute of a lazy element. Because we store the lifecycle phase in there, we can apply styling before and during the loading of the lazy module. An example using TailwindCSS:

                        <div data-lazy-modue="posts" class="bg-red-500 group data-[lazy-state=loading]:animate-pulse">
  <div class="hidden group-data-[lazy-state=loading]:block">
    Loading
  </div>
  <div class="hidden group-data-[lazy-state=mounted]:block">
    Mounted
  </div>
</div>
                    

From theory to practice: the impact of the LazyModule.

By loading modules only upon visibility or interaction, you reduce the initial load on the browser, speed up loading time and offer users a smoother experience, without having to write extra complex logic.

At Cube, we now apply the LazyModule as standard in almost all our production projects, from large web applications to dynamic content platforms. We see time and again that it makes a clear difference: shorter load times, less data consumption, more stable performance and higher user satisfaction. Especially in projects where scalability, mobile performance or dynamic content are important, lazy loading is a practical and valuable optimisation.

👉 Want to know more or contribute? Check out the package on npm or check out the source code on GitHub.

Image without description

Ready for the next step? We are too.

Do you have questions about deploying the LazyModule in your project or do you doubt whether lazy loading is the right solution? Share your experiences or suggestions. We will be happy to help you further.