-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Feature request: Service instances #814
Comments
Interesting. I'm actually planning on removing the service API since it's no longer necessary now that there is only ever one underlying child process. My plan was to just have the
Can you say more about the problem you're trying to solve? And maybe a code example of such an API? I don't think I understand your proposal. As far as I can tell, the current API already seems to fit what you're proposing (with the one difference that creating an instance also does an initial build): // Create an instance
const instance = await esbuild.build({ ...options, incremental: true })
// Trigger a build whenever you want
const result = await instance.rebuild() How is doing the initial build problematic? |
Just wanted to add that I appreciate that you’re going to deprecate the service API. I’ve gotten confused previously between all the different ways to invoke esbuild. Having only transform and build looks ideal. |
Good to know. The context is that it was added quickly in response to a user request and at the time I was unaware of |
@evanw let me try and explain a bit better now that I'm at a real keyboard. In a project I'm working on, we need to orchestrate several interrelated builds, each performed by In this project, there are currently 4 interrelated builds whose timing and re-execution must be coordinated. If I wanted to benefit from
From this perspective, I figured that Now, as I was thinking about this, I was thinking about #641 and how often I've wanted to be able to invoke Here's an idea of how I think it could look: interface ResolveOptions {
importer?: string;
resolveExtensions?: string[];
// Anything else that might be fun!
}
interface ResolveResult {
// Not sure how you'd want to handle `browser` fields that mark imports as `false`
found: boolean;
path?: string;
}
interface ESBuildServiceInstance {
// Main API
build(): Promise<BuildResult>;
resolve(spec: string, options: ResolveOptions): Promise<ResolveResult>;
// Event handlers
onDidCancelBuild(handler: () => void): { dispose(); };
onWillRebuild(handler: (e: InvalidationEvent) => void): { dispose(); };
onDidCompleteBuild(handler: (e: BuildResultEvent) => void): { dispose(); };
onDidFailBuild(handler: (e: BuildFailedEvent) => void): { dispose(); };
} |
One temporary way I am using, before better alternatives are available, is to use esbuild.build() and a plugin to extract the resolved path. const esbuild = require('esbuild')
/**
* Resolves a module using esbuild module resolution
*
* @param {string} id Module to resolve
* @param {string} [resolveDir] The directory to resolve from
* @returns {string} The resolved module
*/
async function esbuildResolve(id, resolveDir = process.cwd()) {
let _resolve
const resolvedPromise = new Promise((resolve) => (_resolve = resolve))
return Promise.race([
resolvedPromise,
esbuild
.build({
sourcemap: false,
write: false,
bundle: true,
format: 'esm',
logLevel: 'silent',
platform: 'node',
stdin: {
contents: `import ${JSON.stringify(id)}`,
loader: 'js',
resolveDir,
sourcefile: __filename
},
plugins: [
{
name: 'esbuildResolve',
setup(build) {
build.onLoad({ filter: /.*/ }, ({ path }) => {
id = path
_resolve(id)
return { contents: '' }
})
}
}
]
})
.then(() => id)
])
} |
@SalvatorePreviti sorry I didn't get back to you sooner. That's a really clever hack. I love it 😁 |
I'm closing this because I don't plan on building the API this way. Another thing to mention is that |
Looks like the final ask from this issue landed in #2816. ❤️ |
So if I'm reading this right, the resolve workaround can be rewritten using @ggoodman What specifically were you referring to as the "final ask"? |
I'm afraid that it's been so long that I'm not entirely sure 😅. |
Not a problem, thanks for looking! 😄 |
With the introduction of the more stateful incremental and watch modes, I wonder if we could explore a different spin on the JS API?
The vague idea I have in mind is that a service instance can be created independently of starting a build. Since these service instances would be fully configured on creation, they could provide a reasonable place for a resolve method. This would also mean that a user of the API wouldn't have to distinguish between build and rebuild (and account for the window between initial build start and completion).
Currently, consumers need to differentiate between pre-initial and post-initial build in order to correctly trigger a build at an arbitrary time. This state management can get tricky and IMHO could live closer to the authority on that state.
The text was updated successfully, but these errors were encountered: