Option structs
#Configuration is input only. These structs have defaults for every member, so a caller names just the fields it cares about.
In this page:
BuildOptionsTransformOptionsServeOptionsWatchOptionsFormatMessagesOptionsAnalyzeMetafileOptionsOnResolveOptionsOnLoadOptionsResolveOptionsMangleCacheResultErrorWithNoteParseOptionsExtras
BuildOptions
#Everything a build can be told. The members are grouped by the phase they affect, and the blank lines between groups mark those boundaries.
struct BuildOptions {
// -- Diagnostics -------------------------------------------------------
StderrColor color{StderrColor::kColorIfTerminal};
LogLevel log_level{LogLevel::kInfo};
int log_limit{}; // cap on reported messages; 0 means no cap
std::unordered_map<std::string, LogLevel> log_override; // per-subsystem levels
AbsPathsFlags abs_paths{AbsPathsFlags::kNone};
// -- Source maps -------------------------------------------------------
SourceMap sourcemap{SourceMap::kNone};
std::string source_root; // URL prefix prepended to every source path
SourcesContent sources_content{SourcesContent::kInclude};
// -- Language level ----------------------------------------------------
// "target" names a single edition; "engines" names the engines you support
// and lets the engine compute the level itself. "supported" is the escape
// hatch: it turns one specific feature on or off regardless of both.
Target target{Target::kDefault};
std::vector<Engine> engines;
std::unordered_map<std::string, bool> supported;
// -- Minification ------------------------------------------------------
// The three minify_* switches are independent, so "minify_whitespace" alone
// is a safe way to shrink a file for debugging while keeping names intact.
// All three default to off and are asked for by name: minification is a
// choice about the bytes a build leaves behind, and a person who has not
// made it should get output they can still read. "--minify" on a command
// line is the shorthand for all three, and each of them keeps working on its
// own, so a caller that wants two passes says two.
// The flag is not shared with Format, because the wrapper's own quoting and
// interop constraints are not negotiable.
// "mangle_props" is a regular expression matching property names to
// shorten; "reserve_props" names the ones to protect. "mangle_cache" lets a
// long-lived caller carry the property-name decisions of a previous build
// forward, so a hot-reload session keeps stable names between runs.
std::string mangle_props;
std::string reserve_props;
MangleQuoted mangle_quoted{MangleQuoted::kFalse};
std::unordered_map<std::string, bool> mangle_cache;
DropFlags drop{DropFlags::kNone};
// Names of statement labels whose labelled statement should be deleted
// outright - the classic way of fencing off development-only code:
// drop_labels = {"DEBUG"}; while (DEBUG) { ... } // the loop is gone
std::vector<std::string> drop_labels;
bool minify_whitespace{};
bool minify_identifiers{};
bool minify_syntax{};
int line_limit{}; // error out if any single line grows past this
Charset charset{Charset::kDefault};
TreeShaking tree_shaking{TreeShaking::kDefault};
bool ignore_annotations{}; // treat /* @__PURE__ */ as an ordinary comment
LegalComments legal_comments{LegalComments::kDefault};
// -- Markup ------------------------------------------------------------
// The classic runtime is configured by naming the factory and the fragment
// ("React.createElement" and "React.Fragment" for the usual choice); the
// automatic runtime instead imports from "jsx_import_source", and appends
// "/jsx-dev-runtime" to it when "jsx_dev" is set so the development build
// of the runtime is used.
JSX jsx{JSX::kTransform};
std::string jsx_factory; // classic runtime: the element factory
std::string jsx_fragment; // classic runtime: the fragment name
std::string jsx_import_source; // automatic runtime: which module to import from
bool jsx_dev{}; // use the development build of that runtime
bool jsx_side_effects{}; // treat used JSX elements as side effects
// -- Markup output ------------------------------------------------------
// HTML is re-emitted from the parsed tree, so both of these describe the
// printer rather than the file. "pretty" indents the tree on output and is
// on by default: the result is meant to be opened, read and edited, and a
// single line of markup is none of those. "minify_html" collapses it, and
// is off by default because the two are opposites and only one can be the
// unasked-for behaviour. Neither touches content that whitespace is
// meaningful in, so turning either on is always safe.
bool pretty{true};
bool minify_html{};
// -- Compile-time substitution -----------------------------------------
// "define" replaces identifiers and dotted paths with literal values;
// "pure" lists functions that may be dropped or reordered when unused.
// Both are validated up front, so a typo in a define becomes a reported
// message rather than a silent mismatch.
std::unordered_map<std::string, std::string> define;
std::vector<std::string> pure;
bool keep_names{}; // preserve function and class names while minifying
// -- Global name -------------------------------------------------------
// Used by the wrapper formats to publish the bundle's exports as a global.
std::string global_name;
// -- UMD format --------------------------------------------------------
// "extend" appends to an existing global instead of replacing it,
// "no_conflict" wraps the assignment so two copies of the library can
// coexist, and "globals" maps external module ids to the global names the
// wrapper should read them from.
//
// "exports" chooses which entry export the bundle publishes: kUnset
// keeps the namespace object, kDefault publishes the entry's default
// export directly, kNamed is the namespace object spelled the
// way, kNone publishes nothing, and kAuto lets the entry's actual
// exports decide. It is spelled "--exports=<value>" on the command line
// and "exports: '<value>'" through the API or a guchho.json "build"
// object, and it is read for every output format.
bool extend{};
bool no_conflict{};
bool strict{true};
std::unordered_map<std::string, std::string> globals;
Exports exports{Exports::kUnset};
// -- AMD format --------------------------------------------------------
// "amd_id" is the module id this file registers as; "amd_define" renames
// the define() function itself; "amd_base_path" prefixes the ids of the
// modules this one pulls in.
std::string amd_id;
bool amd_auto_id{};
std::string amd_base_path;
std::string amd_define{"define"};
bool amd_force_js_extension_for_imports{};
// -- System format -----------------------------------------------------
// Emits null setters for namespace imports, so reading a missing export
// returns undefined instead of throwing.
bool system_null_setters{};
// -- Graph construction ------------------------------------------------
// "bundle" inlines the whole graph into the output; without it each input
// file is merely converted. Two consequences worth knowing: "external" and
// "alias" only mean something when bundling, and using either without it
// is reported as an error, because there is no graph for them to act on.
//
// "splitting" extracts code shared by several entry points into chunks that
// those entries import, which requires kESModule output. "external" keeps
// the named paths out of the graph and leaves the import statement in the
// output; "alias" redirects a specifier before resolution starts. The
// loader map overrides how individual paths are interpreted, and
// "resolve_extensions" lists the suffixes tried for a specifier that has
// none.
//
// Output location: exactly one of "outfile", "outdir" or neither. With
// neither, the result is a single unnamed file meant to be written to
// stdout by the caller, and options that need a directory - external source
// maps, linked legal-comment files, the file and copy loaders - are
// rejected. With more than one input, or an input containing "*", "outdir"
// is required; setting both "outfile" and "outdir" is an error. "outbase"
// chooses which directory the output tree is measured from when computing
// relative names, and "abs_working_dir" replaces the process working
// directory for the whole build.
bool bundle{};
bool preserve_symlinks{}; // resolve through, instead of collapsing, links
bool splitting{};
std::string outfile; // single output file, relative to outdir
bool metafile{}; // fill BuildResult::metafile with build stats
std::string outdir; // root of the output tree
std::string outbase; // directory the output tree is measured from
std::string abs_working_dir; // overrides the process working directory
Platform platform{Platform::kDefault};
Format format{Format::kDefault};
std::vector<std::string> external;
Packages packages{Packages::kDefault};
std::unordered_map<std::string, std::string> alias;
std::vector<std::string> main_fields; // package metadata fields, in order
std::vector<std::string> conditions; // export conditions to activate
std::unordered_map<std::string, Loader> loader;
std::vector<std::string> resolve_extensions;
std::string tsconfig; // path to a compiler config file
std::string tsconfig_raw; // or its contents, used when no file is needed
std::unordered_map<std::string, std::string> out_extension; // e.g. {".js": ".mjs"}
std::string public_path; // prefix for asset URLs in the output
std::vector<std::string> inject; // files whose exports are prepended
std::unordered_map<std::string, std::string> banner; // text prepended per file kind
std::unordered_map<std::string, std::string> footer; // text appended per file kind
std::vector<std::string> node_paths; // extra module search roots
// -- Output naming -----------------------------------------------------
// Templates built from the [dir], [name], [hash] and [ext] placeholders,
// for example "chunks/[name]-[hash].js". Anything outside a placeholder is
// literal text, and an empty template means "use the default name".
std::string entry_names;
std::string chunk_names;
std::string asset_names;
// -- Inputs ------------------------------------------------------------
// Two ways to name inputs: "entry_points" is a flat list of paths, and
// "entry_points_advanced" carries an explicit output path for each one.
// Both may be used at once; the advanced entries are appended after the
// plain ones. A path containing "*" is expanded as a pattern.
std::vector<std::string> entry_points;
std::vector<EntryPoint> entry_points_advanced;
// -- Execution ---------------------------------------------------------
// "write" is the only switch that touches the disk: without it the caller
// receives the bytes and decides what to do with them. "allow_overwrite"
// permits an output file to land on top of a file the build itself read,
// which is otherwise reported as an error. "stdin_data" feeds one virtual
// file into the graph in place of a path on disk.
std::optional<StdinOptions> stdin_data;
bool write{};
bool allow_overwrite{};
std::vector<Plugin> plugins;
// Which of the above somebody actually said out loud. Filled in by the
// command-line parser and consumed by ResolveEffectiveBuildConfigs; null
// means the struct was assembled by hand and every value in it is
// deliberate. See ExplicitlySet for why this is needed at all.
std::shared_ptr<const ExplicitlySet> explicit_set;
// Whether "format" was named by the user or the config file rather than
// arriving as a built-in default. Filled in by ResolveEffectiveBuildConfigs,
// which is the one place the command line's "explicit_set", the config
// file's "FormatFromConfig" and the built-in "esm" default are all visible
// at once. The HTML-entry warnings consume it to tell an explicit format
// (which is ignored for HTML output) from the default (which is not a
// mistake). It only means anything after a resolution has run.
bool format_was_explicit{};
};
TransformOptions
#The per-file subset of BuildOptions. Options that only make sense for a graph - entry points, outdir, splitting, external, plugin hooks, and the module-resolution fields - are absent by construction, so a transform can never accidentally depend on them.
struct TransformOptions {
// -- Diagnostics -------------------------------------------------------
StderrColor color{StderrColor::kColorIfTerminal};
LogLevel log_level{LogLevel::kInfo};
int log_limit{};
std::unordered_map<std::string, LogLevel> log_override;
AbsPathsFlags abs_paths{AbsPathsFlags::kNone};
// -- Source maps -------------------------------------------------------
SourceMap sourcemap{SourceMap::kNone};
std::string source_root;
SourcesContent sources_content{SourcesContent::kInclude};
// -- Language level ----------------------------------------------------
Target target{Target::kDefault};
std::vector<Engine> engines;
std::unordered_map<std::string, bool> supported;
// -- Output shape ------------------------------------------------------
// Without a bundle there is no wrapper to emit, so "format" only takes
// effect for the formats that can express a single file on its own (an
// IIFE, or a CommonJS export of the entry bindings). "global_name" names
// what an IIFE publishes.
Platform platform{Platform::kDefault};
Format format{Format::kDefault};
std::string global_name;
// -- Minification ------------------------------------------------------
// Same knobs as the build API. "mangle_cache" can be fed back in from a
// previous TransformResult, which keeps property names stable while a user
// types into a file and the editor re-transforms it after every keystroke.
std::string mangle_props;
std::string reserve_props;
MangleQuoted mangle_quoted{MangleQuoted::kFalse};
std::unordered_map<std::string, bool> mangle_cache;
DropFlags drop{DropFlags::kNone};
std::vector<std::string> drop_labels;
bool minify_whitespace{};
bool minify_identifiers{};
bool minify_syntax{};
int line_limit{};
Charset charset{Charset::kDefault};
TreeShaking tree_shaking{TreeShaking::kDefault};
bool ignore_annotations{};
LegalComments legal_comments{LegalComments::kDefault};
// -- Markup ------------------------------------------------------------
JSX jsx{JSX::kTransform};
std::string jsx_factory;
std::string jsx_fragment;
std::string jsx_import_source;
bool jsx_dev{};
bool jsx_side_effects{};
// -- Compiler configuration -------------------------------------------
// The configuration is passed as text rather than as a path, because a
// transform may be asked to process a buffer that has no file yet. Only
// the settings that affect parsing are honoured here (path mapping for
// type-only imports, JSX defaults, and similar).
std::string tsconfig_raw;
std::string banner; // text prepended to the output
std::string footer; // text appended to the output
// -- Compile-time substitution -----------------------------------------
std::unordered_map<std::string, std::string> define;
std::vector<std::string> pure;
bool keep_names{};
// -- Input description -------------------------------------------------
// "sourcefile" is the name that appears in diagnostics and in the map's
// "sources" array; it defaults to "<stdin>". "loader" decides how the
// string is read and defaults to kJS, so plain JavaScript needs no
// configuration at all.
std::string sourcefile;
Loader loader{Loader::kNone};
};
ServeOptions
#How to configure the development server. Port 0 asks the system for any free port, and the port that was actually bound is reported back in ServeResult::port.
Every GET or HEAD request produces the current build first, so a reload always shows the latest output. The requested path is then looked for in three places, in order: inside the build's output directory (served straight from memory, whether or not the build wrote anything to disk), then inside "servedir", and finally in the file named by "fallback" - which is how a single-page app gets its own index document back for any unknown route. A build that produced errors answers with status 503 and the error text as the body, so a mistake shows up in the browser instead of silently serving the previous build.
struct ServeOptions {
uint16_t port{};
std::string host; // interface to bind; empty means every interface
std::string servedir; // directory of static files to fall back to
std::string keyfile; // must be set together with certfile
std::string certfile; // must be set together with keyfile
std::string fallback; // served when nothing else matches
// Turns the server into a live-reload host. While it is on, every HTML
// response is given a script tag pointing at the reserved "/guchho.js"
// path, and that script keeps an event stream open to the server; when a
// rebuild changes the output, the page reloads itself. Off by default:
// "serve" is also used for looking at a build without a browser attached,
// and injecting into responses is only wanted when a person is watching
// one. A caller that rebuilds out of band - a watch session driving the
// server - tells it a rebuild happened through ServeResult::notify.
bool live_reload{};
CORSOptions cors;
// Invoked once per request, after the response has been produced, with the
// method, path, status and how long the response took to generate. A good
// place to count requests, or to log anything the server itself did not
// handle.
std::function<void(const ServeOnRequestArgs&)> on_request;
};
WatchOptions
#How long to wait after a change is noticed before rebuilding. The delay exists so a burst of editor writes (save, format, save again) produces one rebuild instead of three. A delay of 0 rebuilds immediately.
struct WatchOptions {
int delay{};
};
FormatMessagesOptions
#How a batch of messages should be rendered. Width 0 means "do not wrap", which is usually what a log file or an editor wants; a positive width wraps the text and breaks the source snippet to fit.
struct FormatMessagesOptions {
int terminal_width{};
MessageKind kind{MessageKind::kError};
bool color{};
};
AnalyzeMetafileOptions
#How the metafile summary should be rendered. "verbose" only changes the filler between the columns: it is true they are joined with a horizontal rule, and false they are padded with spaces. Either way the same rows are produced.
struct AnalyzeMetafileOptions {
bool color{};
bool verbose{}; // draw column separators as rules instead of blank padding
};
OnResolveOptions
#Which import paths a resolve callback should see, and in which namespace.
struct OnResolveOptions {
std::string filter; // a path pattern, or "" for every path
std::string namespace_;
};
OnLoadOptions
#Which paths a load callback should see, and in which namespace.
struct OnLoadOptions {
std::string filter; // a path pattern, or "" for every path
std::string namespace_;
};
ResolveOptions
#The request handed to PluginBuild::resolve when a plugin resolves a path itself. It mirrors what a callback registered with on_resolve would receive, so one piece of resolution logic can be used either way. Only "kind" is mandatory; the other fields describe the situation, and a plugin that leaves them empty is asking its question with as little context as it can manage.
struct ResolveOptions {
std::string plugin_name; // names the plugin in a resolution error
std::string importer; // the file that asked for it, empty for an entry point
std::string namespace_; // virtual filesystem the request came from
std::string resolve_dir; // directory relative paths resolve against
ResolveKind kind{ResolveKind::kNone};
std::any plugin_data; // payload from the previous step
std::unordered_map<std::string, std::string> with; // values passed via "with"
};
MangleCacheResult
#The file as it was read, in the two shapes the build needs.
struct MangleCacheResult {
// Original property name -> the short name chosen for it. An empty
// optional is a property that is deliberately left alone: the file
// recorded "false" for it, and shortening it would break whatever
// outside the bundle reads it by name - a template, a configuration
// payload, a test that reflects over the result.
std::unordered_map<std::string, std::optional<std::string>> cache;
// The same keys in the order the file listed them. The map cannot carry
// that, and the order is what keeps the rewritten file a small diff
// instead of a reshuffle on every build.
std::vector<std::string> order;
};
ErrorWithNote
#Two part command line errors
A rejected flag is only half a message on its own. "Invalid build flag: "-o"" says that something is wrong; the note is what lets a user fix it, because it names the spelling that does work. The two travel together so a caller can print the advice only when there is some, and keep the complaint itself free of it.
struct ErrorWithNote {
// The complaint, always present.
std::string text;
// How to fix it, and often empty: there is nothing useful to suggest
// for a value that is simply not a number.
std::string note;
};
ParseOptionsExtras
#The three settings a build needs that are not part of api::BuildOptions because they describe the run rather than the build: watching, and the two files the run is asked to write alongside the output.
struct ParseOptionsExtras {
bool watch{};
int watch_delay{};
std::optional<std::string> metafile;
std::optional<std::string> mangle_cache;
};