Skip to content

ts_binary

Produces a runnable target from a ts_compile entry point, or from a plain JavaScript file. Without a bundler it runs that entry .js on the JS runtime; with one it bundles first and runs the bundle.

ts_binary and ts_bundle are separate rules with overlapping attributes, not aliases. ts_binary is the rule for bazel run. ts_bundle produces a bundle as a build artifact, requires a bundler, and adds the app-mode, HTML, vite_config and staging_srcs surface that framework builds need.

Usage

load("@rules_typescript//ts:defs.bzl", "ts_binary")

ts_binary(
    name = "app",
    entry_point = "//src/app",
    format = "esm",
    sourcemap = True,
)

Attributes

Attribute Type Default Description
entry_point label required ts_compile target providing JsInfo, or a single .js/.mjs/.cjs source file
entry_file string "" Which source's .js is the entry when the target emits several, e.g. "main.ts"; index.js by convention when unset
data label_list [] Extra runfiles: sibling modules a source entry_point imports, fixtures, anything read at runtime
bundler label None Target providing BundlerInfo. When set, the bundle is what runs
bundle_name string rule name Output file name (without .js)
format string "esm" Output format: esm, cjs, iife
sourcemap bool True Emit source map
external string_list [] Module specifiers to leave external
define string_dict {} Global constant replacements
node_modules label None node_modules target for packages the program needs at runtime

minify and split_chunks are ts_bundle attributes; ts_binary does not accept them.

A JavaScript File as the Entry Point

entry_point also takes a .js, .mjs or .cjs source directly, for a program that is already plain JavaScript — most often a ts_codegen generator:

ts_binary(
    name = "gen_schema",
    entry_point = "generate-schema.mjs",
    data = ["schema-helpers.mjs"],
    node_modules = "//:node_modules",
)

The modules the entry imports go in data. Node resolves a relative import from the entry's real path, which in a local runfiles tree is the workspace source — so an undeclared sibling can still load there and then be missing under a manifest-only or remote layout. Declare every one.

A .ts entry point is refused, with a message pointing at ts_compile: this rule does not compile TypeScript, and standing up an implicit compile here would be a second one with no deps, no tsconfig and no choice of declaration emitter.

Without a Bundler

Without a bundler, ts_binary runs the entry point's own .js file on the JS runtime, with the transitive .js outputs in its runfiles. The imports resolve as written; nothing is concatenated.

With Vite

See Bundling with Vite for a complete example with vite_bundler.

Custom Bundler

Any rule returning BundlerInfo can plug in. See Bundling — Custom Bundler.