sonda
Version:
Universal bundle analyzer and visualizer that works with most popular bundlers and frameworks.
480 lines (478 loc) • 17.7 kB
TypeScript
import { DecodedSourceMap } from "@ampproject/remapping";
import { PluginOption } from "vite";
import { SourcesPathNormalizer } from "load-source-map";
import { Metafile, Plugin } from "esbuild";
import { Plugin as Plugin$1 } from "rollup";
import { Compiler } from "webpack";
//#region src/config.d.ts
declare class Config implements Required<IntegrationOptions> {
#private;
constructor(options: Partial<IntegrationOptions> | Config, defaults: IntegrationOptions);
clone(): Config;
get enabled(): boolean;
get include(): AssetFilter;
get exclude(): AssetFilter;
get format(): Format;
get filename(): string;
get outputDir(): string;
get open(): boolean;
get deep(): boolean;
get sources(): boolean;
get gzip(): boolean;
get brotli(): boolean;
get server(): boolean;
get integration(): Integration;
get sourcesPathNormalizer(): SourcesPathNormalizer;
set filename(filename: string);
set sourcesPathNormalizer(normalizer: SourcesPathNormalizer);
}
interface UserOptions {
/**
* Specifies whether the plugin is enabled.
*
* @default true
*/
enabled?: boolean;
/**
* Specifies a list of RegExp patterns used to match output assets to include in the report.
* By default, all assets are included.
*
* Patterns are matched against the relative asset paths as displayed in the report. For example,
* to include only JavaScript files, use `[ /\.js$/ ]`.
*
* @default null
*/
include?: AssetFilter;
/**
* Specifies a list of RegExp patterns used to match output assets to exclude from the report.
* By default, no assets are excluded, except for those with `.map` and `.d.ts` extensions, which
* are always excluded regardless of this setting.
*
* This option takes precedence over `include`.
*
* Patterns are matched against the relative asset paths as shown in the report. For example, to exclude all CSS files, use `[ /\.css$/ ]`.
*
* @default null
*/
exclude?: AssetFilter;
/**
* Specifies the output format of the report. Supported formats include:
*
* - `'html'` - An HTML file with a treemap visualization.
* - `'json'` - A JSON file.
*
* @default 'html'
*/
format?: Format;
/**
* Specifies the filename of the generated report. If this value is an absolute path,
* it overrides the `outputDir` option.
*
* The default value includes placeholders like `[index]` and `[env]`, which are replaced
* during report generation.
*
* The `[index]` placeholder is replaced with a version number that increments each time
* a new report is generated. This allows you to keep multiple revisions of the report without
* overwriting previous ones. If you want to generate only a single report and always overwrite
* the previous one, you can set this option to a static value, such as `'sonda'`.
*
* Additionally, framework integrations that can generate reports for both the client and server
* (with the `server` option) will include the `[env]` placeholder in the filename. This is replaced with
* the environment name (e.g., `client`, `server`), allowing you to distinguish between client and server reports.
*
* @default `'sonda_[index]'` for bundler integrations and `'sonda_[env]_[index]'` for framework integrations.
*/
filename?: string;
/**
* Specifies the directory where the report will be saved. This can be a relative or absolute path. By default,
* the report is saved in a `.sonda` directory relative to the current working directory.
*
* The directory is created if it does not exist.
*
* @default '.sonda'
*/
outputDir?: string;
/**
* Specifies whether to automatically open the report in the default program for
* the given file extension (`.html` or `.json`, depending on the `format` option)
* after the build process.
*
* @default false
*/
open?: boolean;
/**
* Specifies whether to read source maps of imported modules.
*
* By default, external dependencies bundled into a single file appear as a single asset. When this option
* is enabled, the report includes the source files of imported modules, if their source maps are available.
*
* Enabling this option may increase report generation time and reduce the accuracy of estimated GZIP
* and Brotli sizes.
*
* @default false
*/
deep?: boolean;
/**
* Specifies whether to include source maps of generated assets in the report to visualize which parts of
* the code contribute to the final asset size.
*
* ⚠️
* This option significantly increases the report size and embeds the **source code** of the assets.
* If you are working with proprietary code, ensure you share the report responsibly.
* ⚠️
*
* @default false
*/
sources?: boolean;
/**
* Specifies whether to calculate asset sizes after compression with GZIP.
*
* The report also includes estimated compressed sizes for each file within an asset. These estimates are
* approximate and intended for general reference.
*
* Enabling this option may increase report generation time.
*
* @default false
*/
gzip?: boolean;
/**
* Specifies whether to calculate asset sizes after compression with Brotli.
*
* The report also includes estimated compressed sizes for each file within an asset. These estimates are
* approximate and intended for general reference.
*
* Enabling this option may increase report generation time.
*
* @default false
*/
brotli?: boolean;
/**
* Specifies whether to generate a report for the server build.
*
* This option is only available for framework integrations.
*
* @default false
*/
server?: boolean;
}
interface IntegrationOptions extends UserOptions {
/**
* Specifies the integration used to generate the report.
*/
integration: Integration;
/**
* Normalizes the paths in source maps to a consistent format.
*
* @default null
*/
sourcesPathNormalizer?: SourcesPathNormalizer;
}
/**
* Filter for including or excluding assets based on their paths.
*/
type AssetFilter = Array<RegExp> | null;
type Format = "html" | "json";
type Integration = "angular" | "astro" | "esbuild" | "next" | "nuxt" | "rolldown" | "rollup" | "rspack" | "sveltekit" | "vite" | "webpack" | "unknown";
//#endregion
//#region src/integrations/esbuild.d.ts
declare function SondaEsbuildPlugin(userOptions?: UserOptions): Plugin;
declare function processEsbuildMetafile(metafile: Metafile, options: Config): Promise<void>;
//#endregion
//#region src/integrations/rollup.d.ts
declare function SondaRollupPlugin(userOptions?: UserOptions): Plugin$1;
//#endregion
//#region src/integrations/vite.d.ts
declare function SondaVitePlugin(userOptions?: UserOptions): PluginOption;
//#endregion
//#region src/integrations/webpack.d.ts
declare class SondaWebpackPlugin {
options: Config;
constructor(userOptions?: UserOptions);
apply(compiler: Compiler): void;
}
//#endregion
//#region src/report/types.d.ts
interface JsonReport {
/**
* Metadata about the report, including the version of Sonda used to generate it,
* the integration used, and the options passed to Sonda.
*/
metadata: Metadata;
/**
* List of all input and output resources.
*/
resources: Array<Resource>;
/**
* List of all connections between resources.
*/
connections: Array<Connection>;
/**
* List of all detected external dependencies and their paths. If
* a dependency has more than one path, it's likely duplicated and
* bundled in multiple copies.
*/
dependencies: Array<Dependency>;
/**
* List of issues detected in the outputs.
*/
issues: Array<Issue>;
/**
* Partial source maps of the "asset" resources.
*
* This value is only available when the `deep` option is enabled.
*/
sourcemaps: Array<SourceMap>;
}
interface Metadata {
/**
* Version of Sonda used to generate the report.
*/
version: string;
/**
* Integration used to generate the report.
*/
integration: Integration;
/**
* The normalized value of the `sources` option passed to Sonda.
*/
sources: boolean;
/**
* The normalized value of the `gzip` option passed to Sonda.
*/
gzip: boolean;
/**
* The normalized value of the `brotli` option passed to Sonda.
*/
brotli: boolean;
}
/**
* Base interface for all resources.
*
* Resources represent the following inputs:
*
* ┌─────────────────────────────┐
* │ │
* │ OPTIONAL ORIGINAL SOURCE │
* │ │
* └──────────────▲──────────────┘
* │
* │
* VIA SOURCEMAP
* │
* │
* ┌─────────────────────────────┐ ┌──────────────┼──────────────┐
* │ │ │ │
* │ INTERNAL SOURCE │ │ EXTERNAL SOURCE │
* │ │ │ │
* └──────────────┬──────────────┘ └──────────────┬──────────────┘
* │ │
* │ │
* └─────────────────┬─────────────────┘
* │
* │
* ┌──────────────▼──────────────┐
* │ │
* │ BUNDLER │
* │ │
* └──────────────┬──────────────┘
* │
* │
* │
* │
* │
* ┌──────────────▼──────────────┐
* │ │
* │ ASSET │
* │ │
* └──────────────┬──────────────┘
* │
* │
* VIA SOURCEMAP
* │
* │
* ┌──────────────▼──────────────┐
* │ │
* │ CHUNK │
* │ │
* └─────────────────────────────┘
*/
interface ResourceBase {
/**
* Information where the resource comes from.
*/
kind: ResourceKind;
/**
* Relative path to the resource.
*
* If the `source` is `sourcemap`, the file may not exist in the filesystem.
*/
name: string;
/**
* Type of the resources, determined by the file extension.
*/
type: FileType;
/**
* Format of the module, if the resource type is `script`.
*/
format?: ModuleFormat;
/**
* Size of the resource without any compression.
*/
uncompressed: number;
/**
* Size of the resource after GZIP compression.
*
* This value is only available when the `gzip` option is enabled.
*/
gzip?: number;
/**
* Size of the resource after Brotli compression.
*
* This value is only available when the `brotli` option is enabled.
*/
brotli?: number;
/**
* Parent of the resource.
*
* If the `kind` is `chunk`, this resource is a part of the output
* asset and value of `parent` is the name of the output asset.
*
* If the `kind` is `sourcemap`, this resource is a part of the source
* map of other resource and value of `parent` is the name of that resource.
*/
parent?: string | Array<string> | null;
}
/**
* Input resource loaded from the filesystem by the bundler.
*
* See INTERNAL SOURCE and EXTERNAL SOURCE in the diagram above.
*/
interface FilesystemResource extends ResourceBase {
kind: "filesystem";
name: string;
type: FileType;
format: ModuleFormat;
uncompressed: number;
gzip?: never;
brotli?: never;
parent?: never;
}
/**
* Input resource read from a sourcemap of the filesystem resource.
*
* See OPTIONAL ORIGINAL SOURCE in the diagram above.
*/
interface SourcemapResource extends ResourceBase {
kind: "sourcemap";
name: string;
type: FileType;
format: ModuleFormat;
uncompressed: number;
gzip?: never;
brotli?: never;
parent: string | null;
}
/**
* Output resource generated by the bundler.
*
* See ASSET in the diagram above.
*/
interface AssetResource extends ResourceBase {
kind: "asset";
name: string;
type: FileType;
format?: never;
uncompressed: number;
gzip: number;
brotli: number;
parent?: never;
}
/**
* Part of the input resource that was used in one of the assets
* (after tree-shaking, minification, etc.).
*
* See CHUNK in the diagram above.
*/
interface ChunkResource extends ResourceBase {
kind: "chunk";
name: string;
type: FileType;
format: ModuleFormat;
uncompressed: number;
gzip: number;
brotli: number;
parent: string;
}
interface Connection {
kind: ConnectionKind;
source: string;
target: string;
original: string | null;
}
interface Dependency {
name: string;
paths: Array<string>;
}
interface Issue {
type: string;
data: unknown;
}
/**
* All types of resources.
*/
type Resource = FilesystemResource | SourcemapResource | AssetResource | ChunkResource;
type Sizes = Required<Pick<ResourceBase, "uncompressed" | "gzip" | "brotli">>;
type ResourceKind = "filesystem" | "sourcemap" | "asset" | "chunk";
type ConnectionKind = "entrypoint" | "import" | "require" | "dynamic-import" | "sourcemap";
type FileType = "component" | "font" | "image" | "script" | "style" | "other";
type ModuleFormat = "esm" | "cjs" | "amd" | "umd" | "iife" | "system" | "other";
/**
* Type for the source map strings from the report after decoding.
*/
interface SourceMap {
/**
* Name of the asset file that the source map belongs to.
*/
name: string;
/**
* Stringified source map.
*
* Use the `DecodedMap` type for the decoded version of this map (after `JSON.parse()`).
*/
map: string;
}
type DecodedReportSourceMap = Pick<DecodedSourceMap, "mappings" | "sources" | "sourcesContent">;
//#endregion
//#region src/report/report.d.ts
declare class Report {
#private;
readonly config: Config;
readonly resources: Array<Resource>;
readonly connections: Array<Connection>;
readonly assets: Record<string, Array<string> | undefined>;
protected metadata: Metadata;
protected dependencies: Array<Dependency>;
protected issues: Array<Issue>;
protected sourcemaps: Array<SourceMap>;
constructor(config: Config);
addResource(resource: Resource): void;
addConnection(connection: Connection): void;
addAsset(name: string, entrypoints?: Array<string>): void;
generate(): Promise<string>;
addSourceMap(asset: string, sourcemap: DecodedReportSourceMap): void;
}
//#endregion
//#region src/utils.d.ts
/**
* Normalizes a given path by removing leading null characters and converting it to a relative POSIX path.
*/
declare function normalizePath(pathToNormalize: string): string;
/**
* Returns the type of a given file based on its name.
*/
declare function getTypeByName(name: string): FileType;
/**
* Returns only the object keys which have a string value.
*/
//#endregion
export { AssetResource, ChunkResource, Config, Connection, ConnectionKind, DecodedReportSourceMap, Dependency, FileType, FilesystemResource, Integration, IntegrationOptions, Issue, JsonReport, Metadata, ModuleFormat, Report, Resource, ResourceBase, ResourceKind, Sizes, SondaEsbuildPlugin, SondaRollupPlugin, SondaVitePlugin, SondaWebpackPlugin, SourceMap, SourcemapResource, UserOptions, getTypeByName, normalizePath, processEsbuildMetafile };