evanw/esbuild

Repeating require calls from the same external package

lxsmnsyc opened this issue · 3 comments

Good day,

I noticed that when bundling files with an external module defined, where one or more files imports that module, the transpiled import is repeated per bundled file.

Example output of an ESM build:

// src/useConstant.ts
import {useRef} from "react";
function useConstant(supplier) {
  const ref = useRef();
  if (!ref.current) {
    ref.current = {
      value: supplier()
    };
  }
  return ref.current.value;
}

// src/useForceUpdate.ts
import {useState} from "react";
function useForceUpdate() {
  const [, setState] = useState(false);
  const update = useConstantCallback(() => {
    setState((flag) => !flag);
  });
  return update;
}

// src/useIsomorphicEffect.ts
import {useEffect, useLayoutEffect} from "react";
const useIsomorphicEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
var useIsomorphicEffect_default = useIsomorphicEffect;

// src/useRenderCount.ts
import {useRef as useRef2} from "react";
function useRenderCount() {
  const ref = useRef2(0);
  ref.current += 1;
  return ref.current;
}

export {
  useConstant,
  useConstantCallback,
  useForceUpdate,
  useIsomorphicEffect_default as useIsomorphicEffect,
  useRefSupplier,
  useRenderCount
};
//# sourceMappingURL=react-hooks.esm.js.map

even the minified bundle for CommonJS builds are affected.

Hope that this gets fixed, it would greatly reduce the bundle output specially for an entrypoint with hundreds of files included.

I'm seeing the same behavior. It would be fantastic if we could either combine imports during bundling or remove them entirely when using a "globals" plugin (see #337).

I dug into the code a little bit to see if I could put together a PR, but I'm new to Go and having trouble figuring out where exactly this is implemented. I'm suspicious that this comment is relevant, but that makes me think this is a non-trivial change: it looks like the re-imports (e.g. useRef vs useRef2 from the above) are named based on per-thread basis.

But of course as I type that I realize that wouldn't work, because the possibility of collisions would be too high - so I'm probably not in the right place. TLDR, the Go code is above my head right now. I'll keep at it, but would love pointers if anyone has time!

Yeah I feel like my head is coming apart. I'm not smart enough to tackle this, at least certainly not this week. I'll keep working at it but there's a lot under the hood.

evanw commented

Thanks for reporting this. Closing as a duplicate of #475.