Esbuild: Any plan for a Go API?

Created on 26 May 2020  路  8Comments  路  Source: evanw/esbuild

I'm leading the Hugo project, and esbuild delivers something I have been wanting badly to integrate for a long, long time.

Unfortunately, for good reasons I'm sure, there does not seem to be a public Go API. The main function is easy to understand and seem to cover what we need, but all the API it calls lives in the internal package.

Any plans making (at least part of) this public? Note that I don't mind API-breakage in < 1 versions and would love to get to test this out.

https://github.com/gohugoio/hugo/issues/7321

Most helpful comment

Can you say what your requirements would be explicitly?

My main requirement that differs from the obvious is this: Hugo is backed by a Afero union filesystem. JavaScript source files (and other source files) will be mounted to virtual roots that does not match their location on the real file system (you can even mount GitHub repositories). As an example: For LibSASS we get around this by providing an "import resolver" function to LibSASS.

For this project, my initial thinking that if there was an API that allowed me to implement this interface:

type FS interface {
    ReadDirectory(path string) map[string]Entry
    ReadFile(path string) (string, bool)
}

Or something, that would work. I can probably come up with a quick prototype to see if this will even work.

As to mirroring the JavaScript stdin/stdout CLI I assume you don't mean to actually use stdin/stdout. I notice you say in the README that "Go is just an implementation detail", but you do throw away some major wins (at least from my perspective) if you, for a Go API, trade out io.Reader etc. with os/exec. If you one day for some unlikely reason decide to rewrite the implementation in Rust or C, I would have no problem taking that loss/upgrade path.

I have browsed through the Go source code, and this is some very impressing work, especially considering the short commit history.

All 8 comments

IMO, a good compromise if the project wants to keep its APIs internal is to create an app.CLI(args []string) error public function that main can call. This lets other Go projects embed esbuild without having to install a binary somewhere or committing to any public interface beyond the CLI. I use this pattern quite often, e.g. here.

app.CLI(args []string) error

Not to get ahead of myself here, but for this to be practical/usable for Hugo, we would need access to the filesystem/resolver API, i.e. something more powerful than the above.

I can see why the esbuild team might not want to commit to an external API now, but I think accepting #153 is pretty much a no-brainer, since it doesn't add any new API surface but makes the existing CLI interface easier to use.

Not to get ahead of myself here, but for this to be practical/usable for Hugo, we would need access to the filesystem/resolver API, i.e. something more powerful than the above.

Can you say what your requirements would be explicitly? That could help inform the discussion.

I could see exposing a Go-based transform API to mirror the existing JavaScript-based API. That would let you use esbuild as a minifier or as a way to convert JSX/TypeScript to JavaScript. It's essentially the same as the stable stdin/stdout command-line interface but exposed such that you don't need to touch the file system.

Can you say what your requirements would be explicitly?

My main requirement that differs from the obvious is this: Hugo is backed by a Afero union filesystem. JavaScript source files (and other source files) will be mounted to virtual roots that does not match their location on the real file system (you can even mount GitHub repositories). As an example: For LibSASS we get around this by providing an "import resolver" function to LibSASS.

For this project, my initial thinking that if there was an API that allowed me to implement this interface:

type FS interface {
    ReadDirectory(path string) map[string]Entry
    ReadFile(path string) (string, bool)
}

Or something, that would work. I can probably come up with a quick prototype to see if this will even work.

As to mirroring the JavaScript stdin/stdout CLI I assume you don't mean to actually use stdin/stdout. I notice you say in the README that "Go is just an implementation detail", but you do throw away some major wins (at least from my perspective) if you, for a Go API, trade out io.Reader etc. with os/exec. If you one day for some unlikely reason decide to rewrite the implementation in Rust or C, I would have no problem taking that loss/upgrade path.

I have browsed through the Go source code, and this is some very impressing work, especially considering the short commit history.

There is now a Go API as of version 0.5.0. It's documented here. The new Go API exposes the same interface as the existing JavaScript API, so it can run a build and transform an individual file.

I'm planning to wait on more advanced integrations such as intercepting file system access until a plugin API is exposed. You can follow #111 for updates about the plugin API as it develops. It will probably be a while before that falls into place though. I want to get code splitting and a CSS loader in place first before I implement a plugin API on top.

There is now a Go API as of version 0.5.0. It's documented here. The new Go API exposes the same interface as the existing JavaScript API, so it can run a build and transform an individual file.

I'm planning to wait on more advanced integrations such as intercepting file system access until a plugin API is exposed. You can follow #111 for updates about the plugin API as it develops. It will probably be a while before that falls into place though. I want to get code splitting and a CSS loader in place first before I implement a plugin API on top.

Umm... linked documentation is missing, but I found godoc here

Whoops, sorry about that. The community asked me to move it to godoc and I forgot to update my link above.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

frandiox picture frandiox  路  3Comments

OneOfOne picture OneOfOne  路  3Comments

fannheyward picture fannheyward  路  4Comments

a7ul picture a7ul  路  3Comments

ayox picture ayox  路  4Comments