esbuild / community-plugins

Community plugins for esbuild

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Seeking feedback on a nested build plugin

jed opened this issue · comments

Hey all,

I'm working on a web server (server.mjs) that serves a service worker (sw.js) that serves a JavaScript app (index.js), and would like to build the entire app into a single deployable file. so in my case server.mjs imports sw.js, which in turn imports index.js, and the convention I'm using is that .mjs files are bundled as usual, and .js files are bundled as IIFEs and returned as {source, map} objects. so, for example, server.mjs contains import {source, map} from './sw.js where source and map are both strings.

I've built the following plugin to try to accomplish this. but would like some feedback about a more elegant esbuild-ish way. specifically:

  1. is there a better way to prevent infinite recursion than the plugin storing a reference to remove itself from the parent build?
  2. is there any way to have the returned contents be binary instead of strings? (can't use the binary loader because i need to return an object with two properties).
  3. is there a way to get a reference to the original build function so that the plugin could be self-contained?
  4. is this a sound approach, or a terrible idea? ie, am i better off running these builds consecutively?
let myplugin = {
  name: 'myplugin',
  setup(b) {
    b.onLoad({filter: /\.js$/}, async args => {
      let {outputFiles} = await build({...b.initialOptions,
        entryPoints: [args.path],
        format: 'iife',
        outdir: '.',
        write: false,
        plugins: b.initialOptions.plugins.filter(p => p !== myplugin)
      })

      let values = Object.values(outputFiles)
      let [map, source] = values.map(value => value.text)
      let contents = JSON.stringify({source, map})
      return {contents, loader: 'json'}
    })
  }
}