react-native-bundle-discovery 2.5.0 → 2.7.0-rc.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/README.md CHANGED
@@ -1,73 +1,92 @@
1
1
  # react-native-bundle-discovery
2
2
 
3
- [![react-native-bundle-discovery on npm](https://badgen.net/npm/v/react-native-bundle-discovery)](https://www.npmjs.com/package/react-native-bundle-discovery)
4
- [![react-native-bundle-discovery downloads](https://badgen.net/npm/dm/react-native-bundle-discovery)](https://www.npmtrends.com/react-native-bundle-discovery)
5
-
6
- A simple package that helps developers visualize and analyze the bundle size of React Native apps.
7
- With this tool, you can easily explore your app's codebase, identify large or heavy packages, and inspect the structure of modules and code within your project.
8
-
9
- <img width="800" alt="" src="./assets/img.png" />
10
-
11
- ### Packages:
12
-
13
- - `react-native-bundle-discovery` - simple JS library to generate a JSON report of the bundle.
14
- - `react-native-bundle-discovery-ui` - UI to visualize the bundle report.
15
- - `react-native-bundle-discovery-cli` - CLI to analyze the bundle report.
16
- - `react-native-bundle-discovery-rozenite-plugin` - Rozenite plugin to integrate UI tool to [React Native DevTools](https://reactnative.dev/docs/react-native-devtools).
17
-
18
- ---
19
-
20
- ### Setup:
21
-
22
- There are two ways to install the package:
23
-
24
- 1. As in independent tool (UI + CLI)
25
- 2. Or as a [Rozenite](_rozenite/README.md) plugin (see: [_rozenite/README.md](_rozenite/README.md))
26
-
27
-
28
- > 🚀 If you've migrated to [Re.Pack](https://re-pack.dev/), you can still use this package to analyze 📊 JS bundles 📦 generated by Re.Pack.
3
+ [![npm version](https://badgen.net/npm/v/react-native-bundle-discovery)](https://www.npmjs.com/package/react-native-bundle-discovery)
4
+ [![npm downloads](https://badgen.net/npm/dm/react-native-bundle-discovery)](https://www.npmtrends.com/react-native-bundle-discovery)
5
+ [![license](https://badgen.net/npm/license/react-native-bundle-discovery)](https://www.npmjs.com/package/react-native-bundle-discovery)
6
+
7
+ Visualize and analyze the JS bundle of your React Native app. Find heavy packages, duplicates and deprecated
8
+ dependencies, inspect every module, and catch bundle size regressions in CI.
9
+
10
+ <img width="800" alt="Bundle Discovery UI" src="./assets/img.png" />
11
+
12
+ ## Contents
13
+
14
+ - [Features](#features)
15
+ - [Packages](#packages)
16
+ - [Quick start](#quick-start)
17
+ - [Other setups](#other-setups)
18
+ - [Usage](#usage)
19
+ - [UI](#ui)
20
+ - [CLI](#cli)
21
+ - [Bundle size checks in CI](#bundle-size-checks-in-ci)
22
+ - [API](#api)
23
+ - [`createSerializer`](#createserializeroptions)
24
+ - [`createResolveRequest`](#createresolverequestoptions)
25
+ - [Similar projects](#similar-projects)
26
+ - [Support the project](#support-the-project)
27
+ - [License](#license)
28
+
29
+ ## Features
30
+
31
+ - 📊 Interactive UI to explore packages, modules and their source/bundled code
32
+ - 💡 Optimization recommendations (duplicates, deprecated / outdated / dev-only packages, and more)
33
+ - 🔍 CLI to list the heaviest packages and modules
34
+ - 🆚 Compare two reports and fail CI on bundle size regressions
35
+ - 🧩 Works with Metro, [Re.Pack](./Re.Pack.md) and [React Native DevTools](./packages/rozenite-plugin/README.md) (via Rozenite)
36
+
37
+ ## Packages
38
+
39
+ | Package | What it does | Required |
40
+ | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------- | -------- |
41
+ | `react-native-bundle-discovery` | Generates a JSON report (`metro-stats.json`) of your bundle | ✅ Yes |
42
+ | `react-native-bundle-discovery-ui` | Shows the report in the browser | Optional |
43
+ | `react-native-bundle-discovery-cli` | Analyzes and compares reports in the terminal / CI | Optional |
44
+ | [`react-native-bundle-discovery-rozenite-plugin`](./packages/rozenite-plugin/README.md) | Shows the UI inside [React Native DevTools](https://reactnative.dev/docs/react-native-devtools) | Optional |
45
+
46
+ ## Quick start
47
+
48
+ This setup is for a standard **Metro** project.
49
+ Using Re.Pack or Rozenite? See [Other setups](#other-setups).
50
+
51
+ > [!TIP]
52
+ > **Using an AI coding agent?** Skip the manual steps below. Point your agent (Claude Code, Cursor, Codex, etc.)
53
+ > at the [`setup-react-native-bundle-discovery`](./skills/setup-react-native-bundle-discovery/SKILL.md) skill.
54
+ > It installs the package and sets up Metro or Re.Pack for you:
29
55
  >
30
- > 💡 Learn more: 📖 [Re.Pack.md](./Re.Pack.md)
56
+ > ```bash
57
+ > npx skills add retyui/react-native-bundle-discovery
58
+ > ```
31
59
 
32
- #### 1. Install (independent tool)
60
+ ### 1. Install
33
61
 
34
62
  ```bash
35
- yarn add -D react-native-bundle-discovery # required for generating the JSON report
36
- yarn add -D react-native-bundle-discovery-ui # optional: used for visualizing the report in the browser
37
- yarn add -D react-native-bundle-discovery-cli # optional: used for analysis of the report in the CLI
63
+ yarn add -D react-native-bundle-discovery # required: generates the report
64
+ yarn add -D react-native-bundle-discovery-ui # optional: browser UI
65
+ yarn add -D react-native-bundle-discovery-cli # optional: CLI
38
66
  ```
39
67
 
40
- Add to your `metro.config.js`:
68
+ ### 2. Configure Metro
41
69
 
42
70
  ```diff
43
71
  // metro.config.js
44
- const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
45
- +const {createSerializer} = require('react-native-bundle-discovery');
46
-
47
- +const mySerializer = createSerializer({
48
- + includeCode: true, // Useful if you want to compare source/bundle code (but a report file will be larger)
49
- + projectRoot: __dirname,
50
- + //^^^ ⚠️ WARNING: In a monorepo setup, this should point to the monorepo root,
51
- + // not the individual package directory.
52
- +});
72
+ const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
73
+ +const { createSerializer } = require('react-native-bundle-discovery');
53
74
 
54
75
  -const config = {};
55
76
  +const config = {
56
- serializer: { customSerializer: mySerializer },
57
- };
77
+ + serializer: {
78
+ + customSerializer: createSerializer({
79
+ + projectRoot: __dirname, // ⚠️ In a monorepo, use the monorepo root instead
80
+ + }),
81
+ + },
82
+ +};
58
83
 
59
84
  module.exports = mergeConfig(getDefaultConfig(__dirname), config);
60
85
  ```
61
86
 
62
- #### 2. Install (as plugin for Rozenite)
63
-
64
- See: [_rozenite/README.md](_rozenite/README.md)
65
-
66
- ---
67
-
68
- ### 3. Build the app
87
+ See all options in [`createSerializer`](#createserializeroptions).
69
88
 
70
- For example, for iOS you can run the following command, and it will generate the `metro-stats.json` file in the root of your project:
89
+ ### 3. Build a release bundle
71
90
 
72
91
  ```bash
73
92
  npx react-native bundle \
@@ -78,97 +97,153 @@ npx react-native bundle \
78
97
  --assets-dest ios/assets
79
98
  ```
80
99
 
81
- ### 4. Commands
100
+ This writes `metro-stats.json` to your project root.
101
+
102
+ ### 4. Explore the report
103
+
104
+ ```bash
105
+ npx react-native-bundle-discovery-ui metro-stats.json # open in the browser
106
+ npx react-native-bundle-discovery-cli metro-stats.json # get recommendations in the terminal
107
+ ```
82
108
 
83
- #### CLI package
109
+ ## Other setups
84
110
 
85
- You need to install `react-native-bundle-discovery-cli`
111
+ | Setup | Guide |
112
+ | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
113
+ | Re.Pack (Rspack / Webpack) | [Re.Pack.md](./Re.Pack.md) |
114
+ | React Native DevTools | [Rozenite plugin](./packages/rozenite-plugin/README.md) |
115
+ | AI coding agent | Point your agent at the [`setup-react-native-bundle-discovery`](./skills/setup-react-native-bundle-discovery/SKILL.md) skill |
116
+
117
+ ## Usage
118
+
119
+ ### UI
120
+
121
+ Requires `react-native-bundle-discovery-ui`.
122
+
123
+ ```bash
124
+ # Start a local server (default port: 8079)
125
+ npx react-native-bundle-discovery-ui metro-stats.json [--port <port>]
126
+
127
+ # Build a static HTML report (default output: .bundle-discovery)
128
+ npx react-native-bundle-discovery-ui build metro-stats.json [--output <path>]
129
+ ```
130
+
131
+ ### CLI
132
+
133
+ Requires `react-native-bundle-discovery-cli`. Run any command with `--help` to see all options.
134
+
135
+ | Command | Description |
136
+ | ---------- | --------------------------------------------- |
137
+ | _(none)_ | Show recommended optimizations for the bundle |
138
+ | `packages` | List all packages in the bundle |
139
+ | `modules` | List the heaviest modules |
140
+ | `compare` | Compare two reports |
86
141
 
87
142
  ```bash
88
- # Display all recommended optimizations for the bundle
143
+ # Recommended optimizations
89
144
  npx react-native-bundle-discovery-cli metro-stats.json
90
145
 
91
- # Display all packages in the bundle report
146
+ # All packages
92
147
  npx react-native-bundle-discovery-cli packages metro-stats.json [--sort size|name] [--format json|table|default]
93
148
 
94
- # Display the heaviest modules in the bundle report (default limit: 50, --limit 0 shows all)
95
- # --filter accepts plain text (case-insensitive) or a regexp: --filter '/\.json/i'
149
+ # Heaviest modules (default --limit: 50, use 0 to show all)
150
+ # --filter accepts plain text (case-insensitive) or a regexp, e.g. --filter '/\.json/i'
96
151
  npx react-native-bundle-discovery-cli modules metro-stats.json [--limit 50] [--filter <text|/regexp/>] [--sort size|name] [--format json|table|default]
152
+
153
+ # Diff two reports: total size, added/removed/changed modules and packages,
154
+ # version changes, new duplicates and new deprecated packages
155
+ npx react-native-bundle-discovery-cli compare --before main-stats.json --after pr-stats.json [--limit 50] [--format json|markdown|default]
97
156
  ```
98
157
 
99
- #### UI package
158
+ ### Bundle size checks in CI
100
159
 
101
- You need to install `react-native-bundle-discovery-ui`
160
+ `compare` exits with code `1` when any check fails:
102
161
 
103
- ```bash
104
- # Start server to view the report in the browser (default port: 8079)
105
- npx react-native-bundle-discovery-ui metro-stats.json [--port <port>]
162
+ | Option | Fails when | Example |
163
+ | -------------------- | ------------------------------------------------------------- | ------------------------------- |
164
+ | `--fail-on-increase` | The bundle grows more than the limit (bytes or % of "before") | `50KB`, `0.5MB`, `51200`, `5%` |
165
+ | `--max-size` | The "after" bundle is bigger than the limit | `3MB` |
166
+ | `--fail-on` | New duplicate and/or deprecated packages appear | `new-duplicates,new-deprecated` |
106
167
 
107
- # Build the report into a static HTML file
108
- npx react-native-bundle-discovery-ui build metro-stats.json
168
+ ```bash
169
+ npx react-native-bundle-discovery-cli compare --before main-stats.json --after pr-stats.json \
170
+ --fail-on-increase 50KB \
171
+ --max-size 3MB \
172
+ --fail-on new-duplicates,new-deprecated
109
173
  ```
110
174
 
111
- ---
175
+ **GitHub Actions** works out of the box: the markdown report is added to the job summary and failed checks
176
+ are shown as error annotations.
177
+
178
+ ```yaml
179
+ - run: npx react-native-bundle-discovery-cli compare --before main-stats.json --after pr-stats.json --fail-on-increase 5%
180
+ ```
112
181
 
113
- ### `react-native-bundle-discovery` JS API
182
+ To post the report as a PR comment, use `--format markdown`.
114
183
 
115
- #### `createSerializer(options: Options)`
184
+ ## API
116
185
 
117
- | Prop | Default value | Description |
118
- | ---------------------- | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
119
- | serializer: Function | Default serializer | A custom serializer function. If not provided, a default serializer is used. |
120
- | projectRoot: string | Required | The root directory of the project. ⚠️ In a monorepo setup, this should point to the monorepo root, not the individual package directory. |
121
- | outputJsonPath: string | `<root>/metro-stats.json` | The path where the JSON report will be saved. Defaults to `metro-stats.json` in project root. |
122
- | includeCode: boolean | `true` | Whether to include the source and output code in the JSON report. |
186
+ Exported from `react-native-bundle-discovery`.
123
187
 
124
- **⚠️ Be cautious sharing reports with `includeCode` enabled**
188
+ ### `createSerializer(options)`
125
189
 
126
- Enabling this option significantly increases report size and **embeds the source code** of your assets.
190
+ Creates a Metro serializer that writes the JSON report. Use it as `serializer.customSerializer` (see [Quick start](#2-configure-metro)).
127
191
 
128
- If your code is proprietary 🔒, share these reports responsibly 🤝!
192
+ | Option | Type | Default | Description |
193
+ | ----------------------- | ---------- | -------------------------------- | ----------------------------------------------------------------------------------------- |
194
+ | `projectRoot` | `string` | **Required** | Project root. ⚠️ In a monorepo, use the monorepo root, not the app package directory. |
195
+ | `outputJsonPath` | `string` | `<projectRoot>/metro-stats.json` | Where to save the report. |
196
+ | `includeCode` | `boolean` | `true` | Include source and bundled code of each module in the report (larger file). |
197
+ | `includeEnvs` | `string[]` | `[]` | Names of environment variables to include in the report. |
198
+ | `fetchPackagesMetadata` | `boolean` | `true` | Fetch package metadata (publish date, deprecation, latest version) from the npm registry. |
199
+ | `silent` | `boolean` | `false` | Disable log output. |
200
+ | `serializer` | `Function` | Metro default serializer | Custom serializer to wrap. |
129
201
 
130
- ---
202
+ > [!WARNING]
203
+ > With `includeCode: true` (the default) the report **contains your source code**.
204
+ > If your code is proprietary, be careful who you share the report with.
131
205
 
132
- ### `createResolveRequest(options: ResolveRequestOptions)`
206
+ ### `createResolveRequest(options)`
133
207
 
134
- | Prop | Default value | Description |
135
- | ------------------------------ | ------------- | ----------------------------------------------------------------------------------------------------------------------------- |
136
- | removePromisePolyfill: boolean | `false` | Remove the Promise polyfill as Hermes provide own impl. (issue: [#57702](https://github.com/react/react-native/issues/57702)) |
137
- | removeUTFSequence: boolean | `false` | Remove useless undocumented RN module. |
208
+ Creates a Metro `resolveRequest` that removes unnecessary React Native modules from **release** bundles
209
+ (dev builds are not affected). The CLI recommends these options when they apply to your bundle.
138
210
 
139
- Helper that creates a custom resolve request function to filter out unnecessary modules from the bundle.
140
- You can get recommendations during the analysis of the bundle report using the CLI tool.
211
+ | Option | Type | Default | Description |
212
+ | ------------------- | --------- | ------- | -------------------------------------------------------------------------------- |
213
+ | `removeUTFSequence` | `boolean` | `false` | Remove the unused `react-native/Libraries/UTFSequence.js` module. |
214
+ | `removeNewRenderer` | `boolean` | `false` | Remove the Fabric renderer. Enable only if the New Architecture is **disabled**. |
141
215
 
142
216
  ```js
143
217
  // metro.config.js
144
218
  const { createResolveRequest } = require("react-native-bundle-discovery");
145
- const resolveRequest = createResolveRequest({
146
- removePromisePolyfill: true,
147
- removeUTFSequence: true,
148
- });
219
+
149
220
  const config = {
150
221
  resolver: {
151
- resolveRequest,
222
+ resolveRequest: createResolveRequest({
223
+ removeUTFSequence: true,
224
+ }),
152
225
  },
153
226
  };
154
227
  ```
155
228
 
156
- ### Financial Contributors
229
+ ## Similar projects
157
230
 
158
- Become a financial contributor at [OpenCollective](https://opencollective.com/react-native-bundle-discovery) or [GitHub Sponsors](https://github.com/sponsors/retyui)
231
+ - [expo-atlas](https://github.com/expo/atlas)
232
+ - [expo-atlas-without-expo](https://github.com/v3ron/expo-atlas-without-expo)
233
+ - [react-native-bundle-visualizer](https://github.com/callstack/react-native-bundle-visualizer)
234
+ - [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer)
235
+ - [bundle-stats](https://github.com/relative-ci/bundle-stats/tree/master/packages/cli#readme)
236
+ - [statoscope](https://github.com/statoscope/statoscope)
159
237
 
160
- ### Other
238
+ Built with [Discovery.js](https://github.com/discoveryjs/discovery)
239
+ ([views showcase](https://discoveryjs.github.io/discovery/#views-showcase),
240
+ [Jora syntax](https://discoveryjs.github.io/jora/#article:jora-syntax-operators)).
161
241
 
162
- **Similar projects:**
242
+ ## Support the project
163
243
 
164
- - [expo-atlas](https://github.com/expo/atlas) [![expo-atlas downloads](https://badgen.net/npm/dm/expo-atlas)](https://www.npmtrends.com/expo-atlas) [![expo-atlas install size](https://packagephobia.com/badge?p=expo-atlas)](https://packagephobia.com/result?p=expo-atlas)
165
- - [expo-atlas-without-expo](https://github.com/v3ron/expo-atlas-without-expo) [![expo-atlas-without-expo downloads](https://badgen.net/npm/dm/expo-atlas-without-expo)](https://www.npmtrends.com/expo-atlas-without-expo) [![expo-atlas-without-expo install size](https://packagephobia.com/badge?p=expo-atlas-without-expo)](https://packagephobia.com/result?p=expo-atlas-without-expo)
166
- - [react-native-bundle-visualizer](https://github.com/callstack/react-native-bundle-visualizer) [![react-native-bundle-visualizer downloads](https://badgen.net/npm/dm/react-native-bundle-visualizer)](https://www.npmtrends.com/react-native-bundle-visualizer)[![react-native-bundle-visualizer install size](https://packagephobia.com/badge?p=react-native-bundle-visualizer)](https://packagephobia.com/result?p=react-native-bundle-visualizer)
167
- - [webpack-bundle-analyzer](https://github.com/webpack-contrib/webpack-bundle-analyzer) [![webpack-bundle-analyzer downloads](https://badgen.net/npm/dm/webpack-bundle-analyzer)](https://www.npmtrends.com/webpack-bundle-analyzer)[![webpack-bundle-analyzer install size](https://packagephobia.com/badge?p=webpack-bundle-analyzer)](https://packagephobia.com/result?p=webpack-bundle-analyzer)
168
- - [bundle-stats](https://github.com/relative-ci/bundle-stats/tree/master/packages/cli#readme) [![bundle-stats downloads](https://badgen.net/npm/dm/bundle-stats)](https://www.npmtrends.com/bundle-stats)[![bundle-stats install size](https://packagephobia.com/badge?p=bundle-stats)](https://packagephobia.com/result?p=bundle-stats)
169
- - [statoscope](https://github.com/statoscope/statoscope) [![@statoscope/cli downloads](https://badgen.net/npm/dm/@statoscope/cli)](https://www.npmtrends.com/@statoscope/cli)[![@statoscope/cli install size](https://packagephobia.com/badge?p=@statoscope/cli)](https://packagephobia.com/result?p=@statoscope/cli)
244
+ Become a financial contributor on [OpenCollective](https://opencollective.com/react-native-bundle-discovery)
245
+ or [GitHub Sponsors](https://github.com/sponsors/retyui).
170
246
 
171
- **Built using [Discovery.js](https://github.com/discoveryjs/discovery):**
247
+ ## License
172
248
 
173
- - Build blocks for pages: https://discoveryjs.github.io/discovery/#views-showcase
174
- - Jora syntax: https://discoveryjs.github.io/jora/#article:jora-syntax-operators
249
+ MIT
@@ -0,0 +1,262 @@
1
+ import { Buffer } from "node:buffer";
2
+ //#region src/types.d.ts
3
+ /**
4
+ * Shape of the `metro-stats.json` report.
5
+ * Mirrors the report types of the (private) monorepo `shared` package; kept local so the
6
+ * published `.d.ts` is self-contained.
7
+ */
8
+ interface PackageMetadata {
9
+ createdAt: string | null;
10
+ deprecated: string | false;
11
+ isLatest: boolean;
12
+ latestVersion: string | null;
13
+ }
14
+ interface SizeInfo {
15
+ sizeInBytes: number;
16
+ }
17
+ interface CodeInfo extends SizeInfo {
18
+ code: string;
19
+ lineCount: number;
20
+ }
21
+ interface ReportPackage {
22
+ name: string;
23
+ absolutePath: string;
24
+ version: string;
25
+ metadata?: PackageMetadata | null;
26
+ }
27
+ interface ReportModuleDependency {
28
+ absolutePath: string;
29
+ name: string;
30
+ }
31
+ interface ReportModule {
32
+ path: string;
33
+ source: CodeInfo;
34
+ output: CodeInfo;
35
+ dependencies: ReportModuleDependency[];
36
+ }
37
+ interface TransformOptions {
38
+ customTransformOptions?: Record<string, unknown>;
39
+ dev: boolean;
40
+ minify: boolean;
41
+ platform: string;
42
+ type?: string;
43
+ unstable_transformProfile?: string;
44
+ [key: string]: unknown;
45
+ }
46
+ //#endregion
47
+ //#region src/parseUtils.d.ts
48
+ type Modules = Record<string, string>;
49
+ interface ParseBundleOptions {
50
+ sourceType?: "script" | "module";
51
+ expectedModuleIds?: (string | number)[];
52
+ }
53
+ declare function parseBundle(bundlePath: string, opts?: ParseBundleOptions): {
54
+ modules: Modules;
55
+ src: string;
56
+ runtimeSrc: string;
57
+ };
58
+ //#endregion
59
+ //#region src/webpack.d.ts
60
+ /** Options passed to `stats.toJson()` (https://webpack.js.org/configuration/stats/) */
61
+ type StatsOptions = Record<string, unknown>;
62
+ /** Minimal shape of the (normalized) Webpack/Rspack compiler options used by the plugin */
63
+ interface CompilerOptions {
64
+ context?: string;
65
+ mode?: string;
66
+ name?: string;
67
+ output: {
68
+ path?: string;
69
+ };
70
+ optimization?: {
71
+ minimize?: boolean;
72
+ };
73
+ }
74
+ /** Minimal shape of a Webpack/Rspack `Stats` object */
75
+ interface Stats {
76
+ toJson(options: StatsOptions): unknown;
77
+ }
78
+ /** Minimal shape of a Webpack/Rspack `Compiler` */
79
+ interface Compiler {
80
+ options: CompilerOptions;
81
+ hooks: {
82
+ done: {
83
+ tap(name: string, callback: (stats: Stats) => void): void;
84
+ };
85
+ };
86
+ }
87
+ interface StatsReason {
88
+ type?: string;
89
+ modulePath?: string;
90
+ moduleNameForCondition?: string;
91
+ resolvedModule?: string;
92
+ moduleIdentifier?: string;
93
+ userRequest?: string;
94
+ }
95
+ interface StatsModule {
96
+ id?: string | number;
97
+ type?: string;
98
+ path?: string;
99
+ identifier?: string;
100
+ nameForCondition?: string;
101
+ source?: string;
102
+ size?: number;
103
+ reasons?: StatsReason[];
104
+ }
105
+ interface StatsAsset {
106
+ name: string;
107
+ info: {
108
+ javascriptModule?: boolean;
109
+ };
110
+ }
111
+ interface StatsJson {
112
+ builtAt?: number;
113
+ assets: StatsAsset[];
114
+ modules: StatsModule[];
115
+ }
116
+ type ParsedBundle = ReturnType<typeof parseBundle>;
117
+ interface WebpackReport {
118
+ kind: "webpack";
119
+ date: number;
120
+ entryPoint: string;
121
+ rootFolder: string;
122
+ transformOptions: TransformOptions;
123
+ modules: ReportModule[];
124
+ packages: ReportPackage[];
125
+ }
126
+ interface BundleDiscoveryPluginOptions {
127
+ /** Output file name (resolved against the compiler `context`). Defaults to `"metro-stats.json"`. */
128
+ filename?: string;
129
+ /** Extra options passed to `stats.toJson()`. */
130
+ options?: StatsOptions;
131
+ /** Whether the plugin is enabled. Defaults to `true`. */
132
+ enabled?: boolean;
133
+ /** Whether to fetch packages metadata (publish date, deprecation, latest version) from the npm registry. Defaults to `true`. */
134
+ fetchPackagesMetadata?: boolean;
135
+ }
136
+ /**
137
+ * Simple Webpack/Rspack plugin
138
+ * to adapt stats object https://webpack.js.org/api/stats/
139
+ * to metro-stats.json format used by `react-native-bundle-discovery`
140
+ */
141
+ export declare class BundleDiscoveryPlugin {
142
+ options: StatsOptions | undefined;
143
+ filename: string;
144
+ enabled: boolean;
145
+ fetchPackagesMetadata: boolean;
146
+ constructor({ filename, options, enabled, fetchPackagesMetadata }?: BundleDiscoveryPluginOptions);
147
+ extractSizesFromJsBundle(statAsset: StatsAsset, options: CompilerOptions): ParsedBundle | null;
148
+ apply(compiler: Compiler): void;
149
+ writeReport(statsJson: WebpackReport, outputPath: string): Promise<void>;
150
+ readSource(filePath: string): CodeInfo;
151
+ getPkgVersionFromPath(path: string): string | null;
152
+ getPackages(statsJson: StatsJson): ReportPackage[];
153
+ getEntryFile(statsJson: StatsJson, rootFolder: string): string;
154
+ getModuleOutput(mdl: StatsModule, bundleModules: ParsedBundle | null): CodeInfo;
155
+ formatStat(statsJson: StatsJson, bundleModules: ParsedBundle | null, compilerOptions: CompilerOptions): WebpackReport;
156
+ buildImportsMapFromReasons(statsJson: StatsJson, compilerOptions: CompilerOptions): Map<string, ReportModuleDependency[]>;
157
+ findCommonRoot(paths: string[]): string;
158
+ }
159
+ //#endregion
160
+ //#region src/index.d.ts
161
+ /** Minimal shape of a Metro module (`Module` from `metro/src/DeltaBundler/types`) */
162
+ interface MetroModule {
163
+ path: string;
164
+ getSource(): Buffer;
165
+ output: ReadonlyArray<{
166
+ data: {
167
+ code: string;
168
+ lineCount: number;
169
+ };
170
+ }>;
171
+ dependencies?: Map<string, {
172
+ absolutePath?: string | null;
173
+ data: {
174
+ name: string;
175
+ };
176
+ }>;
177
+ }
178
+ /** Minimal shape of a Metro graph (`ReadOnlyGraph` from `metro/src/DeltaBundler/types`) */
179
+ interface MetroGraph {
180
+ dependencies: Map<string, MetroModule>;
181
+ transformOptions: TransformOptions;
182
+ }
183
+ /** Minimal shape of Metro serializer options */
184
+ interface MetroSerializerOptions {
185
+ processModuleFilter?: (module: MetroModule) => boolean;
186
+ sentryBundleCallback?: (bundle: unknown) => unknown;
187
+ [key: string]: unknown;
188
+ }
189
+ type MetroSerializerResult = string | {
190
+ code: string;
191
+ map: string;
192
+ } | Promise<string | {
193
+ code: string;
194
+ map: string;
195
+ }>;
196
+ type MetroSerializer = (entryPoint: string, preModules: ReadonlyArray<MetroModule>, graph: MetroGraph, options: MetroSerializerOptions) => MetroSerializerResult;
197
+ interface CreateSerializerOptions {
198
+ /** A custom serializer function. If not provided, a default serializer is used. */
199
+ serializer?: MetroSerializer;
200
+ /** The root directory of the project. Must exist. */
201
+ projectRoot: string;
202
+ /** The path where the JSON report will be saved. Defaults to "metro-stats.json" in the project root. */
203
+ outputJsonPath?: string;
204
+ /** Whether to include the source and output code in the JSON report. Defaults to `true`. */
205
+ includeCode?: boolean;
206
+ /** Whether to suppress log messages. Defaults to `false`. */
207
+ silent?: boolean;
208
+ /** A list of environment variable names to include in the JSON report. Defaults to `[]`. */
209
+ includeEnvs?: string[];
210
+ /** Whether to fetch packages metadata (publish date, deprecation, latest version) from the npm registry. Defaults to `true`. */
211
+ fetchPackagesMetadata?: boolean;
212
+ }
213
+ /**
214
+ * Creates a custom serializer function for Metro bundler, which generates a JSON report
215
+ * and optionally modifies the serialization process.
216
+ *
217
+ * @param options - Configuration options for the serializer.
218
+ * @returns A custom serializer function to be used by Metro.
219
+ * @throws Throws an error if the project root does not exist.
220
+ */
221
+ declare function createSerializer({ serializer, projectRoot, outputJsonPath, includeCode, silent, includeEnvs, fetchPackagesMetadata }?: CreateSerializerOptions): MetroSerializer;
222
+ /** Minimal shape of a Metro resolution result */
223
+ type MetroResolution = {
224
+ type: string;
225
+ filePath?: string;
226
+ };
227
+ /** Minimal shape of a Metro resolution context */
228
+ interface MetroResolutionContext {
229
+ dev: boolean;
230
+ resolveRequest(context: MetroResolutionContext, moduleName: string, platform: string | null): MetroResolution;
231
+ }
232
+ /**
233
+ * Usage:
234
+ *
235
+ * ```js
236
+ * // metro.config.js
237
+ * const { createResolveRequest } = require("react-native-bundle-discovery");
238
+ * const resolveRequest = createResolveRequest({
239
+ * removePromisePolyfill: true,
240
+ * });
241
+ * const config = {
242
+ * resolver: {
243
+ * resolveRequest,
244
+ * },
245
+ * };
246
+ * ```
247
+ */
248
+ declare const createResolveRequest: ({ removeNewRenderer, removeUTFSequence }?: {
249
+ removeNewRenderer?: boolean;
250
+ removeUTFSequence?: boolean;
251
+ }) => (context: MetroResolutionContext, moduleName: string, platform: string | null) => MetroResolution;
252
+ /**
253
+ * @deprecated Use `createResolveRequest` instead.
254
+ */
255
+ declare const createProcessModuleFilter: ({ removePromisePolyfill, removeUTFSequence }?: {
256
+ removePromisePolyfill?: boolean;
257
+ removeUTFSequence?: boolean;
258
+ }) => (module: {
259
+ path: string;
260
+ }) => boolean;
261
+ //#endregion
262
+ export { createProcessModuleFilter, createResolveRequest, createSerializer };