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

node's module.register + bundling #4016

Open
JakobJingleheimer opened this issue Dec 23, 2024 · 2 comments
Open

node's module.register + bundling #4016

JakobJingleheimer opened this issue Dec 23, 2024 · 2 comments

Comments

@JakobJingleheimer
Copy link

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
Copy link

hyrious commented Dec 24, 2024

  1. esbuild only bundles analyzable imports so if you must bundle something in you have to import that directly:
import loaderJS from '@nodejs-loaders/alias'
  1. 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
Copy link
Author

Excellent, thank you! Just what I was looking for 🙂

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

No branches or pull requests

2 participants