-
Notifications
You must be signed in to change notification settings - Fork 176
Expand file tree
/
Copy pathmetro.config.js
More file actions
98 lines (87 loc) · 4.47 KB
/
Copy pathmetro.config.js
File metadata and controls
98 lines (87 loc) · 4.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
const { getDefaultConfig } = require('expo/metro-config');
const path = require('path');
const config = getDefaultConfig(__dirname);
// ─── Tree-shaking / minification ─────────────────────────────────────────────
// Enable minification in production so unused code paths are removed by the
// Metro bundler's inline-requires and dead-code-elimination passes.
config.transformer = {
...config.transformer,
// Inline requires defers module evaluation until first use — this effectively
// implements lazy loading for heavy modules (ethers, stellar-sdk, etc.)
// and removes them from the critical path entirely when not needed.
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: true,
inlineRequires: true,
},
}),
// ── Performance profiling ──────────────────────────────────────────────────
// Emit source-maps in development so the Chrome/Flipper profiler can map
// hot-path frames back to TypeScript source lines.
minifierConfig: {
// Keep class/function names in dev for readable profiler traces
keep_fnames: process.env.NODE_ENV !== 'production',
keep_classnames: process.env.NODE_ENV !== 'production',
},
};
// ─── Resolver: platform-specific module aliases ───────────────────────────────
// Prefer the ES-module (tree-shakeable) entry point for libraries that ship
// both CJS and ESM builds.
config.resolver = {
...config.resolver,
// Prioritise .mjs then .js so bundler picks up ESM where available
sourceExts: ['mjs', 'js', 'jsx', 'ts', 'tsx', 'cjs', 'json'],
// ── Module aliasing for bundle splitting ──────────────────────────────────
// Heavy chain/crypto modules are conditionally resolved so they don't bloat
// the main bundle on screens that don't use them. Each alias points at a
// thin dynamic-import wrapper (lazy loaded on first use via inlineRequires).
extraNodeModules: {
// Allow absolute imports from the project root (used by screen-level code)
'@subtrackr': path.resolve(__dirname, 'src'),
},
};
// ─── Performance budget reporter ─────────────────────────────────────────────
// Read the performance-budget.json thresholds and print a warning when the
// serialised bundle exceeds them. Runs only during the bundle step (not watch).
if (process.env.METRO_BUNDLE_REPORT === '1') {
const fs = require('fs');
const budgetFile = path.join(__dirname, 'performance-budget.json');
if (fs.existsSync(budgetFile)) {
const budget = JSON.parse(fs.readFileSync(budgetFile, 'utf8'));
const originalSerializer = config.serializer?.customSerializer;
config.serializer = {
...config.serializer,
customSerializer: (entryPoint, preModules, graph, options) => {
const bundle =
typeof originalSerializer === 'function'
? originalSerializer(entryPoint, preModules, graph, options)
: undefined;
// Approximate bundle size by summing module source lengths
let totalBytes = 0;
for (const [, mod] of graph.dependencies) {
totalBytes += (mod.output ?? []).reduce((acc, o) => acc + (o.data?.code?.length ?? 0), 0);
}
const budgetBytes = (budget.bundleSizeKb ?? 5120) * 1024;
if (totalBytes > budgetBytes) {
const overKb = Math.round((totalBytes - budgetBytes) / 1024);
console.warn(
`[Metro] ⚠ Bundle size ${Math.round(totalBytes / 1024)} KB ` +
`exceeds budget ${budget.bundleSizeKb} KB by ${overKb} KB`
);
} else {
console.info(
`[Metro] ✓ Bundle size ${Math.round(totalBytes / 1024)} KB ` +
`within budget ${budget.bundleSizeKb} KB`
);
}
return bundle;
},
};
}
}
// ─── Bundle analyser ──────────────────────────────────────────────────────────
// To analyse bundle size locally, run:
// METRO_BUNDLE_REPORT=1 npx expo export
// Or visualise interactively:
// npx react-native-bundle-visualizer
module.exports = config;