node's `module.register` + bundling
Opened this issue · 2 comments
JakobJingleheimer commented
esbuild understandably does not realise the target of module.register
is a dependency, which needs to be bundled and then referenced (possibly inlined). Is there a way to explicitly tell esbuild to do this?
For instance
module.register('@nodejs-loaders/alias');
would be updated to something like
module.register(`data:text/javascript,${aZ2.toString()}`);
hyrious commented
- esbuild only bundles analyzable imports so if you must bundle something in you have to import that directly:
import loaderJS from '@nodejs-loaders/alias'
- You can use plugins to tell esbuild to import the bundled javascript of a module, rough implementation:
// source.js
import loaderJS from '@nodejs-loaders/alias' with { loader: 'bundle-inline' }
import module from 'node:module'
module.register(loaderJS)
// build.js
import {build} from 'esbuild'
build({
entryPoints: ['source.js'],
platform: 'node',
bundle: true,
format: 'esm',
outdir: 'dist',
plugins: [{
name: 'bundle-inline',
setup({ onResolve, onLoad }) {
onResolve({ filter: /(?:)/ }, args => {
if (args.with.loader == 'bundle-inline') {
// Use '.js' extension so that the 'dataurl' loader will prepend correct mime type.
let path = args.path + '.js'
// TODO: pluginData.path = resolve(args.path, args.args.resolveDir)
return { namespace: 'bundle-inline', path: path, pluginData: args }
}
})
onLoad({ namespace: 'bundle-inline', filter: /(?:)/ }, async args => {
let {outputFiles: [{contents}]} = await build({
entryPoints: [args.pluginData.path],
platform: 'node',
bundle: true,
format: 'esm',
minify: true,
write: false,
})
return { contents, loader: 'dataurl' }
})
}
}]
}).catch(() => process.exit())
Note that I'm using import attributes for plugins to pick up as the hint, you can use other ways like query strings in import paths.
JakobJingleheimer commented
Excellent, thank you! Just what I was looking for 🙂