Seeking feedback on a nested build plugin
jed opened this issue · comments
Jed Schmidt commented
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:
- is there a better way to prevent infinite recursion than the plugin storing a reference to remove itself from the parent build?
- 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). - is there a way to get a reference to the original
build
function so that the plugin could be self-contained? - 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'}
})
}
}