Build Process
Relevant source files
The following files were used as context for generating this wiki page:The Ghostbird build process is an automated system orchestrated by Yarn scripts that leverages the tsdown bundler. Its primary purpose is to transpile TypeScript source code, process and generate necessary assets like manifest.json and localization files, bundle the code, and package everything into a final .xpi file for distribution as a Thunderbird add-on. The entire process is defined through a combination of package.json scripts and a central tsdown configuration file.
Sources: doc/building.md, package.json, tools/tsdown_config.ts
Build Orchestration
The build process is initiated via Yarn scripts defined in package.json. These scripts provide entry points for different build tasks, from development to final packaging.
Sources: package.json:20-56, CONTRIBUTING.md:46-51
Key Build Scripts
The following table summarizes the main scripts used in the build process:
| Script | Description |
|---|---|
yarn build | Runs a full build sequence: check (type-check & lint), test, build-js, and finally build-xpi. |
yarn build-js | Invokes tsdown to bundle TypeScript source files and assets into the dist/ext/ directory. |
yarn build-xpi | Uses web-ext to package the contents of dist/ext/ into a .xpi file in the dist/ directory. |
yarn watch | An alias for yarn build-js --watch, which continuously rebuilds JavaScript bundles on file changes. |
yarn start | An alias for web-ext run, which launches Thunderbird with the extension loaded for debugging. |
yarn index-ts | An alias for barrelsby, which generates index.ts barrel files. This also runs on postinstall. |
yarn test | Runs the full unit test suite using Vitest. |
yarn check | Runs tsc for type checking and biome for linting. |
Sources: package.json:20-56, CONTRIBUTING.md:46-77
Build Architecture and Flow
The build process is centered around the tsdown tool, configured in tools/tsdown_config.ts. It takes various source files as input and produces the bundled JavaScript files and other assets required for the extension.
The overall data flow of the build process is as follows:
This diagram shows how source files are processed by tsdown and its plugins to generate intermediate artifacts, which are then packaged by web-ext into the final extension file.
Sources: doc/building.md, tools/tsdown_config.ts
tsdown Configuration
The core of the build logic resides in tools/tsdown_config.ts. This file defines the configuration for tsdown, including entry points, output directories, and plugins. It specifies two main configurations: one for ES modules (esmConfig) and one for an immediately-invoked function expression (iifeConfig) for the compose.js script.
A commonConfig object defines shared settings, such as:
outDir:dist/ext/platform:browsertarget:firefox128sourcemap:trueminify:dce-only(dead code elimination only)
Sources: tools/tsdown_config.ts:31-87
Build Modes: Development vs. Release
The build process operates in two modes: development and release. The mode is determined by the isRelease flag in tools/tsdown_config.ts, which checks for the CI environment variable or the existence of ext/manifest.json.
- Development Build:
- Source maps contain absolute paths for easier debugging.
console.log()statements are preserved.- Sanity tests and type-checking are run as part of the build.
- Release Build:
- Source maps use relative paths.
console.log()statements are removed from the output.- Sanity tests and type-checking are skipped, as they are expected to be run in preceding steps (
yarn build).
Sources: doc/building.md:43-58, tools/tsdown_config.ts:29, 61, 107-109
Custom Build Plugins
The build process is extended with several custom plugins for tsdown, each handling a specific task.
| Plugin File | Description |
|---|---|
tools/barrelsby.ts | Generates index.ts barrel files for easier module imports, based on tsconfig.json configuration. |
tools/generate_manifest.ts | Creates dist/ext/manifest.json from manifest_template.json, injecting version information. |
tools/generate_locale_messages.ts | Generates _locales/*/messages.json files from a single locales.toml file for internationalization. |
tools/test_sanity.ts | Runs basic unit tests during development builds to catch common errors early. |
tools/typecheck_with_tsc.ts | Runs tsc --build to perform type checking, as tsdown itself does not check types. |
tools/codecov.ts | Uploads bundle size information to Codecov during release builds. |
Sources: doc/building.md:60-74, tools/tsdown_config.ts:105-115
Barrel File Generation
The barrelsby.ts script, which is also run via yarn index-ts, automatically creates index.ts files in each directory under src/. These files export all other modules in their directory, simplifying import statements across the project. The configuration for this is stored in tsconfig.json. The script also ensures that a top-level src/index.ts is not created.
Sources: tools/barrelsby.ts, tsconfig.json:11-23, doc/faq.md:100-104
Manifest Generation and Versioning
The generate_manifest.ts plugin is responsible for creating the final manifest.json. It reads manifest_template.json, injects a version number, and writes the result to the build output directory.
The version number is determined based on the build environment, following a specific hierarchy:
This flow ensures that builds are versioned appropriately for CI releases, local development, and builds from source tarballs without Git history. A key part of the release versioning is appending a truncated commit SHA to the version string.
// tools/generate_manifest.ts:98-100
function appendSha(version: string, sha: string): string {
return `${version}.${Number.parseInt(sha.slice(0, 7), 16)}`
}
Sources: tools/generate_manifest.ts, doc/building.md:80-104
Testing in the Build Pipeline
Unit tests are an integral part of the build.
yarn testruns the complete test suite using Vitest.yarn test:sanityruns a subset of tests. This is integrated into the development build (build-js) via thetest_sanity.tsplugin to provide fast feedback.- After tests are run, a dependency report is generated at
build/test/dependency_tree.md, which visualizes the class dependency graph.
Sources: package.json:41-45, tools/tsdown_config.ts:107-108, doc/testing.md:3-15, src/test/util/dependency_reporter.ts:10-17, src/test/startup.test.ts:50-55
Final Packaging
The final step of the build process is packaging the extension into a .xpi file. This is handled by the web-ext tool, triggered by the yarn build-xpi script. The configuration in package.json instructs web-ext to:
- Use
dist/ext/as the source directory. - Place the output artifact in
dist/. - Name the file using the pattern
{short_name}-{version}.xpi.
Sources: package.json:59-67, doc/building.md:27-29