react-native-inapp-inspector 1.1.23 → 1.1.24
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/dist/commonjs/components/Inspector/BundleTab.js +37 -0
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/customHooks/bundleAnalyzer.d.ts +1 -1
- package/dist/commonjs/customHooks/bundleAnalyzer.js +95 -28
- package/dist/commonjs/i18n/locales/en.json +2 -0
- package/dist/esm/components/Inspector/BundleTab.js +37 -0
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/customHooks/bundleAnalyzer.d.ts +1 -1
- package/dist/esm/customHooks/bundleAnalyzer.js +96 -29
- package/dist/esm/i18n/locales/en.json +2 -0
- package/package.json +1 -1
|
@@ -762,6 +762,21 @@ const BundleTab = react_1.default.memo(() => {
|
|
|
762
762
|
</react_native_1.View>
|
|
763
763
|
</react_native_1.View>
|
|
764
764
|
|
|
765
|
+
{/* Live analysis unavailable warning */}
|
|
766
|
+
{analysis && !analysis.isLive && (<react_native_1.View style={bundleStyles.liveWarningCard}>
|
|
767
|
+
<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6, flex: 1 }}>
|
|
768
|
+
<NetworkIcons_1.CircleAlertIcon color={AppColors_1.AppColors.amber700} size={16}/>
|
|
769
|
+
<react_native_1.View style={{ flex: 1 }}>
|
|
770
|
+
<react_native_1.Text style={bundleStyles.liveWarningTitle}>
|
|
771
|
+
{t('bundle.liveAnalysisUnavailable')}
|
|
772
|
+
</react_native_1.Text>
|
|
773
|
+
<react_native_1.Text style={bundleStyles.liveWarningDesc}>
|
|
774
|
+
{t('bundle.liveAnalysisUnavailableSub')}
|
|
775
|
+
</react_native_1.Text>
|
|
776
|
+
</react_native_1.View>
|
|
777
|
+
</react_native_1.View>
|
|
778
|
+
</react_native_1.View>)}
|
|
779
|
+
|
|
765
780
|
{/* Development Bundle Split-Up (derived from the real running bundle) */}
|
|
766
781
|
{analysis && (<react_native_1.View style={bundleStyles.sectionCard}>
|
|
767
782
|
<react_native_1.View style={bundleStyles.sectionHeaderRow}>
|
|
@@ -2233,6 +2248,28 @@ const bundleStyles = react_native_1.StyleSheet.create({
|
|
|
2233
2248
|
borderWidth: 1,
|
|
2234
2249
|
borderColor: AppColors_1.AppColors.errorBorder,
|
|
2235
2250
|
},
|
|
2251
|
+
liveWarningCard: {
|
|
2252
|
+
flexDirection: 'row',
|
|
2253
|
+
alignItems: 'center',
|
|
2254
|
+
backgroundColor: AppColors_1.AppColors.amber100,
|
|
2255
|
+
borderWidth: 1,
|
|
2256
|
+
borderColor: AppColors_1.AppColors.amber200,
|
|
2257
|
+
borderRadius: 10,
|
|
2258
|
+
padding: 12,
|
|
2259
|
+
marginBottom: 12,
|
|
2260
|
+
},
|
|
2261
|
+
liveWarningTitle: {
|
|
2262
|
+
fontFamily: AppFonts_1.AppFonts.interBold,
|
|
2263
|
+
fontSize: 12,
|
|
2264
|
+
color: AppColors_1.AppColors.amber800Warm,
|
|
2265
|
+
marginBottom: 2,
|
|
2266
|
+
},
|
|
2267
|
+
liveWarningDesc: {
|
|
2268
|
+
fontFamily: AppFonts_1.AppFonts.interRegular,
|
|
2269
|
+
fontSize: 10.5,
|
|
2270
|
+
lineHeight: 14,
|
|
2271
|
+
color: AppColors_1.AppColors.amber800Warm,
|
|
2272
|
+
},
|
|
2236
2273
|
adviceBadge: {
|
|
2237
2274
|
paddingHorizontal: 8,
|
|
2238
2275
|
paddingVertical: 4,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const LIB_VERSION = "1.1.
|
|
1
|
+
export declare const LIB_VERSION = "1.1.24";
|
|
@@ -3,4 +3,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.LIB_VERSION = void 0;
|
|
4
4
|
// AUTO-GENERATED FILE — do not edit by hand.
|
|
5
5
|
// Regenerated from package.json on every build by scripts/gen-version.js.
|
|
6
|
-
exports.LIB_VERSION = '1.1.
|
|
6
|
+
exports.LIB_VERSION = '1.1.24';
|
|
@@ -107,7 +107,7 @@ export declare const getHostScriptURL: () => string;
|
|
|
107
107
|
/**
|
|
108
108
|
* Parses raw Metro bundle source code to discover real modules and packages in the host app.
|
|
109
109
|
*/
|
|
110
|
-
export declare const parseBundleSource: (bundleText: string, totalBytes: number, scriptURL: string) => HostBundleAnalysisResult;
|
|
110
|
+
export declare const parseBundleSource: (bundleText: string, totalBytes: number, scriptURL: string, isLive?: boolean) => HostBundleAnalysisResult;
|
|
111
111
|
/**
|
|
112
112
|
* Automatically fetch and analyze the real running bundle for the host app.
|
|
113
113
|
*/
|
|
@@ -15,20 +15,88 @@ const react_native_1 = require("react-native");
|
|
|
15
15
|
let cachedAnalysis = null;
|
|
16
16
|
let isAnalyzing = false;
|
|
17
17
|
const subscribers = [];
|
|
18
|
+
const getSourceCodeModule = () => {
|
|
19
|
+
try {
|
|
20
|
+
const legacy = react_native_1.NativeModules?.SourceCode;
|
|
21
|
+
if (legacy && typeof legacy.scriptURL === 'string' && legacy.scriptURL.length > 0) {
|
|
22
|
+
return legacy;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch { }
|
|
26
|
+
try {
|
|
27
|
+
const turbo = react_native_1.TurboModuleRegistry?.get?.('SourceCode');
|
|
28
|
+
const constants = turbo?.getConstants?.();
|
|
29
|
+
const scriptURL = turbo?.scriptURL || constants?.scriptURL;
|
|
30
|
+
if (typeof scriptURL === 'string' && scriptURL.length > 0) {
|
|
31
|
+
return { scriptURL };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch { }
|
|
35
|
+
return null;
|
|
36
|
+
};
|
|
18
37
|
const getHostScriptURL = () => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
38
|
+
// 1. NativeModules.SourceCode (bridged) or SourceCode TurboModule (bridgeless / new arch)
|
|
39
|
+
const scriptURL = getSourceCodeModule()?.scriptURL;
|
|
40
|
+
if (typeof scriptURL === 'string' && scriptURL.length > 0) {
|
|
41
|
+
return scriptURL;
|
|
22
42
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
43
|
+
// 2. Android legacy: PlatformConstants.serverHost -> "localhost:8082"
|
|
44
|
+
try {
|
|
45
|
+
const serverHost = react_native_1.NativeModules?.PlatformConstants?.serverHost;
|
|
46
|
+
if (typeof serverHost === 'string' && serverHost.length > 0) {
|
|
47
|
+
return `http://${serverHost}/index.bundle?platform=${react_native_1.Platform.OS}&dev=true`;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch { }
|
|
51
|
+
return '';
|
|
26
52
|
};
|
|
27
53
|
exports.getHostScriptURL = getHostScriptURL;
|
|
54
|
+
const DEV_SERVER_PORTS = [8081, 8082, 8083, 8084, 8090, 8080, 19000];
|
|
55
|
+
const buildProbeUrls = (scriptURL) => {
|
|
56
|
+
const urls = [];
|
|
57
|
+
if (typeof scriptURL === 'string' && scriptURL.startsWith('http')) {
|
|
58
|
+
urls.push(scriptURL);
|
|
59
|
+
}
|
|
60
|
+
const portMatch = typeof scriptURL === 'string' ? scriptURL.match(/:(\d{2,5})/) : null;
|
|
61
|
+
const ports = portMatch ? [parseInt(portMatch[1], 10)] : DEV_SERVER_PORTS;
|
|
62
|
+
const hosts = react_native_1.Platform.OS === 'android'
|
|
63
|
+
? ['localhost', '127.0.0.1', '10.0.2.2']
|
|
64
|
+
: ['localhost', '127.0.0.1'];
|
|
65
|
+
for (const host of hosts) {
|
|
66
|
+
for (const port of ports) {
|
|
67
|
+
urls.push(`http://${host}:${port}/index.bundle?platform=${react_native_1.Platform.OS}&dev=true`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return Array.from(new Set(urls));
|
|
71
|
+
};
|
|
72
|
+
const fetchWithTimeout = async (url, timeoutMs) => {
|
|
73
|
+
try {
|
|
74
|
+
const controller = new AbortController();
|
|
75
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
76
|
+
try {
|
|
77
|
+
const res = await fetch(url, { signal: controller.signal });
|
|
78
|
+
if (!res.ok)
|
|
79
|
+
return { ok: false };
|
|
80
|
+
const contentLength = res.headers.get('content-length');
|
|
81
|
+
const text = await res.text();
|
|
82
|
+
return {
|
|
83
|
+
ok: true,
|
|
84
|
+
text,
|
|
85
|
+
bytes: contentLength ? parseInt(contentLength, 10) || text.length : text.length,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
clearTimeout(timer);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return { ok: false };
|
|
94
|
+
}
|
|
95
|
+
};
|
|
28
96
|
/**
|
|
29
97
|
* Parses raw Metro bundle source code to discover real modules and packages in the host app.
|
|
30
98
|
*/
|
|
31
|
-
const parseBundleSource = (bundleText, totalBytes, scriptURL) => {
|
|
99
|
+
const parseBundleSource = (bundleText, totalBytes, scriptURL, isLive = true) => {
|
|
32
100
|
const isHermes = Boolean(globalThis.HermesInternal);
|
|
33
101
|
const totalDevMb = Number((totalBytes / (1024 * 1024)).toFixed(2));
|
|
34
102
|
const totalDevKb = Math.round(totalBytes / 1024);
|
|
@@ -451,7 +519,7 @@ const parseBundleSource = (bundleText, totalBytes, scriptURL) => {
|
|
|
451
519
|
},
|
|
452
520
|
];
|
|
453
521
|
return {
|
|
454
|
-
isLive
|
|
522
|
+
isLive,
|
|
455
523
|
scriptURL,
|
|
456
524
|
totalDevBytes: totalBytes,
|
|
457
525
|
totalDevMb,
|
|
@@ -526,30 +594,29 @@ const analyzeHostAppBundle = async () => {
|
|
|
526
594
|
}
|
|
527
595
|
isAnalyzing = true;
|
|
528
596
|
const scriptURL = (0, exports.getHostScriptURL)();
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
byteLength = byteLength || bundleText.length;
|
|
539
|
-
const result = (0, exports.parseBundleSource)(bundleText, byteLength, scriptURL);
|
|
540
|
-
cachedAnalysis = result;
|
|
541
|
-
isAnalyzing = false;
|
|
542
|
-
subscribers.forEach(cb => cb(result));
|
|
543
|
-
subscribers.length = 0;
|
|
544
|
-
return result;
|
|
597
|
+
// Probe candidate dev-server URLs until one serves the JS bundle
|
|
598
|
+
let fetched = null;
|
|
599
|
+
let fetchedUrl = '';
|
|
600
|
+
for (const url of buildProbeUrls(scriptURL)) {
|
|
601
|
+
const probe = await fetchWithTimeout(url, 3000);
|
|
602
|
+
if (probe.ok && probe.text && probe.text.length > 0) {
|
|
603
|
+
fetched = { text: probe.text, bytes: probe.bytes ?? probe.text.length };
|
|
604
|
+
fetchedUrl = url;
|
|
605
|
+
break;
|
|
545
606
|
}
|
|
546
607
|
}
|
|
547
|
-
|
|
548
|
-
|
|
608
|
+
if (fetched) {
|
|
609
|
+
const result = (0, exports.parseBundleSource)(fetched.text, fetched.bytes, fetchedUrl);
|
|
610
|
+
cachedAnalysis = result;
|
|
611
|
+
isAnalyzing = false;
|
|
612
|
+
subscribers.forEach(cb => cb(result));
|
|
613
|
+
subscribers.length = 0;
|
|
614
|
+
return result;
|
|
549
615
|
}
|
|
550
|
-
// Fallback
|
|
616
|
+
// Fallback: could not reach a Metro dev server (release build, offline, or
|
|
617
|
+
// custom dev-server host). Return estimated values so the UI never crashes.
|
|
551
618
|
const fallbackBytes = 6840000; // ~6.8MB standard RN dev bundle
|
|
552
|
-
const result = (0, exports.parseBundleSource)('', fallbackBytes, scriptURL);
|
|
619
|
+
const result = (0, exports.parseBundleSource)('', fallbackBytes, scriptURL || 'unknown', false);
|
|
553
620
|
cachedAnalysis = result;
|
|
554
621
|
isAnalyzing = false;
|
|
555
622
|
subscribers.forEach(cb => cb(result));
|
|
@@ -355,6 +355,8 @@
|
|
|
355
355
|
"heroTitle": "Bundle & Asset Architecture",
|
|
356
356
|
"heroSubtitle": "Real-time size breakdown across all assets, code, and dependencies",
|
|
357
357
|
"heroSubtitleLive": "Live analysis of {{scriptUrl}}",
|
|
358
|
+
"liveAnalysisUnavailable": "Live bundle analysis unavailable",
|
|
359
|
+
"liveAnalysisUnavailableSub": "Could not reach the Metro dev server, so values are estimates. Make sure the app runs in development via `npx react-native start` and the Inspector can reach your Metro port (8081, 8082, ...).",
|
|
358
360
|
"bundleOverviewJson": "Bundle Overview JSON",
|
|
359
361
|
"devBundleSize": "DEV BUNDLE SIZE",
|
|
360
362
|
"devBundleHint": "{{kb}} KB • {{modules}} modules",
|
|
@@ -724,6 +724,21 @@ const BundleTab = React.memo(() => {
|
|
|
724
724
|
</View>
|
|
725
725
|
</View>
|
|
726
726
|
|
|
727
|
+
{/* Live analysis unavailable warning */}
|
|
728
|
+
{analysis && !analysis.isLive && (<View style={bundleStyles.liveWarningCard}>
|
|
729
|
+
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 6, flex: 1 }}>
|
|
730
|
+
<CircleAlertIcon color={AppColors.amber700} size={16}/>
|
|
731
|
+
<View style={{ flex: 1 }}>
|
|
732
|
+
<Text style={bundleStyles.liveWarningTitle}>
|
|
733
|
+
{t('bundle.liveAnalysisUnavailable')}
|
|
734
|
+
</Text>
|
|
735
|
+
<Text style={bundleStyles.liveWarningDesc}>
|
|
736
|
+
{t('bundle.liveAnalysisUnavailableSub')}
|
|
737
|
+
</Text>
|
|
738
|
+
</View>
|
|
739
|
+
</View>
|
|
740
|
+
</View>)}
|
|
741
|
+
|
|
727
742
|
{/* Development Bundle Split-Up (derived from the real running bundle) */}
|
|
728
743
|
{analysis && (<View style={bundleStyles.sectionCard}>
|
|
729
744
|
<View style={bundleStyles.sectionHeaderRow}>
|
|
@@ -2195,6 +2210,28 @@ const bundleStyles = StyleSheet.create({
|
|
|
2195
2210
|
borderWidth: 1,
|
|
2196
2211
|
borderColor: AppColors.errorBorder,
|
|
2197
2212
|
},
|
|
2213
|
+
liveWarningCard: {
|
|
2214
|
+
flexDirection: 'row',
|
|
2215
|
+
alignItems: 'center',
|
|
2216
|
+
backgroundColor: AppColors.amber100,
|
|
2217
|
+
borderWidth: 1,
|
|
2218
|
+
borderColor: AppColors.amber200,
|
|
2219
|
+
borderRadius: 10,
|
|
2220
|
+
padding: 12,
|
|
2221
|
+
marginBottom: 12,
|
|
2222
|
+
},
|
|
2223
|
+
liveWarningTitle: {
|
|
2224
|
+
fontFamily: AppFonts.interBold,
|
|
2225
|
+
fontSize: 12,
|
|
2226
|
+
color: AppColors.amber800Warm,
|
|
2227
|
+
marginBottom: 2,
|
|
2228
|
+
},
|
|
2229
|
+
liveWarningDesc: {
|
|
2230
|
+
fontFamily: AppFonts.interRegular,
|
|
2231
|
+
fontSize: 10.5,
|
|
2232
|
+
lineHeight: 14,
|
|
2233
|
+
color: AppColors.amber800Warm,
|
|
2234
|
+
},
|
|
2198
2235
|
adviceBadge: {
|
|
2199
2236
|
paddingHorizontal: 8,
|
|
2200
2237
|
paddingVertical: 4,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const LIB_VERSION = "1.1.
|
|
1
|
+
export declare const LIB_VERSION = "1.1.24";
|
|
@@ -107,7 +107,7 @@ export declare const getHostScriptURL: () => string;
|
|
|
107
107
|
/**
|
|
108
108
|
* Parses raw Metro bundle source code to discover real modules and packages in the host app.
|
|
109
109
|
*/
|
|
110
|
-
export declare const parseBundleSource: (bundleText: string, totalBytes: number, scriptURL: string) => HostBundleAnalysisResult;
|
|
110
|
+
export declare const parseBundleSource: (bundleText: string, totalBytes: number, scriptURL: string, isLive?: boolean) => HostBundleAnalysisResult;
|
|
111
111
|
/**
|
|
112
112
|
* Automatically fetch and analyze the real running bundle for the host app.
|
|
113
113
|
*/
|
|
@@ -8,23 +8,91 @@ import { AppColors } from '../styles/AppColors';
|
|
|
8
8
|
// 3. Extracting real module paths (project files vs node_modules dependencies).
|
|
9
9
|
// 4. Computing real Development and Production Binary (.ipa / .aab / .apk) sizes.
|
|
10
10
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
11
|
-
import { NativeModules, Platform } from 'react-native';
|
|
11
|
+
import { NativeModules, Platform, TurboModuleRegistry } from 'react-native';
|
|
12
12
|
let cachedAnalysis = null;
|
|
13
13
|
let isAnalyzing = false;
|
|
14
14
|
const subscribers = [];
|
|
15
|
+
const getSourceCodeModule = () => {
|
|
16
|
+
try {
|
|
17
|
+
const legacy = NativeModules?.SourceCode;
|
|
18
|
+
if (legacy && typeof legacy.scriptURL === 'string' && legacy.scriptURL.length > 0) {
|
|
19
|
+
return legacy;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
catch { }
|
|
23
|
+
try {
|
|
24
|
+
const turbo = TurboModuleRegistry?.get?.('SourceCode');
|
|
25
|
+
const constants = turbo?.getConstants?.();
|
|
26
|
+
const scriptURL = turbo?.scriptURL || constants?.scriptURL;
|
|
27
|
+
if (typeof scriptURL === 'string' && scriptURL.length > 0) {
|
|
28
|
+
return { scriptURL };
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch { }
|
|
32
|
+
return null;
|
|
33
|
+
};
|
|
15
34
|
export const getHostScriptURL = () => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
35
|
+
// 1. NativeModules.SourceCode (bridged) or SourceCode TurboModule (bridgeless / new arch)
|
|
36
|
+
const scriptURL = getSourceCodeModule()?.scriptURL;
|
|
37
|
+
if (typeof scriptURL === 'string' && scriptURL.length > 0) {
|
|
38
|
+
return scriptURL;
|
|
39
|
+
}
|
|
40
|
+
// 2. Android legacy: PlatformConstants.serverHost -> "localhost:8082"
|
|
41
|
+
try {
|
|
42
|
+
const serverHost = NativeModules?.PlatformConstants?.serverHost;
|
|
43
|
+
if (typeof serverHost === 'string' && serverHost.length > 0) {
|
|
44
|
+
return `http://${serverHost}/index.bundle?platform=${Platform.OS}&dev=true`;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch { }
|
|
48
|
+
return '';
|
|
49
|
+
};
|
|
50
|
+
const DEV_SERVER_PORTS = [8081, 8082, 8083, 8084, 8090, 8080, 19000];
|
|
51
|
+
const buildProbeUrls = (scriptURL) => {
|
|
52
|
+
const urls = [];
|
|
53
|
+
if (typeof scriptURL === 'string' && scriptURL.startsWith('http')) {
|
|
54
|
+
urls.push(scriptURL);
|
|
55
|
+
}
|
|
56
|
+
const portMatch = typeof scriptURL === 'string' ? scriptURL.match(/:(\d{2,5})/) : null;
|
|
57
|
+
const ports = portMatch ? [parseInt(portMatch[1], 10)] : DEV_SERVER_PORTS;
|
|
58
|
+
const hosts = Platform.OS === 'android'
|
|
59
|
+
? ['localhost', '127.0.0.1', '10.0.2.2']
|
|
60
|
+
: ['localhost', '127.0.0.1'];
|
|
61
|
+
for (const host of hosts) {
|
|
62
|
+
for (const port of ports) {
|
|
63
|
+
urls.push(`http://${host}:${port}/index.bundle?platform=${Platform.OS}&dev=true`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return Array.from(new Set(urls));
|
|
67
|
+
};
|
|
68
|
+
const fetchWithTimeout = async (url, timeoutMs) => {
|
|
69
|
+
try {
|
|
70
|
+
const controller = new AbortController();
|
|
71
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
72
|
+
try {
|
|
73
|
+
const res = await fetch(url, { signal: controller.signal });
|
|
74
|
+
if (!res.ok)
|
|
75
|
+
return { ok: false };
|
|
76
|
+
const contentLength = res.headers.get('content-length');
|
|
77
|
+
const text = await res.text();
|
|
78
|
+
return {
|
|
79
|
+
ok: true,
|
|
80
|
+
text,
|
|
81
|
+
bytes: contentLength ? parseInt(contentLength, 10) || text.length : text.length,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
clearTimeout(timer);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return { ok: false };
|
|
19
90
|
}
|
|
20
|
-
return Platform.OS === 'ios'
|
|
21
|
-
? 'http://localhost:8081/index.bundle?platform=ios&dev=true'
|
|
22
|
-
: 'http://10.0.2.2:8081/index.bundle?platform=android&dev=true';
|
|
23
91
|
};
|
|
24
92
|
/**
|
|
25
93
|
* Parses raw Metro bundle source code to discover real modules and packages in the host app.
|
|
26
94
|
*/
|
|
27
|
-
export const parseBundleSource = (bundleText, totalBytes, scriptURL) => {
|
|
95
|
+
export const parseBundleSource = (bundleText, totalBytes, scriptURL, isLive = true) => {
|
|
28
96
|
const isHermes = Boolean(globalThis.HermesInternal);
|
|
29
97
|
const totalDevMb = Number((totalBytes / (1024 * 1024)).toFixed(2));
|
|
30
98
|
const totalDevKb = Math.round(totalBytes / 1024);
|
|
@@ -447,7 +515,7 @@ export const parseBundleSource = (bundleText, totalBytes, scriptURL) => {
|
|
|
447
515
|
},
|
|
448
516
|
];
|
|
449
517
|
return {
|
|
450
|
-
isLive
|
|
518
|
+
isLive,
|
|
451
519
|
scriptURL,
|
|
452
520
|
totalDevBytes: totalBytes,
|
|
453
521
|
totalDevMb,
|
|
@@ -521,30 +589,29 @@ export const analyzeHostAppBundle = async () => {
|
|
|
521
589
|
}
|
|
522
590
|
isAnalyzing = true;
|
|
523
591
|
const scriptURL = getHostScriptURL();
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
byteLength = byteLength || bundleText.length;
|
|
534
|
-
const result = parseBundleSource(bundleText, byteLength, scriptURL);
|
|
535
|
-
cachedAnalysis = result;
|
|
536
|
-
isAnalyzing = false;
|
|
537
|
-
subscribers.forEach(cb => cb(result));
|
|
538
|
-
subscribers.length = 0;
|
|
539
|
-
return result;
|
|
592
|
+
// Probe candidate dev-server URLs until one serves the JS bundle
|
|
593
|
+
let fetched = null;
|
|
594
|
+
let fetchedUrl = '';
|
|
595
|
+
for (const url of buildProbeUrls(scriptURL)) {
|
|
596
|
+
const probe = await fetchWithTimeout(url, 3000);
|
|
597
|
+
if (probe.ok && probe.text && probe.text.length > 0) {
|
|
598
|
+
fetched = { text: probe.text, bytes: probe.bytes ?? probe.text.length };
|
|
599
|
+
fetchedUrl = url;
|
|
600
|
+
break;
|
|
540
601
|
}
|
|
541
602
|
}
|
|
542
|
-
|
|
543
|
-
|
|
603
|
+
if (fetched) {
|
|
604
|
+
const result = parseBundleSource(fetched.text, fetched.bytes, fetchedUrl);
|
|
605
|
+
cachedAnalysis = result;
|
|
606
|
+
isAnalyzing = false;
|
|
607
|
+
subscribers.forEach(cb => cb(result));
|
|
608
|
+
subscribers.length = 0;
|
|
609
|
+
return result;
|
|
544
610
|
}
|
|
545
|
-
// Fallback
|
|
611
|
+
// Fallback: could not reach a Metro dev server (release build, offline, or
|
|
612
|
+
// custom dev-server host). Return estimated values so the UI never crashes.
|
|
546
613
|
const fallbackBytes = 6840000; // ~6.8MB standard RN dev bundle
|
|
547
|
-
const result = parseBundleSource('', fallbackBytes, scriptURL);
|
|
614
|
+
const result = parseBundleSource('', fallbackBytes, scriptURL || 'unknown', false);
|
|
548
615
|
cachedAnalysis = result;
|
|
549
616
|
isAnalyzing = false;
|
|
550
617
|
subscribers.forEach(cb => cb(result));
|
|
@@ -355,6 +355,8 @@
|
|
|
355
355
|
"heroTitle": "Bundle & Asset Architecture",
|
|
356
356
|
"heroSubtitle": "Real-time size breakdown across all assets, code, and dependencies",
|
|
357
357
|
"heroSubtitleLive": "Live analysis of {{scriptUrl}}",
|
|
358
|
+
"liveAnalysisUnavailable": "Live bundle analysis unavailable",
|
|
359
|
+
"liveAnalysisUnavailableSub": "Could not reach the Metro dev server, so values are estimates. Make sure the app runs in development via `npx react-native start` and the Inspector can reach your Metro port (8081, 8082, ...).",
|
|
358
360
|
"bundleOverviewJson": "Bundle Overview JSON",
|
|
359
361
|
"devBundleSize": "DEV BUNDLE SIZE",
|
|
360
362
|
"devBundleHint": "{{kb}} KB • {{modules}} modules",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-inapp-inspector",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.24",
|
|
4
4
|
"description": "The zero-config, all-in-one in-app debugger for React Native & Expo. Inspect Network (fetch/axios), Console logs, Stack Traces, Redux State, Firebase Analytics, and JS Bundle size directly on device.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|