Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inaccurate bundle size when using dynamic imports #351

Closed
glitch-txs opened this issue Feb 19, 2024 · 10 comments
Closed

Inaccurate bundle size when using dynamic imports #351

glitch-txs opened this issue Feb 19, 2024 · 10 comments

Comments

@glitch-txs
Copy link

I have a small project setup where I'm testing tools to measure bundle size:

I have two files (index.js & store.js), one file has a function createStore which creates a basic JavaScript store, the index file exports a returnCreateStore function that simply returns the createStore function from store.js, I created this same library twice but just added a dynamic import to one of them for the createStore.

Library A:

import { createStore } from './store.js'

export async function returnCreateStore(){
  return createStore
}

Library B

export async function returnCreateStore(){
  const { createStore } = await import('./store.js')
  return createStore
}

With the following config:

[
  {
    "path": "dist/index.js",
    "import" : "{ returnCreateStore }"
  }
]

Library A: Size: 223 B
Library B: Size: 1.13 kB

When both should have around the same size

Repository: https://github.com/glitch-txs/bundlephobia-poc

@ai
Copy link
Owner

ai commented Feb 19, 2024

Very likely that 1 KB of JS is esbuild’s code for import().

Can you try what bundle will create Vite with your library?

@glitch-txs
Copy link
Author

Can you try what bundle will create Vite with your library?

Sorry I didn't understand your question, what should I try? Do you mean bundling it with Vite first?

@ai
Copy link
Owner

ai commented Feb 19, 2024

Do you mean bundling it with Vite first?

Yes, and see the real bundle of library A and B.

@glitch-txs
Copy link
Author

yeah it creates a lot of extra code:

this is just a return function with a dynamic import inside:

const h = "modulepreload",
  m = function (o) {
    return "/" + o;
  },
  c = {},
  v = function (u, l, f) {
    let a = Promise.resolve();
    if (l && l.length > 0) {
      const r = document.getElementsByTagName("link");
      a = Promise.all(
        l.map((e) => {
          if (((e = m(e)), e in c)) return;
          c[e] = !0;
          const n = e.endsWith(".css"),
            d = n ? '[rel="stylesheet"]' : "";
          if (!!f)
            for (let s = r.length - 1; s >= 0; s--) {
              const i = r[s];
              if (i.href === e && (!n || i.rel === "stylesheet")) return;
            }
          else if (document.querySelector(`link[href="${e}"]${d}`)) return;
          const t = document.createElement("link");
          if (
            ((t.rel = n ? "stylesheet" : h),
            n || ((t.as = "script"), (t.crossOrigin = "")),
            (t.href = e),
            document.head.appendChild(t),
            n)
          )
            return new Promise((s, i) => {
              t.addEventListener("load", s),
                t.addEventListener("error", () =>
                  i(new Error(`Unable to preload CSS for ${e}`))
                );
            });
        })
      );
    }
    return a
      .then(() => u())
      .catch((r) => {
        const e = new Event("vite:preloadError", { cancelable: !0 });
        if (((e.payload = r), window.dispatchEvent(e), !e.defaultPrevented))
          throw r;
      });
  };
async function E() {
  const { createStore: o } = await v(
    () => import("./store-DcLibnQz.js"),
    __vite__mapDeps([])
  );
  return o;
}
E();
function __vite__mapDeps(indexes) {
  if (!__vite__mapDeps.viteFileDeps) {
    __vite__mapDeps.viteFileDeps = [];
  }
  return indexes.map((i) => __vite__mapDeps.viteFileDeps[i]);
}

@ai
Copy link
Owner

ai commented Feb 19, 2024

So, the Size Limit is right.

The true cost of library B will be higher in real JS bundles.

@ai ai closed this as completed Feb 19, 2024
@glitch-txs
Copy link
Author

got it, thanks!

@glitch-txs
Copy link
Author

glitch-txs commented Feb 23, 2024

Hi @ai ! I have another case where dynamic import is not working as expected, could you check on this please?

I created two packages that import an external package, this external package is a direct dependency, if I use dynamic import it won't calculate the external package size, if I use nomal import it will, even when my configuration is like this:

[
  {
    "path": "dist/*.js",
    "import": "*"
  }
]

This is the repo, is very minimal:
https://github.com/glitch-txs/size-limit-dynamic-import

Results

split file

  Size:         1.3 kB with all dependencies, minified and brotlied
  Loading time: 26 ms  on slow 3G
  Running time: 48 ms  on Snapdragon 410
  Total time:   73 ms

no-split file

  Size:         81.44 kB with all dependencies, minified and brotlied
  Loading time: 1.6 s    on slow 3G
  Running time: 976 ms   on Snapdragon 410
  Total time:   2.6 s

@glitch-txs
Copy link
Author

ah small lib seems to do the work, since the big one measures the execution time and the function is not being executed, this is why it's omitted I assume

@glitch-txs
Copy link
Author

does the small package apply minification?

@ai
Copy link
Owner

ai commented Feb 23, 2024

if I use dynamic import it won't calculate the external package size

Unfortunately, it is how import() works. It is dynamic, so the content of import() is not part of a current bundle.

import() is used for code splitting and it is expected behavior to not see loaded part in a current bundle size.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants