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

--footer esbuild & rollup style! #14396

Merged
merged 7 commits into from
Oct 8, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions docs/bundler/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -1092,7 +1092,7 @@ $ bun build ./index.tsx --outdir ./out --loader .png:dataurl --loader .txt:file

### `banner`

A banner to be added to the final bundle, this can be a directive like "use client" for react or a comment block such as a license for the code.
A banner to be added to the final bundle, this can be a directive like "use client" for react or a comment block such as a license for the code.

{% codetabs %}

Expand All @@ -1108,11 +1108,29 @@ await Bun.build({
$ bun build ./index.tsx --outdir ./out --banner "\"use client\";"
```

### `footer`

A footer to be added to the final bundle, this can be something like a comment block for a license or just a fun easter egg.

{% codetabs %}

```ts#JavaScript
await Bun.build({
entrypoints: ['./index.tsx'],
outdir: './out',
footer: '// built with love in SF'
})
```

```bash#CLI
$ bun build ./index.tsx --outdir ./out --footer="// built with love in SF"
```

{% /codetabs %}

### `experimentalCss`

Whether to enable *experimental* support for bundling CSS files. Defaults to `false`.
Whether to enable _experimental_ support for bundling CSS files. Defaults to `false`.

This supports bundling CSS files imported from JS, as well as CSS entrypoints.

Expand Down
6 changes: 6 additions & 0 deletions docs/bundler/vs-esbuild.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,12 @@ In Bun's CLI, simple boolean flags like `--minify` do not accept an argument. Ot

---

- `--footer`
- `--footer`
- Only applies to js bundles

---

- `--certfile`
- n/a
- Not applicable
Expand Down
6 changes: 6 additions & 0 deletions packages/bun-types/bun.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1599,6 +1599,12 @@ declare module "bun" {
* Add a banner to the bundled code such as "use client";
*/
banner?: string;
/**
* Add a footer to the bundled code such as a comment block like
*
* `// made with bun!`
*/
footer?: string;

/**
* **Experimental**
Expand Down
6 changes: 6 additions & 0 deletions src/bun.js/api/JSBundler.zig
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ pub const JSBundler = struct {
format: options.Format = .esm,
bytecode: bool = false,
banner: OwnedString = OwnedString.initEmpty(bun.default_allocator),
footer: OwnedString = OwnedString.initEmpty(bun.default_allocator),
experimental_css: bool = false,

pub const List = bun.StringArrayHashMapUnmanaged(Config);
Expand Down Expand Up @@ -190,6 +191,11 @@ pub const JSBundler = struct {
try this.banner.appendSliceExact(slice.slice());
}

if (try config.getOwnOptional(globalThis, "footer", ZigString.Slice)) |slice| {
defer slice.deinit();
try this.footer.appendSliceExact(slice.slice());
}

if (config.getOwnTruthy(globalThis, "sourcemap")) |source_map_js| {
if (bun.FeatureFlags.breaking_changes_1_2 and config.isBoolean()) {
if (source_map_js == .true) {
Expand Down
14 changes: 13 additions & 1 deletion src/bundler/bundle_v2.zig
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,7 @@ pub const BundleV2 = struct {
this.linker.options.ignore_dce_annotations = bundler.options.ignore_dce_annotations;

this.linker.options.banner = bundler.options.banner;
this.linker.options.footer = bundler.options.footer;

this.linker.options.experimental_css = bundler.options.experimental_css;

Expand Down Expand Up @@ -1478,6 +1479,7 @@ pub const BundleV2 = struct {
bundler.options.ignore_dce_annotations = config.ignore_dce_annotations;
bundler.options.experimental_css = config.experimental_css;
bundler.options.banner = config.banner.toOwnedSlice();
bundler.options.footer = config.footer.toOwnedSlice();

bundler.configureLinker();
try bundler.configureDefines();
Expand Down Expand Up @@ -4602,6 +4604,7 @@ pub const LinkerContext = struct {
minify_syntax: bool = false,
minify_identifiers: bool = false,
banner: []const u8 = "",
footer: []const u8 = "",
experimental_css: bool = false,
source_maps: options.SourceMapOption = .none,
target: options.Target = .browser,
Expand Down Expand Up @@ -8977,7 +8980,16 @@ pub const LinkerContext = struct {
j.ensureNewlineAtEnd();
// TODO: maybeAppendLegalComments

// TODO: footer
if (c.options.footer.len > 0) {
if (newline_before_comment) {
j.pushStatic("\n");
line_offset.advance("\n");
}
j.pushStatic(ctx.c.options.footer);
line_offset.advance(ctx.c.options.footer);
j.pushStatic("\n");
line_offset.advance("\n");
}

chunk.intermediate_output = c.breakOutputIntoPieces(
worker.allocator,
Expand Down
6 changes: 6 additions & 0 deletions src/cli.zig
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ pub const Arguments = struct {
clap.parseParam("--outfile <STR> Write to a file") catch unreachable,
clap.parseParam("--sourcemap <STR>? Build with sourcemaps - 'linked', 'inline', 'external', or 'none'") catch unreachable,
clap.parseParam("--banner <STR> Add a banner to the bundled output such as \"use client\"; for a bundle being used with RSCs") catch unreachable,
clap.parseParam("--footer <STR> Add a footer to the bundled output such as // built with bun!") catch unreachable,
clap.parseParam("--format <STR> Specifies the module format to build to. Only \"esm\" is supported.") catch unreachable,
clap.parseParam("--root <STR> Root directory used for multiple entry points") catch unreachable,
clap.parseParam("--splitting Enable code splitting") catch unreachable,
Expand Down Expand Up @@ -783,6 +784,10 @@ pub const Arguments = struct {
ctx.bundler_options.banner = banner;
}

if (args.option("--footer")) |footer| {
ctx.bundler_options.footer = footer;
}

const experimental_css = args.flag("--experimental-css");
ctx.bundler_options.experimental_css = experimental_css;

Expand Down Expand Up @@ -1408,6 +1413,7 @@ pub const Command = struct {
output_format: options.Format = .esm,
bytecode: bool = false,
banner: []const u8 = "",
footer: []const u8 = "",
experimental_css: bool = false,
};

Expand Down
2 changes: 2 additions & 0 deletions src/cli/build_command.zig
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ pub const BuildCommand = struct {
this_bundler.options.ignore_dce_annotations = ctx.bundler_options.ignore_dce_annotations;

this_bundler.options.banner = ctx.bundler_options.banner;
this_bundler.options.footer = ctx.bundler_options.footer;

this_bundler.options.experimental_css = ctx.bundler_options.experimental_css;

this_bundler.options.output_dir = ctx.bundler_options.outdir;
Expand Down
29 changes: 29 additions & 0 deletions test/bundler/bundler_footer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { describe } from "bun:test";
import { itBundled } from "./expectBundled";

describe("bundler", () => {
itBundled("footer/CommentFooter", {
footer: "// developed with love in SF",
files: {
"/a.js": `console.log("Hello, world!")`,
},
onAfterBundle(api) {
api.expectFile("out.js").toContain("// developed with love in SF");
},
});
itBundled("footer/MultilineFooter", {
footer: `/**
* This is copyright of [...] ${new Date().getFullYear()}
* do not redistribute without consent of [...]
*/`,
files: {
"index.js": `console.log("Hello, world!")`,
},
onAfterBundle(api) {
api.expectFile("out.js").toContain(`/**
versecafe marked this conversation as resolved.
Show resolved Hide resolved
* This is copyright of [...] ${new Date().getFullYear()}
* do not redistribute without consent of [...]
*/`);
},
});
});
4 changes: 4 additions & 0 deletions test/bundler/expectBundled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ export interface BundlerTestInput {
alias?: Record<string, string>;
assetNaming?: string;
banner?: string;
footer?: string;
define?: Record<string, string | number>;

/** Use for resolve custom conditions */
Expand Down Expand Up @@ -416,6 +417,7 @@ function expectBundled(
external,
packages,
files,
footer,
format,
globalName,
inject,
Expand Down Expand Up @@ -666,6 +668,7 @@ function expectBundled(
serverComponents && "--server-components",
outbase && `--root=${outbase}`,
banner && `--banner="${banner}"`, // TODO: --banner-css=*
footer && `--footer="${footer}"`,
ignoreDCEAnnotations && `--ignore-dce-annotations`,
emitDCEAnnotations && `--emit-dce-annotations`,
// inject && inject.map(x => ["--inject", path.join(root, x)]),
Expand Down Expand Up @@ -710,6 +713,7 @@ function expectBundled(
metafile && `--metafile=${metafile}`,
sourceMap && `--sourcemap=${sourceMap}`,
banner && `--banner:js=${banner}`,
footer && `--footer:js=${footer}`,
legalComments && `--legal-comments=${legalComments}`,
ignoreDCEAnnotations && `--ignore-annotations`,
splitting && `--splitting`,
Expand Down