sonda
Version:
Universal bundle analyzer and visualizer that works with most popular bundlers and frameworks.
476 lines (475 loc) • 17.7 kB
TypeScript
import { DecodedSourceMap } from "@jridgewell/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(): Array<Format>;
get filename(): string;
get outputDir(): string;
get open(): boolean | Format;
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 | Array<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 | Format;
/**
* 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<Array<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;
//#endregion
export { type AssetResource, type ChunkResource, Config, type Connection, type ConnectionKind, type DecodedReportSourceMap, type Dependency, type FileType, type FilesystemResource, type Integration, type IntegrationOptions, type Issue, type JsonReport, type Metadata, type ModuleFormat, Report, type Resource, type ResourceBase, type ResourceKind, type Sizes, SondaEsbuildPlugin, SondaRollupPlugin, SondaVitePlugin, SondaWebpackPlugin, type SourceMap, type SourcemapResource, type UserOptions, getTypeByName, normalizePath, processEsbuildMetafile };