esbuild icon indicating copy to clipboard operation
esbuild copied to clipboard

[Feature request] Support stable chunk names

Open neilj opened this issue 1 year ago • 2 comments

When building a project with code splitting, you currently have to use [hash] inside the chunkNames build option, as [name] always resolves to "chunk", so they will conflict if there's more than one. Ideally, [name] would instead use the name of the first file from which contents of the chunk were taken.

Rationale

I am looking to replace rollup with esbuild to build a large web app with a lot of code splitting (we end up with over 200 chunks). When we rollout a new version of our app, it builds all the output files, then creates a single hash of all the content and uses this for the directory name of the output, so you end up with something like this:

/dist/{build hash}/file1.js
/dist/{build hash}/file2.js
etc.

All imports in the files are relative and do not contain the directory structure, e.g. in file2.js you might have import { foo } from "./file1.js".

A service worker caches all the files in the build. When there is a new version, a new service worker is installed. Embedded in the service worker is a list of all the file names and a hash of the contents of each file. It checks the cache to see if the hash has changed, and only downloads the files that have done so — otherwise it just replaces the build hash with the new one in the cache, and doesn't have to download the file again. This makes it very efficient for most updates.

If instead you put a hash in the filename, this hash also ends up inside the contents of any other file that imports it, which has a cascading effect. So changing one small thing in a single file will now mean every file's contents changes so we have to download all of them to do an update.

What I would love is some way to get a largely stable name for each chunk — I don't really care what it is, but rollup seems to automatically use the name of the file the first data in the chunk comes from, with a sequential number appended if there is a clash — so we can use esbuild and continue to do efficient software updates. Thanks for your consideration!

neilj avatar Jul 11 '24 04:07 neilj

There's a workaround for most feature requests to manual chunks, that you do not enable code splitting, but bundle each entry-points individually:

// src/file1.ts
export let a = 1

// src/file2.ts
import { a } from './file1.js'  // <-- Must use '.js' extension
console.log(a)
build({
  entryPoints: ['src/file1.ts', 'src/file2.ts'],
  bundle: true,
  format: 'esm',
  external: ['./file1.js'], // <-- make the 'file2' bundle to not include 'file1'
  outdir: 'dist',
  // code splitting is not enabled
})

hyrious avatar Jul 11 '24 07:07 hyrious

Thanks for the suggestion, but that does not scale to what we are doing, which includes heavy use of dynamic import as well as multiple entry points.

neilj avatar Jul 12 '24 03:07 neilj

@hyrious Thanks for the suggestion, as i start from a clean structure this workaround is great.

krei-se avatar Oct 19 '24 21:10 krei-se