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

Split independent chunks by entrypoint name in bundle (preserve module hierarchy) #492

Open
manzt opened this issue Oct 29, 2020 · 5 comments

Comments

@manzt
Copy link

manzt commented Oct 29, 2020

Loving esbuild! Thanks for all the hard work pushing this forward.

I have a project with several tree-shakeable submodules and a top-level index.ts that simply export these default modules by name. Bundling with multiple entrypoints (and --splitting), I would expect the module hierarchy to be preserved using the named entrypoints, rather than producing unique chunks that are imported independently by each entrypoint. As an example,

// index.ts
export { default as add } from './add';
export { default as subtract } from './subtract';

// add.ts 
import { log } from './shared';
export default (a: number, b: number): number => {
  log();
  return a + b;
}

// subtract.ts
import { log } from './shared';
export default (a: number, b: number): number => {
  log();
  return a - b;
}

// shared.ts
export const log = () => console.log('I'm shared code!');
esbuild --bundle --format=esm --splitting --outdir=dist index.ts add.ts subtract.ts

dist
├── add.js
├── chunk.LP5ZINJT.js
├── chunk.MWAHXVAE.js
├── chunk.NDHDC5HE.js
├── index.js
└── subtract.js

Where each entrypoint imports a unique combination of chunks, and index.js does not import add.js or subtract.js. I would instead expect something like Rollup produces (or what esbuild produces when entrypoints aren't within a hierarchy):

dist
├── add.js
├── chunk.LP5ZINJE.js
├── index.js
└── subtract.js

which reduces the number of chunks and preserves the structure of imports. Instead index.js would look something like:

import { add_default } from './add.js'; // unique chunk for add.js is bundled into this entrypoint
import { subtract_default } from './subtract.js'; // unique chunk for subtract.js is bundled into this entrypoint
import './chunk.LP5ZINJE.js';
export { 
  add_default as add,
  subtract_default as subtract
}

I don't think this is related to #399, and couldn't find another related issue. Apologies if I've missed something!

@manzt
Copy link
Author

manzt commented Oct 29, 2020

@lgarron
Copy link
Contributor

lgarron commented Nov 8, 2020

I'm exploring esbuild for a moderately large project, and I would also really love to see this!

I have 8 entry points corresponding to 8 source folders (it's a monorepo), but the output has those 8 entry points + an additional 15 chunks. 😳

While more code splitting might result in less total code being loaded when someone imports a given method, this would also avoid more round-trips if used directly in production. In our case, we've already tried to split up the project along what we think is a reasonable breakdown.

@manzt
Copy link
Author

manzt commented Mar 19, 2021

FWIW, rollup used to generate the output that is desired here with experimentalOptimizedChunks, but 2.0 removed this feature because it was too complicated to maintain. The manualChunks option in rollup works, but I'm not sure if there is something equivalent in esbuild.

@evanw
Copy link
Owner

evanw commented Mar 19, 2021

I can't promise that entry points will ever be able to import each other like that since entry points are special and may sometimes need special handling. For example, the upcoming top-level await feature will require each entry point to evaluate the top-level await state machine, and importing one entry point into another would mess this up.

Doing manual chunk assignment in the general case while maintaining the correct import order (especially with top-level await) requires the ability to lazily defer code execution ESM files. This is pretty complex but I'm already partway through implementing this and I hope to be able to get it in sometime in the next month or two. I believe manual chunk assignment is currently being tracked by #207 and #268.

@manzt
Copy link
Author

manzt commented Mar 19, 2021

Admittedly I was fairly naive wrt the complexity of the request in this issue. (I'd originally opened it because I'd seen the output I'd expected in rollup pre-2.0, which has now been dropped and the ESM output is similar to esbuild --splitting.) I'll be tracking the issue for manual chunk assignment, thanks for the pointer (and for all your work on this project)!

lgarron added a commit to cubing/cubing.js that referenced this issue Apr 12, 2021
This is a hacky implementation of:

- evanw/esbuild#207
- evanw/esbuild#492

If either of those are implemented, most of this should be obsolete.

For now, we will use this build in CI to enforce an impohgra graph among
the `cubing/*` modules.
lgarron added a commit to cubing/cubing.js that referenced this issue Apr 12, 2021
This is a hacky implementation of:

- evanw/esbuild#207
- evanw/esbuild#492

If either of those are implemented, most of this should be obsolete.

For now, we will use this build in CI to enforce an import graph among
the `cubing/*` modules.
lgarron added a commit to cubing/cubing.js that referenced this issue May 6, 2021
We're waiting on evanw/esbuild#492 to split the build properly. The code I wrote to try to get that working ended up being more practical for enforcing import graph restrictions.
lgarron added a commit to cubing/cubing.js that referenced this issue May 6, 2021
We're waiting on evanw/esbuild#492 to split the build properly. The code I wrote to try to get that working ended up being more practical for enforcing import graph restrictions.
lgarron added a commit to cubing/cubing.js that referenced this issue May 6, 2021
We're waiting on evanw/esbuild#492 to split the build properly. The code I wrote to try to get that working ended up being more practical for enforcing import graph restrictions.
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

3 participants