esbuild icon indicating copy to clipboard operation
esbuild copied to clipboard

Feature: Generate AMD output

Open joaomoreno opened this issue 3 years ago • 5 comments

Hi @evanw! First off, amazing work here, you've accomplished something really impressive with esbuild. Thanks so much upfront!

You may not be aware but at https://github.com/microsoft/vscode we have adopted esbuild as our JavaScript minifier. As expected, in runs in a fraction of the time when compared to our previous minifier. We're pretty happy so far.

VS Code happens to be a product which relies on an AMD environment at runtime. I know, so 2010's. But the truth is that the investment to move off it is too big. At least larger than the effort I estimate for adding AMD output support for esbuild. Getting that to work would allow us to fully depend on esbuild for our development and production builds, greatly improving times overall, without making any runtime changes. So here are two questions for you:

  1. Would this be something you'd consider merging into esbuild?
  2. What's your complexity estimation for such a task? Having looked at your sources myself, it doesn't really feel like a big endeavor. At least compared to the one you've just been through, creating esbuild itself. 😉

joaomoreno avatar Feb 16 '21 21:02 joaomoreno

I wasn't aware that esbuild is being used as a minifier in vscode. That's very cool!

Right now I'm hard at work solidifying esbuild's core. I'm currently in the middle of a big rewrite of the linker (the part of the compiler that assembles the output format). This is necessary to add more features including top-level await and manual chunk names, to fix existing ordering issues with code splitting and CSS, and to bring code splitting to all output formats.

With a big project like esbuild, each feature usually interacts with each other feature so adding new features is sometimes quadratic complexity instead of linear complexity. Adding new output formats now before a big rewrite of the linker would make the rewrite a lot harder, so I have been saying "no" to new output formats for now (people also want UMD and SystemJS). Once esbuild is more mature it could make more sense to add more output formats.

I'm not sure what your AMD needs are and I'm very unfamiliar with AMD, but it may be possible to use the banner and footer features for this. For example, it's possible to generate a UMD build using these features even though esbuild doesn't support UMD by generating CommonJS instead and then using banner and footer to insert a UMD wrapper. So I could imagine something like this working for a simple AMD build:

require('esbuild').build({
  entryPoints: ['vscode.js'],
  outfile: 'out.js',
  bundle: true,
  format: 'iife',
  globalName: '__export__',
  banner: `define(['somelib'], function(somelib) {`,
  footer: `return __export__;\n});`,
})

You could potentially handle imports by having the bundled code access the imports as globals and then have the wrapper provide those globals as imports. It may also not work for another reason as I'm not familiar with AMD. But I thought I'd point that out in case it happens to work for you.

evanw avatar Feb 17 '21 13:02 evanw

@joaomoreno are you transforming files, or bundling them? The output generated for esm is pretty regexp-able. I used this to emulate UMD bundles in my project

jacobp100 avatar Feb 19 '21 12:02 jacobp100

I am transforming files

On Fri, Feb 19, 2021, 6:50 AM Jacob Parker [email protected] wrote:

@joaomoreno https://github.com/joaomoreno are you transforming files, or bundling them? The format generated from ES modules seems pretty regexp-able - which is what I did to emulate UMD bundles over here https://github.com/jacobp100/technicalc-core/blob/01f639cb3f49db1022f2c0751d0ebedc9d099ad9/packages/technicalc-prebuilt/build.js#L91-L101

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/evanw/esbuild/issues/819#issuecomment-782054440, or unsubscribe https://github.com/notifications/unsubscribe-auth/AQNDYU6R435M6JCEYSYKGKTS7ZM7RANCNFSM4XXGPGJQ .

Valerie1Davis1 avatar Feb 19 '21 22:02 Valerie1Davis1

would this work also to support old/legacy framework like durandaljs ? trying to make some legacy project more mantainable.. but uses requirejs and amd modules https://github.com/BlueSpire/Durandal.

jkone27 avatar Jun 29 '22 16:06 jkone27

@joaomoreno

If you're still blocked, fast ESM to AMD transformation may be a simple task on your end.

You can use es-module-lexer to reliably parse import/export statements. And then you can use magic-string to remove the import statements and wrap the module in AMD headers/footers. Neither tools generate an AST so they're blazing fast.

privatenumber avatar Jul 02 '22 05:07 privatenumber

@joaomoreno are you transforming files, or bundling them? The output generated for esm is pretty regexp-able. I used this to emulate UMD bundles in my project

generally yes, for simple cases regexp or banner + footer can work


most basic generation of amd would be to wrap code output in something like this

define(['exports', /* external imports */], function (exports, /* external import names*/) {
/* code */
})

if you bundle code without external dependencies this can be simply achieved with banner + footer, but its hard to properly regexp import/require statements without lexer (adding additional parsing step is not ideal tho).

armano2 avatar Mar 29 '23 16:03 armano2