react-native-bundle-discovery 2.2.0-rc.3 → 2.3.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/webpack.js +64 -16
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-bundle-discovery",
3
- "version": "2.2.0-rc.3",
3
+ "version": "2.3.0",
4
4
  "main": "index.js",
5
5
  "repository": "git@github.com:retyui/react-native-bundle-discovery.git",
6
6
  "author": "David <4661784+retyui@users.noreply.github.com>",
package/webpack.js CHANGED
@@ -15,7 +15,7 @@ class BundleDiscoveryPlugin {
15
15
  constructor({ filename, options, enabled } = {}) {
16
16
  this.options = options;
17
17
  this.filename = filename || "metro-stats.json";
18
- this.enabled = enabled || true;
18
+ this.enabled = enabled ?? true;
19
19
  }
20
20
 
21
21
  extractSizesFromJsBundle(statAsset, options) {
@@ -51,6 +51,7 @@ class BundleDiscoveryPlugin {
51
51
  const statsJson = this.formatStat(
52
52
  json,
53
53
  // Parse JS bundle to extract modules sizes
54
+ // WANR: The stats asset list can contain multiple emitted files and is not guaranteed to put the JavaScript bundle first (and can be empty after a failed compilation)
54
55
  this.extractSizesFromJsBundle(json.assets[0], compiler.options),
55
56
  compiler.options,
56
57
  );
@@ -90,6 +91,7 @@ class BundleDiscoveryPlugin {
90
91
  if (parts.length < 2) {
91
92
  return null;
92
93
  }
94
+ // WARN: Won't work with `pnpm's nested layout`
93
95
  const packagePath = parts[1].split(path.sep).filter(Boolean);
94
96
  if (packagePath.length === 0) {
95
97
  return null;
@@ -160,6 +162,10 @@ class BundleDiscoveryPlugin {
160
162
  }
161
163
 
162
164
  formatStat(statsJson, bundleModules, compilerOptions) {
165
+ const modulesDeps = this.buildImportsMapFromReasons(
166
+ statsJson,
167
+ compilerOptions,
168
+ );
163
169
  return {
164
170
  date: statsJson.builtAt || Date.now(),
165
171
  entryPoint: this.getEntryFile(statsJson, compilerOptions.context),
@@ -176,6 +182,9 @@ class BundleDiscoveryPlugin {
176
182
  modules: statsJson.modules
177
183
  .map((mdl) => {
178
184
  if (mdl.type === "runtime modules") {
185
+ if (!bundleModules) {
186
+ return null;
187
+ }
179
188
  const sourceAndOutput = {
180
189
  code: bundleModules.runtimeSrc ?? "",
181
190
  lineCount: bundleModules.runtimeSrc?.split("\n").length ?? 0,
@@ -184,8 +193,9 @@ class BundleDiscoveryPlugin {
184
193
  "utf-8",
185
194
  ),
186
195
  };
196
+
187
197
  return {
188
- path: "__prelude__",
198
+ path: "runtime modules", // Can we rename it?
189
199
  source: sourceAndOutput,
190
200
  output: sourceAndOutput,
191
201
  dependencies: [],
@@ -196,26 +206,64 @@ class BundleDiscoveryPlugin {
196
206
  path: mdl.nameForCondition,
197
207
  source: this.readSource(mdl.nameForCondition),
198
208
  output: this.getModuleOutput(mdl, bundleModules),
199
- dependencies:
200
- mdl.reasons
201
- ?.filter((r) => r.type !== "entry")
202
- .map((reason) => {
203
- return {
204
- absolutePath: path.isAbsolute(reason.resolvedModule)
205
- ? reason.resolvedModule
206
- : path.resolve(
207
- compilerOptions.context,
208
- reason.resolvedModule,
209
- ),
210
- name: reason.userRequest,
211
- };
212
- }) ?? [],
209
+ dependencies: modulesDeps.get(mdl.nameForCondition) ?? [],
213
210
  };
214
211
  })
215
212
  .filter((e) => e !== null),
216
213
  packages: this.getPackages(statsJson),
217
214
  };
218
215
  }
216
+
217
+ buildImportsMapFromReasons(statsJson, compilerOptions) {
218
+ const modules = Array.isArray(statsJson?.modules) ? statsJson.modules : [];
219
+ const importsMap = new Map();
220
+
221
+ const getAbs = (p) => {
222
+ if (!p || typeof p !== "string") return null;
223
+ if (path.isAbsolute(p)) return p;
224
+ return compilerOptions?.context
225
+ ? path.resolve(compilerOptions?.context, p)
226
+ : p;
227
+ };
228
+
229
+ const getModulePath = (m) =>
230
+ m?.path || m?.nameForCondition || m?.identifier || null;
231
+
232
+ for (const depModule of modules) {
233
+ const depAbsolutePath = getAbs(getModulePath(depModule));
234
+ if (!depAbsolutePath) continue;
235
+
236
+ const reasons = Array.isArray(depModule.reasons) ? depModule.reasons : [];
237
+ for (const reason of reasons) {
238
+ if (reason?.type === "entry") continue;
239
+
240
+ // importer (who imports current dep module)
241
+ const importerPath = getAbs(
242
+ reason?.modulePath ||
243
+ reason?.moduleNameForCondition ||
244
+ reason?.resolvedModule ||
245
+ reason?.moduleIdentifier,
246
+ );
247
+ if (!importerPath) continue;
248
+
249
+ if (!importsMap.has(importerPath)) {
250
+ importsMap.set(importerPath, []);
251
+ }
252
+
253
+ const deps = importsMap.get(importerPath);
254
+
255
+ // uniq by absolutePath
256
+ if (!deps.some((d) => d.absolutePath === depAbsolutePath)) {
257
+ deps.push({
258
+ absolutePath: depAbsolutePath,
259
+ name: reason?.userRequest || "",
260
+ });
261
+ }
262
+ }
263
+ }
264
+
265
+ return importsMap;
266
+ }
219
267
  }
220
268
 
221
269
  module.exports = { BundleDiscoveryPlugin };