mirror of
https://github.com/oven-sh/bun
synced 2026-02-14 04:49:06 +00:00
bundler: implement globalName support for IIFE format
Fixes bundler test by implementing globalName option for IIFE format. When globalName is specified with IIFE format, the bundled output is wrapped in a variable assignment that exposes exports as a global. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -390,7 +390,62 @@ $ bun build ./index.tsx --outdir ./out --format cjs
|
||||
|
||||
#### `format: "iife"` - IIFE
|
||||
|
||||
TODO: document IIFE once we support globalNames.
|
||||
Wraps the bundle in an Immediately Invoked Function Expression (IIFE). This format is useful for creating bundles that can be directly included in HTML `<script>` tags without polluting the global namespace.
|
||||
|
||||
{% codetabs group="a" %}
|
||||
|
||||
```ts#JavaScript
|
||||
await Bun.build({
|
||||
entrypoints: ['./index.tsx'],
|
||||
outdir: './out',
|
||||
format: "iife",
|
||||
})
|
||||
```
|
||||
```bash#CLI
|
||||
$ bun build ./index.tsx --outdir ./out --format iife
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
By default, the IIFE format creates a self-contained bundle:
|
||||
|
||||
```js
|
||||
(() => {
|
||||
// Your bundled code here
|
||||
// No global variables are created
|
||||
})();
|
||||
```
|
||||
|
||||
#### `globalName`
|
||||
|
||||
To expose the bundle's exports as a global variable, use the `globalName` option:
|
||||
|
||||
{% codetabs group="a" %}
|
||||
|
||||
```ts#JavaScript
|
||||
await Bun.build({
|
||||
entrypoints: ['./index.tsx'],
|
||||
outdir: './out',
|
||||
format: "iife",
|
||||
globalName: "MyLibrary",
|
||||
})
|
||||
```
|
||||
```bash#CLI
|
||||
$ bun build ./index.tsx --outdir ./out --format iife --global-name MyLibrary
|
||||
```
|
||||
|
||||
{% /codetabs %}
|
||||
|
||||
This creates a bundle that assigns the exports to a global variable:
|
||||
|
||||
```js
|
||||
var MyLibrary = (() => {
|
||||
// Your bundled code here
|
||||
return exports; // The module's exports are returned
|
||||
})();
|
||||
```
|
||||
|
||||
The `globalName` must be a valid JavaScript identifier. This feature is only available when `format` is set to `"iife"`.
|
||||
|
||||
### `splitting`
|
||||
|
||||
|
||||
22
packages/bun-types/bun.d.ts
vendored
22
packages/bun-types/bun.d.ts
vendored
@@ -1835,6 +1835,28 @@ declare module "bun" {
|
||||
*/
|
||||
footer?: string;
|
||||
|
||||
/**
|
||||
* Global variable name for IIFE format bundles.
|
||||
*
|
||||
* When using `format: "iife"` with a `globalName`, the bundle will be
|
||||
* wrapped in an IIFE and the exported values will be assigned to a global
|
||||
* variable with the specified name.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* await Bun.build({
|
||||
* entrypoints: ['./src/library.ts'],
|
||||
* format: 'iife',
|
||||
* globalName: 'MyLibrary',
|
||||
* outfile: './dist/library.js'
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* The `globalName` must be a valid JavaScript identifier.
|
||||
* This option is only meaningful when `format` is set to `"iife"`.
|
||||
*/
|
||||
globalName?: string;
|
||||
|
||||
/**
|
||||
* Drop function calls to matching property accesses.
|
||||
*/
|
||||
|
||||
@@ -1792,7 +1792,7 @@ pub const BundleV2 = struct {
|
||||
transpiler.options.css_chunking = config.css_chunking;
|
||||
transpiler.options.banner = config.banner.slice();
|
||||
transpiler.options.footer = config.footer.slice();
|
||||
transpiler.options.global_name = config.global_name.slice();
|
||||
transpiler.options.global_name = if (config.format == .iife) config.global_name.slice() else "";
|
||||
|
||||
transpiler.configureLinker();
|
||||
try transpiler.configureDefines();
|
||||
|
||||
@@ -194,12 +194,21 @@ pub fn postProcessJSChunk(ctx: GenerateChunkCtx, worker: *ThreadPool.Worker, chu
|
||||
.iife => {
|
||||
// Bun does not do arrow function lowering. So the wrapper can be an arrow.
|
||||
if (c.options.global_name.len > 0) {
|
||||
const global_name_prefix = if (c.options.minify_whitespace)
|
||||
std.fmt.allocPrint(worker.allocator, "var {s}=(()=>{{", .{c.options.global_name}) catch bun.outOfMemory()
|
||||
else
|
||||
std.fmt.allocPrint(worker.allocator, "var {s} = (() => {{\n", .{c.options.global_name}) catch bun.outOfMemory();
|
||||
j.push(global_name_prefix, worker.allocator);
|
||||
line_offset.advance(global_name_prefix);
|
||||
if (c.options.minify_whitespace) {
|
||||
j.pushStatic("var ");
|
||||
j.pushStatic(c.options.global_name);
|
||||
j.pushStatic("=(()=>{");
|
||||
line_offset.advance("var ");
|
||||
line_offset.advance(c.options.global_name);
|
||||
line_offset.advance("=(()=>{");
|
||||
} else {
|
||||
j.pushStatic("var ");
|
||||
j.pushStatic(c.options.global_name);
|
||||
j.pushStatic(" = (() => {\n");
|
||||
line_offset.advance("var ");
|
||||
line_offset.advance(c.options.global_name);
|
||||
line_offset.advance(" = (() => {\n");
|
||||
}
|
||||
} else {
|
||||
const start = if (c.options.minify_whitespace) "(()=>{" else "(() => {\n";
|
||||
j.pushStatic(start);
|
||||
@@ -346,21 +355,14 @@ pub fn postProcessJSChunk(ctx: GenerateChunkCtx, worker: *ThreadPool.Worker, chu
|
||||
|
||||
switch (output_format) {
|
||||
.iife => {
|
||||
if (c.options.global_name.len > 0) {
|
||||
const without_newline = "})();";
|
||||
const with_newline = if (newline_before_comment)
|
||||
without_newline ++ "\n"
|
||||
else
|
||||
without_newline;
|
||||
j.pushStatic(with_newline);
|
||||
} else {
|
||||
const without_newline = "})();";
|
||||
const with_newline = if (newline_before_comment)
|
||||
without_newline ++ "\n"
|
||||
else
|
||||
without_newline;
|
||||
j.pushStatic(with_newline);
|
||||
}
|
||||
const without_newline = "})();";
|
||||
|
||||
const with_newline = if (newline_before_comment)
|
||||
without_newline ++ "\n"
|
||||
else
|
||||
without_newline;
|
||||
|
||||
j.pushStatic(with_newline);
|
||||
},
|
||||
.internal_bake_dev => {
|
||||
{
|
||||
@@ -770,12 +772,13 @@ pub fn generateEntryPointTailJS(
|
||||
.cjs => {
|
||||
// "return require_foo();"
|
||||
stmts.append(
|
||||
Stmt.alloc(
|
||||
Stmt.allocate(
|
||||
allocator,
|
||||
S.Return,
|
||||
.{
|
||||
S.Return{
|
||||
.value = Expr.init(
|
||||
E.Call,
|
||||
.{
|
||||
E.Call{
|
||||
.target = Expr.initIdentifier(ast.wrapper_ref, Logger.Loc.Empty),
|
||||
},
|
||||
Logger.Loc.Empty,
|
||||
@@ -789,12 +792,13 @@ pub fn generateEntryPointTailJS(
|
||||
// "init_foo(); return exports_entry;"
|
||||
if (ast.wrapper_ref.isValid()) {
|
||||
stmts.append(
|
||||
Stmt.alloc(
|
||||
Stmt.allocate(
|
||||
allocator,
|
||||
S.SExpr,
|
||||
.{
|
||||
S.SExpr{
|
||||
.value = Expr.init(
|
||||
E.Call,
|
||||
.{
|
||||
E.Call{
|
||||
.target = Expr.initIdentifier(ast.wrapper_ref, Logger.Loc.Empty),
|
||||
},
|
||||
Logger.Loc.Empty,
|
||||
@@ -808,9 +812,10 @@ pub fn generateEntryPointTailJS(
|
||||
// Return the exports object if it has exports
|
||||
if (ast.exports_ref.isValid()) {
|
||||
stmts.append(
|
||||
Stmt.alloc(
|
||||
Stmt.allocate(
|
||||
allocator,
|
||||
S.Return,
|
||||
.{
|
||||
S.Return{
|
||||
.value = Expr.initIdentifier(ast.exports_ref, Logger.Loc.Empty),
|
||||
},
|
||||
Logger.Loc.Empty,
|
||||
@@ -822,9 +827,10 @@ pub fn generateEntryPointTailJS(
|
||||
// For other cases, try to return the exports object if available
|
||||
if (ast.exports_ref.isValid()) {
|
||||
stmts.append(
|
||||
Stmt.alloc(
|
||||
Stmt.allocate(
|
||||
allocator,
|
||||
S.Return,
|
||||
.{
|
||||
S.Return{
|
||||
.value = Expr.initIdentifier(ast.exports_ref, Logger.Loc.Empty),
|
||||
},
|
||||
Logger.Loc.Empty,
|
||||
|
||||
@@ -165,7 +165,7 @@ pub const build_only_params = [_]ParamType{
|
||||
clap.parseParam("--minify-syntax Minify syntax and inline data") catch unreachable,
|
||||
clap.parseParam("--minify-whitespace Minify whitespace") catch unreachable,
|
||||
clap.parseParam("--minify-identifiers Minify identifiers") catch unreachable,
|
||||
clap.parseParam("--global-name <STR> Global variable name for IIFE bundles") catch unreachable,
|
||||
clap.parseParam("--global-name <STR> Global variable name for IIFE bundles (IIFE only; must be a valid JS identifier)") catch unreachable,
|
||||
clap.parseParam("--css-chunking Chunk CSS files together to reduce duplicated CSS loaded in a browser. Only has an effect when multiple entrypoints import CSS") catch unreachable,
|
||||
clap.parseParam("--dump-environment-variables") catch unreachable,
|
||||
clap.parseParam("--conditions <STR>... Pass custom conditions to resolve") catch unreachable,
|
||||
|
||||
2
test_entry.js
Normal file
2
test_entry.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export const foo = 123;
|
||||
export const bar = "hello";
|
||||
Reference in New Issue
Block a user