Skip to content
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

Proof-of-concept for transform plugins #234

Closed
wants to merge 1 commit into from

Conversation

matthewmueller
Copy link

@matthewmueller matthewmueller commented Jul 6, 2020

Hey Evan,

I wanted to share a proof-of-concept for how esbuild could support simple 3rd-party plugins using the virtual filesystem. I don't expect this to be merged – this is throwaway code. If there's interest, I'd be more than happy to make this PR legit.

It's less ambitious than some of the ideas in #111, but still very flexible and the changes required are minimal. I also think it's quite fair to ask people to write their own main.go file to customize esbuild. This would be similar to how rollup.config.js or webpack.config.js works.

For a public FileSystem interface, it should be possible re-use the interface and implementation from godoc. That virtual filesystem is used quite a bit in the Go ecosystem.

package main

import "golang.org/x/tools/godoc/vfs/mapfs"

func main() {
  fs := mapfs.New(map[string]string{...})
}

@matthewmueller matthewmueller marked this pull request as draft July 6, 2020 21:01
@evanw
Copy link
Owner

evanw commented Jul 7, 2020

I'm glad you're excited about esbuild plugins! I am too. This is very timely because I'm planning to start experimenting with a plugin API for esbuild soon.

I also think it's quite fair to ask people to write their own main.go file to customize esbuild. This would be similar to how rollup.config.js or webpack.config.js works.

This is a reasonable first approach, but I personally think that's too much friction. I have kept the Go and JavaScript APIs similar in shape and feature set so far and I plan to continue to do this with the plugin API. It should be possible to extend esbuild easily from JavaScript as well as Go. The JavaScript bridge will be written using IPC just like the existing JavaScript API.

And having a plugin written in JavaScript will likely lead to higher performance for certain use cases. For example, it will avoid having to repeatedly pay node's startup cost for every transform like in this example.

@matthewmueller
Copy link
Author

matthewmueller commented Jul 7, 2020

Excellent! I'm thrilled to hear that this is top of mind.

This is a reasonable first approach, but I personally think that's too much friction

I absolutely agree that the IPC approach would be more accessible to more folks. I wrote something similar for doing a Go CLI where you can install third-party subcommands. If nothing else, it could be a useful point of reference: https://github.com/matthewmueller/plugin

And having a plugin written in JavaScript will likely lead to higher performance for certain use cases. For example, it will avoid having to repeatedly pay node's startup cost for every transform like in this example.

Yep. For what it's worth, this can be avoided by initializing the node service.

In (untested) code:

package transform

func Load() (*Transformer, error) {
   cmd := exec.Command("node", "service.js")
   var stdin bytes.Buffer
   cmd.Stdin = &stdin
   var stdout bytes.Buffer
   cmd.Stdout = &stdout
   err := cmd.Start()
   if err != nil {
     return nil, err
   }
   return &Transform{
      cmd: cmd,
      stdin: stdin,
      stdout: stdout,
   }, nil
}

var _ fs.FS = (*Transformer)(nil)

type Transformer struct {
   cmd *exec.Command
   stdin bytes.Buffer
   stdout bytes.Buffer
}

func (t *Transformer) ReadFile(path string) (string, bool) {
  buf, _ = ioutil.ReadFile(path)
  js, _ := svelte.Compile(buf)
  t.stdin.Write(js)
  return t.stdout.Read(), true
}

Excited to see this come together!

@matthewmueller matthewmueller deleted the poc/transform branch August 1, 2020 21:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants