3rd party library lazy load and re-use in bundle

Question for fellow frappe developers.

Let’s say we have 2 custom pages, each with their own bundle.js that is lazy loaded using frappe.require().

Both page bundles use a 3rd party library that is huge, +2mb.
This library is only used by those custom pages, so we don’t want to load it initially with the app.

public/js/page1.bundle.js

import “./lib/hugelib.js”

… page1 specific code …

public/js/page2.bundle.js

import “./lib/hugelib.js”

… page2 specific code …

Now when I issue a bench build, I can see with the size of the resulting bundles that the huge library was included in both bundles. This is not good.

Is there any way to make esbuild more clever about re-using the same ES modules ?
I dont’ know… maybe it could create some shared bundles when it detect the same ES modules is imported in different bundles ?

Or do you have different ideas how to structure this ?

Is the only option to bundle both pages in the same bundle ?

Hi,
if you want to avoid the duplication of the huge library, you can create a separate bundle for it and load it only when it is needed by either of the custom pages.
Create a separate bundle for the huge library:

public/js/hugelib.bundle.js

import hugelib from "./lib/hugelib.js";
export default hugelib;

Update your custom pages to use the hugelib bundle instead of importing the library directly:
public/js/page1.bundle.js


import hugelib from "../hugelib.bundle.js";

… page1 specific code that uses hugelib …

public/js/page2.bundle.js

import hugelib from "../hugelib.bundle.js";

… page2 specific code that uses hugelib …

Use code splitting to load the hugelib bundle only when it is needed. You can do this by adding a dynamic import statement to your custom page code that loads the hugelib bundle on demand:

public/js/page1.bundle.js

const loadHugelib = async () => {
    const hugelib = await import("../hugelib.bundle.js");
    // use hugelib here
};

… page1 specific code that uses loadHugelib() to load hugelib …

public/js/page2.bundle.js

const loadHugelib = async () => {
    const hugelib = await import("../hugelib.bundle.js");
    // use hugelib here
};

… page2 specific code that uses loadHugelib() to load hugelib …

Hope this will help you out.

Thank you.

Oh interesting! I will investigate the async import. Thanks for that @VINOTH !

In the meantime, I have created this request in Frappe github, where I explored esbuild external files.

Sadly, dynamic import is not working as esbuild still bundle the hugelib with each page’s bundle.