evanw / evanw/esbuild

Feature request: running default loaders from onLoad hook

Open
#3,244 2 comments 2 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
40.1k
Forks
1.3k
PR merge metrics
No merged PRs in 30d

Description

Hi, First of all I want to thank you for such a fast and customizable library. It allows me to do a lot of things.

## Problem
At the moment I am working on generating static websites, the source code of which is written in typescript and react.
As an input point I need to set some `.tsx` file, which should turn into an `.html` file on output. I can do this by redirecting the path in the `onResolve` hook. However, I need to import the styles file and the original `.ts` file. It seems that I can't just read the `.ts` file with `fs`, because it has to be processed with the standard ts loader. But if I return that ts file in `onLoad`, that's what goes into the final output.

At the moment I have to subscribe to the `onEnd` hook and do my manipulations in it, which gives me 2 files: `.ts` and `.html`, but I would like to have only one.

## Suggestion
What I think can be done: by analogy with `build.resolve` make `build.load`, which will call the hook `onResolve`, then `onLoad` and then return the final result. So I'll be able to do something like this:
```javascript
build.onResolve({ filter: /\.tsx$/ }, (args) => {
if (args.kind === "entry-point") {
return {
path: htmlPath(args),
namespace: "@namespace-html",
pluginData: {
resolveDir: args.resolveDir,
originalFile: args.path,
},
};
}
});

build.onLoad(
{ filter: /.+/, namespace: "@namespace-html" },
async (args) => {
const originalEntrypointAsString = await build.load(
path.join(args.pluginData.resolveDir, args.pluginData.originalFile)
);

const moduleResult = await import(
toDataUrl(originalReactComponentString)
);

const reactElement = moduleResult.reactElement;
const cssPath = moduleResult.cssPath; // already moved to assets

return {
contents: ReactDOM.renderToStaticMarkup(reactElement).replace("{CSS}", cssPath),
loader: "file"
};
}
);
```

I'm also considering calling `build.esbuild.transorm()`, but in that case I get problems with assets.
Calling `build.esbuild.build()` would also cause issues with assemblies and break the links between builds, since it would actually be calling N+1 isolated builds.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with esbuild's plugin onResolve and onLoad hooks and compare the requested behavior with the existing build.resolve analogy. Determine how a build.load-style API could invoke the default loaders while preserving assets and links between builds; done means the original entry point produces only the generated HTML without a separate TypeScript output.

Written by the indexing model from the issue text.

Assessment

Tech stack
react, typescript
Domain
build-system, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.