evanw/esbuild

Question: `transform` stage in plugins.

hyrious opened this issue · 3 comments

This question is about plugin composition, I used to be curious why rollup has 3 essential steps: resolveId, load, transform, now I have an answer: Plugins can be composited by doing different step.

Say we have a svelte plugin and a virtual icons plugin, which creates virtual module in your code and you just import it and use:

<script>
import PlusIcon from "virtual-icon:mdi-plus.svelte"
</script>
<PlusIcon />

If it is in rollup, the two plugins can be composited by:

icons plugin: resolve & load(virtual-name) => svelte code
svelte plugin: transform(svelte code) => js & css

Only the svelte plugin has to call svelte-compiler, so we can put compiler options (like whether to generate SSR code) in one place.

However, in esbuild plugins, we must do all works in onLoad, the icons plugin now has to call svelte-compiler, and we must pass compiler options to all of them.

There are other ways to deal with the same problem, for example:

  • let the svelte plugin export a global state called virtual files, then let the icons plugin put these virtual files into that state. Now the icons plugin has a dependency of svelte plugin.
  • let plugins can define custom loaders, like loader: 'svelte', so that its onLoad can receive contents from other plugins.

I'm not sure which is the correct way to handle this usage.

evanw commented

Yes, I should do this. The general workaround right now is to have one plugin wrap the other and emulate esbuild's API but that sucks obviously.

In addition to the plugin enhancement, I found another requirement that help to get rid of "bundle twice" -- by enforce the order.

Not too many, only an enforce: post should be enough. For example the unocss plugin generates a virtual css file in your final bundle, but it needs to wait for all sources to be scanned (in transform hook) to really load the generated css code.

Sorry for the bump, but is there a package that handles the manual daisy-chaining of plugins for me?

edit: using esbuild-rna for now...