sonda 0.8.1 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 87d59f9: Add `include` and `exclude` options
8
+
9
+ ## 0.8.2
10
+
11
+ ### Patch Changes
12
+
13
+ - 3ec00ae: (Performance) Prevent duplicate resolution of some imports in Rollup
14
+ - 9f34bbf: Add a search field to the Treemap view for filtering inputs
15
+ - 1c14126: Log report path after generation
16
+ - 5ae02e5: Fix edge case in Treemap where items fail to sort in descending order by size
17
+ - 9d25830: Always show input code when available, even if CSS Custom Highlighting API is unsupported
18
+ - b230643: Allow filtering inputs by "type" when inspecting asset in Treemap view
19
+ - ab2f385: Reintroduce the `filename` configuration option
20
+
3
21
  ## 0.8.1
4
22
 
5
23
  ### Patch Changes
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Sonda
2
2
 
3
- Sonda is a universal visualizer and analyzer for JavaScript and CSS bundles. It generates an interactive HTML report that is more accurate and detailed than some alternatives. The accuracy is achieved by analyzing source maps and showing the size of each module after tree-shaking and minification.
3
+ Sonda is a universal bundle analyzer and visualizer. It generates an interactive HTML report that is more accurate and detailed than some alternatives. The accuracy is achieved by analyzing source maps and showing the size of each module after tree-shaking and minification.
4
4
 
5
5
  Sonda works with the following tools:
6
6
 
@@ -8,6 +8,7 @@ const { values } = parseArgs( {
8
8
  config: { type: 'string' },
9
9
  projects: { type: 'string', multiple: true },
10
10
  format: { type: 'string' },
11
+ filename: { type: 'string' },
11
12
  outputDir: { type: 'string' },
12
13
  'no-open': { type: 'boolean' },
13
14
  deep: { type: 'boolean' },
@@ -6,7 +6,7 @@ import { Config, processEsbuildMetafile } from "sonda";
6
6
  async function SondaAngular({ config = "angular.json", projects = [],...userOptions }) {
7
7
  const options = new Config(userOptions, {
8
8
  integration: "angular",
9
- filename: "sonda_[project]"
9
+ filename: "sonda_[env]_[index]"
10
10
  });
11
11
  const angularConfig = loadJson(config);
12
12
  const projectsToGenerate = projects.length ? projects : Object.keys(angularConfig.projects);
@@ -18,7 +18,7 @@ async function SondaAngular({ config = "angular.json", projects = [],...userOpti
18
18
  paths.server = resolve(paths.base, paths.server || "server");
19
19
  const metafile = updateMetafile(loadJson(resolve(paths.base, "stats.json")), paths.base);
20
20
  const sondaOptions = options.clone();
21
- sondaOptions.filename = sondaOptions.filename.replace("[project]", project);
21
+ sondaOptions.filename = sondaOptions.filename.replace("[env]", project);
22
22
  sondaOptions.sourcesPathNormalizer = (path) => resolve(process.cwd(), path);
23
23
  await processEsbuildMetafile(metafile, sondaOptions);
24
24
  }
@@ -4,20 +4,23 @@ import { Config, SondaVitePlugin } from "sonda";
4
4
  function SondaAstroPlugin(userOptions = {}) {
5
5
  const options = new Config(userOptions, {
6
6
  integration: "astro",
7
- filename: "sonda_[env]"
7
+ filename: "sonda_[env]_[index]"
8
8
  });
9
9
  if (!options.enabled) return {
10
- name: "sonda-astro",
10
+ name: "sonda/astro",
11
11
  hooks: {}
12
12
  };
13
13
  return {
14
- name: "sonda-astro",
14
+ name: "sonda/astro",
15
15
  hooks: { "astro:build:setup"({ vite, target }) {
16
16
  if (target === "server" && !options.server) return;
17
17
  const sondaOptions = options.clone();
18
18
  sondaOptions.filename = sondaOptions.filename.replace("[env]", target);
19
19
  vite.plugins ??= [];
20
- vite.plugins.push(SondaVitePlugin(sondaOptions));
20
+ vite.plugins.push({
21
+ ...SondaVitePlugin(sondaOptions),
22
+ name: "sonda/astro"
23
+ });
21
24
  } }
22
25
  };
23
26
  }
@@ -5,7 +5,7 @@ function SondaNextPlugin(userOptions = {}) {
5
5
  return function Sonda(nextConfig = {}) {
6
6
  const options = new Config(userOptions, {
7
7
  integration: "next",
8
- filename: "sonda_[env]"
8
+ filename: "sonda_[env]_[index]"
9
9
  });
10
10
  if (!options.enabled) return nextConfig;
11
11
  return Object.assign({}, nextConfig, { webpack(config, { nextRuntime, isServer }) {
@@ -5,7 +5,7 @@ function SondaNuxtPlugin(userOptions = {}) {
5
5
  return function SondaNuxtPlugin$1(_, nuxt) {
6
6
  const options = new Config(userOptions, {
7
7
  integration: "nuxt",
8
- filename: "sonda_[env]"
8
+ filename: "sonda_[env]_[index]"
9
9
  });
10
10
  if (!options.enabled) return;
11
11
  nuxt.hook("vite:extendConfig", (config, { isClient, isServer }) => {
@@ -14,7 +14,10 @@ function SondaNuxtPlugin(userOptions = {}) {
14
14
  const sondaOptions = options.clone();
15
15
  sondaOptions.filename = sondaOptions.filename.replace("[env]", env);
16
16
  config.plugins ??= [];
17
- config.plugins.push(SondaVitePlugin(sondaOptions));
17
+ config.plugins.push({
18
+ ...SondaVitePlugin(sondaOptions),
19
+ name: "sonda/nuxt"
20
+ });
18
21
  });
19
22
  };
20
23
  }
@@ -3,10 +3,10 @@ import { Config, SondaRollupPlugin } from "sonda";
3
3
  //#region src/entrypoints/rolldown.ts
4
4
  function RolldownPlugin(userOptions = {}) {
5
5
  const options = new Config(userOptions, { integration: "rolldown" });
6
- if (!options.enabled) return { name: "sonda-rolldown" };
6
+ if (!options.enabled) return { name: "sonda/rolldown" };
7
7
  return {
8
8
  ...SondaRollupPlugin(options),
9
- name: "sonda-rolldown"
9
+ name: "sonda/rolldown"
10
10
  };
11
11
  }
12
12
 
@@ -4,12 +4,12 @@ import { Config, SondaVitePlugin } from "sonda";
4
4
  function SondaSvelteKitPlugin(userOptions = {}) {
5
5
  const options = new Config(userOptions, {
6
6
  integration: "sveltekit",
7
- filename: "sonda_[env]"
7
+ filename: "sonda_[env]_[index]"
8
8
  });
9
- if (!options.enabled) return { name: "sonda-sveltekit" };
9
+ if (!options.enabled) return { name: "sonda/sveltekit" };
10
10
  return {
11
11
  ...SondaVitePlugin(options),
12
- name: "sonda-sveltekit",
12
+ name: "sonda/sveltekit",
13
13
  configResolved(config) {
14
14
  const env = config.build.ssr ? "server" : "client";
15
15
  const generateForServer = userOptions.server ?? false;
package/dist/index.d.ts CHANGED
@@ -11,7 +11,10 @@ declare class Config implements Required<IntegrationOptions> {
11
11
  constructor(options: Partial<IntegrationOptions> | Config, defaults: IntegrationOptions);
12
12
  clone(): Config;
13
13
  get enabled(): boolean;
14
+ get include(): AssetFilter;
15
+ get exclude(): AssetFilter;
14
16
  get format(): Format;
17
+ get filename(): string;
15
18
  get outputDir(): string;
16
19
  get open(): boolean;
17
20
  get deep(): boolean;
@@ -20,7 +23,6 @@ declare class Config implements Required<IntegrationOptions> {
20
23
  get brotli(): boolean;
21
24
  get server(): boolean;
22
25
  get integration(): Integration;
23
- get filename(): string;
24
26
  get sourcesPathNormalizer(): SourcesPathNormalizer;
25
27
  set filename(filename: string);
26
28
  set sourcesPathNormalizer(normalizer: SourcesPathNormalizer);
@@ -33,13 +35,60 @@ interface UserOptions {
33
35
  */
34
36
  enabled?: boolean;
35
37
  /**
36
- * Specifies the output format of the report.
38
+ * Specifies a list of RegExp patterns used to match output assets to include in the report.
39
+ * By default, all assets are included.
40
+ *
41
+ * Patterns are matched against the relative asset paths as displayed in the report. For example,
42
+ * to include only JavaScript files, use `[ /\.js$/ ]`.
43
+ *
44
+ * @default null
45
+ */
46
+ include?: AssetFilter;
47
+ /**
48
+ * Specifies a list of RegExp patterns used to match output assets to exclude from the report.
49
+ * By default, no assets are excluded, except for those with `.map` and `.d.ts` extensions, which
50
+ * are always excluded regardless of this setting.
51
+ *
52
+ * This option takes precedence over `include`.
53
+ *
54
+ * Patterns are matched against the relative asset paths as shown in the report. For example, to exclude all CSS files, use `[ /\.css$/ ]`.
55
+ *
56
+ * @default null
57
+ */
58
+ exclude?: AssetFilter;
59
+ /**
60
+ * Specifies the output format of the report. Supported formats include:
61
+ *
62
+ * - `'html'` - An HTML file with a treemap visualization.
63
+ * - `'json'` - A JSON file.
37
64
  *
38
65
  * @default 'html'
39
66
  */
40
67
  format?: Format;
41
68
  /**
42
- * Specifies the name of the directory where the report will be saved.
69
+ * Specifies the filename of the generated report. If this value is an absolute path,
70
+ * it overrides the `outputDir` option.
71
+ *
72
+ * The default value includes placeholders like `[index]` and `[env]`, which are replaced
73
+ * during report generation.
74
+ *
75
+ * The `[index]` placeholder is replaced with a version number that increments each time
76
+ * a new report is generated. This allows you to keep multiple revisions of the report without
77
+ * overwriting previous ones. If you want to generate only a single report and always overwrite
78
+ * the previous one, you can set this option to a static value, such as `'sonda'`.
79
+ *
80
+ * Additionally, framework integrations that can generate reports for both the client and server
81
+ * (with the `server` option) will include the `[env]` placeholder in the filename. This is replaced with
82
+ * the environment name (e.g., `client`, `server`), allowing you to distinguish between client and server reports.
83
+ *
84
+ * @default `'sonda_[index]'` for bundler integrations and `'sonda_[env]_[index]'` for framework integrations.
85
+ */
86
+ filename?: string;
87
+ /**
88
+ * Specifies the directory where the report will be saved. This can be a relative or absolute path. By default,
89
+ * the report is saved in a `.sonda` directory relative to the current working directory.
90
+ *
91
+ * The directory is created if it does not exist.
43
92
  *
44
93
  * @default '.sonda'
45
94
  */
@@ -53,47 +102,47 @@ interface UserOptions {
53
102
  */
54
103
  open?: boolean;
55
104
  /**
56
- * Specifies whether to read the source maps of imported modules.
105
+ * Specifies whether to read source maps of imported modules.
57
106
  *
58
- * By default, external dependencies bundled into a single file appear as a single
59
- * asset in the report. When this option is enabled, the report includes the source
60
- * files of imported modules, if source maps are available.
107
+ * By default, external dependencies bundled into a single file appear as a single asset. When this option
108
+ * is enabled, the report includes the source files of imported modules, if their source maps are available.
61
109
  *
62
- * Enabling this option may increase the time needed to generate the report and reduce
63
- * the accuracy of estimated GZIP and Brotli sizes for individual files.
110
+ * Enabling this option may increase report generation time and reduce the accuracy of estimated GZIP
111
+ * and Brotli sizes.
64
112
  *
65
113
  * @default false
66
114
  */
67
115
  deep?: boolean;
68
116
  /**
69
- * Specifies whether to include source maps of the assets in the report to visualize
70
- * which parts of the code contribute to the final asset size.
117
+ * Specifies whether to include source maps of generated assets in the report to visualize which parts of
118
+ * the code contribute to the final asset size.
71
119
  *
72
- * ⚠️ This option significantly increases the size of the report and embeds the
73
- * **source code** of the assets. If you are working with proprietary code, ensure
74
- * you share the report responsibly. ⚠️
120
+ * ⚠️
121
+ * This option significantly increases the report size and embeds the **source code** of the assets.
122
+ * If you are working with proprietary code, ensure you share the report responsibly.
123
+ * ⚠️
75
124
  *
76
125
  * @default false
77
126
  */
78
127
  sources?: boolean;
79
128
  /**
80
- * Specifies whether to calculate the sizes of assets after compression with GZIP.
129
+ * Specifies whether to calculate asset sizes after compression with GZIP.
81
130
  *
82
- * The report includes estimated compressed sizes for each file within an asset.
83
- * However, these estimates are approximate and should be used as a general reference.
131
+ * The report also includes estimated compressed sizes for each file within an asset. These estimates are
132
+ * approximate and intended for general reference.
84
133
  *
85
- * Enabling this option may increase the time required to generate the report.
134
+ * Enabling this option may increase report generation time.
86
135
  *
87
136
  * @default false
88
137
  */
89
138
  gzip?: boolean;
90
139
  /**
91
- * Specifies whether to calculate the sizes of assets after compression with Brotli.
140
+ * Specifies whether to calculate asset sizes after compression with Brotli.
92
141
  *
93
- * The report includes estimated compressed sizes for each file within an asset.
94
- * However, these estimates are approximate and should be used as a general reference.
142
+ * The report also includes estimated compressed sizes for each file within an asset. These estimates are
143
+ * approximate and intended for general reference.
95
144
  *
96
- * Enabling this option may increase the time required to generate the report.
145
+ * Enabling this option may increase report generation time.
97
146
  *
98
147
  * @default false
99
148
  */
@@ -101,7 +150,7 @@ interface UserOptions {
101
150
  /**
102
151
  * Specifies whether to generate a report for the server build.
103
152
  *
104
- * This option is only available for meta-framework integrations.
153
+ * This option is only available for framework integrations.
105
154
  *
106
155
  * @default false
107
156
  */
@@ -113,18 +162,16 @@ interface IntegrationOptions extends UserOptions {
113
162
  */
114
163
  integration: Integration;
115
164
  /**
116
- * Specifies the name of the file where the report will be saved.
117
- *
118
- * @default 'sonda'
119
- */
120
- filename?: string;
121
- /**
122
165
  * Normalizes the paths in source maps to a consistent format.
123
166
  *
124
167
  * @default null
125
168
  */
126
169
  sourcesPathNormalizer?: SourcesPathNormalizer;
127
170
  }
171
+ /**
172
+ * Filter for including or excluding assets based on their paths.
173
+ */
174
+ type AssetFilter = Array<RegExp> | null;
128
175
  type Format = "html" | "json";
129
176
  type Integration = "angular" | "astro" | "esbuild" | "next" | "nuxt" | "rolldown" | "rollup" | "rspack" | "sveltekit" | "vite" | "webpack" | "unknown";
130
177
  //#endregion
@@ -412,7 +459,7 @@ declare class Report {
412
459
  addResource(resource: Resource): void;
413
460
  addConnection(connection: Connection): void;
414
461
  addAsset(name: string, entrypoints?: Array<string>): void;
415
- generate(): Promise<void>;
462
+ generate(): Promise<string>;
416
463
  addSourceMap(asset: string, sourcemap: DecodedReportSourceMap): void;
417
464
  }
418
465
  //#endregion