evanw / evanw/esbuild

[Feature] Support dynamic imports via plugins

Open
#700 27 comments 72 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
40.1k
Forks
1.3k
PR merge metrics
No merged PRs in 30d

Description

I know there have been multiple threads on the subject (#661, #453, #322, #56), but since plugins are now a thing I figured it could be worth opening one more discussion. Perhaps there could be a solution that doesn't require statically pregenerating files? At least I haven't seen my suggestion elsewhere 😄

ESBuild currently warns when it detects dynamic imports, and leaves them in-place. It's a good start, but it's not enough: whatever is tasked from consuming them will still lose critical information, in particular the location the dynamic import is relative to (for instance, when doing an `import('./widgets/' + name)` into an application compiled via `--bundle`, I really need to know where was the file that made this import).

My suggestion to support dynamic imports with only a little extra API surface would be to instead yield the generation of an intermediary dynamic import module to a special type of loader. For example, the following loader would allow dynamic imports where each module would end up in their own chunk:

```ts
// `dynamic` would be a builtin namespace used only for dynamic imports
build.onLoad({ namespace: `dynamic` }, async args => {
// Similar to how template strings work; args.path
// would be a special path generated by esbuild
const [importer, segments, ...expressions] = JSON.parse(args.path);

// Would find all the files that match the path
const files = glob(segments.join(`**`));

// Then generates the intermediary file
return {
// Note that this assumes that esbuild would then transform something
// like `import('foo')` into `import('')('foo')`
contents: `
export default async function (p) {
switch (p) {
${files.map(file => `
case "${file}": return import("${file}");
`).join(``)}
}
}
`,
};
});
```

On the other hand, if I wanted to make a dynamic import where all modules are in the same chunk, then I'd just need my loader to generate regular `import from` statements, without the consumer code having to know about this. I feel like this might match the kind of flexibility you had in mind given how loaders currently work.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.