Build Configurations and tps.json
tps.json is the configuration file the Transpose compiler reads for every
build. This page covers where the compiler looks for it, how the
per-configuration variants tps.Debug.json and tps.Release.json are merged,
and how the active build configuration decides whether the minified or
non-minified output is wired into the generated HTML.
For the full list of individual options, see Global Configuration.
For everything about the resources section specifically, see Resources.
Where the compiler looks for tps.json
The compiler reads tps.json from the project (.csproj) directory — one
location, no search path. If the file is absent the compiler falls back to its
built-in defaults and the build still runs.
tps.json is JSON with // and /* */ comments and trailing commas allowed.
Property names are case-sensitive
Unlike h5, which matched keys case-insensitively, Transpose reads the keys
verbatim: outputFormatting is read, OutputFormatting is silently ignored.
Use camelCase exactly as documented. (The values of outputFormatting are
matched case-insensitively, so "both" and "Both" are equivalent.)
Per-configuration files
Alongside tps.json you can ship a configuration-specific file whose name
carries the MSBuild configuration:
tps.Debug.jsontps.Release.jsontps.<AnyConfiguration>.json— any custom configuration name works too (for exampletps.Staging.jsonfor aStagingbuild configuration).
The configuration comes from the build: dotnet build -c Release looks for
tps.Release.json, dotnet build -c Debug looks for tps.Debug.json. These
files live in the project directory, next to tps.json.
How the files are merged
When a build configuration is active, the compiler loads tps.json as the
base and merges the matching tps.<Configuration>.json on top of it.
The rules in detail:
- Scalar settings (
output,fileName,outputFormatting,html.*,reflection.*,cleanOutputFolder, …): a key present in the configuration-specific file wins. A key absent from it keeps the base value. - Arrays (
resourcesandcleanOutputFolderExclude) are concatenated, base first, then the overlay — they do not replace. - If
tps.<Configuration>.jsondoes not exist, onlytps.jsonis used. - If no configuration is passed to the build, only
tps.jsonis read; no per-configuration file is picked up.
Arrays are concatenated, not replaced
Because the resources arrays from both
files are appended, declaring the same bundle in both produces two entries.
Resources are de-duplicated by their resolved output name, with the overlay's
entry winning, so a deliberate override works — but keeping a resource in only
one of the two files is clearer.
What to put where
Keep everything shared in tps.json and put only the values that genuinely
differ per configuration in the override file. A common split is to emit both
output variants for Release while keeping Debug builds readable and fast:
{
"output": "$(OutDir)tps/",
"fileName": "app.js",
"outputFormatting": "Formatted"
}
How the configuration affects the output
The outputFormatting option controls which flavours of the JavaScript are
produced:
| Value | Produces |
|---|---|
Formatted |
Readable .js only |
Minified |
.min.js only |
Both |
Both .js and .min.js (the default) |
When both variants exist, the active build configuration decides which one is referenced from the generated HTML:
Release— only the minified files are wired up, and the minified page is written out asindex.html.Debug— only the non-minified files are wired up inindex.html.- No configuration — both
index.html(non-minified) andindex.min.html(minified) are written.
This same configuration-driven selection applies to resources pulled from
referenced libraries. A Transpose library package embeds its compiled JavaScript
in both a formatted and a pre-minified variant, so a consuming project
extracts the .min.js versions in Release and the plain .js versions in
Debug without minifying library code itself. See the
Resources page for how a library's own
resources section interacts with that.
Debug and Release are structurally different builds
Beyond which JavaScript variant is wired up, the two configurations emit different .NET assemblies:
- Debug emits a metadata-only assembly: full metadata, but no method bodies. This is sound because a Transpose assembly binds against the browser-side stand-in BCL and is never executed on .NET, and it makes the build measurably faster.
- Release emits full IL.
Because a package needs real IL, the SDK refuses to package a Debug build:
GeneratePackageOnBuild is forced off in Debug and dotnet pack -c Debug fails
with TPS1001. Pack Release.
Incremental builds
The SDK passes --incremental by default, so a rebuild reuses the previous
build's cache: nothing is compiled at all when every input hashes the same, and
an edit confined to method bodies keeps the cached JavaScript of every untouched
type. The output is byte-identical either way.
Turn it off for a project with:
<PropertyGroup>
<TransposeIncremental>false</TransposeIncremental>
</PropertyGroup>
The tps CLI itself defaults to incremental off; pass --incremental to opt
in when invoking it directly.