evanw / esbuild

An extremely fast bundler for the web
https://esbuild.github.io/
MIT License
37.95k stars 1.14k forks source link

change the nature of iife to be async to allow for top level await #2112

Open jimmywarting opened 2 years ago

jimmywarting commented 2 years ago

I'm currently building in es syntax, but i'm bundling for older browser that don't have type=module support

also i'm using top level await...

so i was wondering if you could somehow generate a iife that is more close to how es modules work. it's about time to change UMD, AMD and iife to become a async module loader instead.

So i would like to propose that they become something like this:

(async () => {
  await fetch(req)
})();
eligrey commented 2 years ago

This would break scripts relying on sync init. Instead, target should probably be split into multiple discrete semantics:

At Transcend, we already have to create a pseudo-IIFE using the header and footer options due to these limitations just to enable strict mode without leaking globals:

format: 'cjs',
banner: { js: '(()=>{"use strict";' },
footer: { js: '})()' },
jimmywarting commented 2 years ago

AMD was hot for a while, by allowing for asynchronous module definition using simple things such as script tags... but it's pretty oldschool now...

i think that if you write something like the following:

import foo from './foo.js'
import bar from './bar.js'

what ☝️ that really should translate into would be something like:

(async () => {
  const foo = await __loader('./foo.js')
  const bar = await __loader('./bar.js')
})()

or at the very best:

(async () => {
  const [foo, bar] = await Promise.all([
    __loader('./foo.js'),
    __loader('./bar.js')
  ]
})()

I could pretty much need this right now... how do i write a custom bundler?