[turbopack] Optimize ESM exports (#82214)
## Optimize ESM Exports
### What
For an esm module like
```js
export const foo = 2;
```
turbopack will generate a factory function like
```js
__turbopack_context__ => {
__turbopack_context__.s({foo: ()=>foo});
const foo = 2;
}
```
* we expose the exports early to enable circular imports between modules
* we expose as 'getter functions' to enable live bindings
These behaviors are necessary to uphold the ESM specification, however, we can optimize it by avoiding objects.
```js
__turbopack_context__ => {
__turbopack_context__.s(['foo', ()=>foo]);
const foo = 2;
}
```
Since the runtime simply walks the object literal in order to call `defineProperty` a number of times switching to an array representation will speed up both construction and iteration.
In a later step i will pursue an approach to avoid generating the getter functions.
### Performance analysis courtesy of v0
I ran the `module-cost` benchmark 30 times across this branch and canary. Each measurement was in a fresh incognito window.
| Scenario | Metric | HEAD (ms) | HEAD σ | HEAD CV | CHANGE (ms) | CHANGE σ | CHANGE CV | Delta (ms) | % Change |
|----------|--------|-----------|---------|---------|-------------|----------|-----------|------------|----------|
| **Pages API ESM** | Load Duration | 39.84 | 2.8 | 7.0% | 36.61 | 2.7 | 7.4% | -3.23 | -8.1% ✅ |
| | Execution Duration | 60.89 | 3.6 | 5.9% | 58.14 | 2.8 | 4.8% | -2.75 | -4.5% ✅ |
| **Client ESM** | Load Duration | 46.09 | 2.4 | 5.2% | 46.31 | 3.2 | 6.9% | +0.22 | +0.5% ❌ |
| | Execution Duration | 47.77 | 0.8 | 1.7% | 46.07 | 1.0 | 2.2% | -1.70 | -3.6% ✅ |
### Key Findings
**Strong improvements in Pages API ESM performance:**
- Load time reduced by 8.1% with consistent variance
- Execution time improved by 4.5% with reduced variance
**Mixed results for Client ESM:**
- Load times remain essentially unchanged (+0.5%)
- Execution times show solid improvement (-3.6%)
- Measurements remain highly consistent across both versions