Bundle only the icons the app renders
Lucide ships one module per icon, but the barrel import dragged all ~1600 in. A local Babel plugin rewrites each named import to its own icon module, so the bundle drops from 4.66 MB to 3.40 MB and the earliest tap that reliably lands a photo moves from ~1.8 s to ~1.6 s on the test device.
This commit is contained in:
+2
-1
@@ -13,7 +13,8 @@ Memory
|
||||
|
||||
Cold start
|
||||
- The JS bundle is stored uncompressed in the APK.
|
||||
- Named Lucide imports are rewritten to per-icon modules, so only the icons the app renders are bundled: 4.66 MB → 3.40 MB (−27%).
|
||||
- The export pipeline and the recipe/GPS helpers load on demand.
|
||||
- Hidden modals render nothing.
|
||||
|
||||
Measured on a vivo V2430 (Android 16): the cold-start work did not move the tap threshold (the earliest reliable tap is still ~1.9 s). The remaining time is spent before app JS — process init, SoLoader, Hermes eval. Trimming the bundle is the next candidate; `lucide-react-native` currently ships the whole icon set.
|
||||
Measured on a vivo V2430 (Android 16) with a force-stop/start/tap probe: the earliest tap that reliably lands a photo moved from ~1.8 s to ~1.6 s once the bundle was trimmed. The rest is spent before app JS — process init, SoLoader, Hermes eval.
|
||||
|
||||
@@ -1,3 +1,28 @@
|
||||
// Lucide ships one module per icon, but the barrel import drags all ~1600 in.
|
||||
// Rewrite each named import into its own icon module so Metro only walks what we use.
|
||||
const lucidePerIcon = () => ({
|
||||
visitor: {
|
||||
ImportDeclaration(path) {
|
||||
if (path.node.source.value !== "lucide-react-native") return;
|
||||
const t = require("@babel/types");
|
||||
const kebab = (n) =>
|
||||
n
|
||||
.replace(/([a-z0-9])([A-Z])/g, "$1-$2")
|
||||
.replace(/([A-Za-z])(\d)/g, "$1-$2")
|
||||
.toLowerCase();
|
||||
path.replaceWithMultiple(
|
||||
path.node.specifiers.map((s) =>
|
||||
s.type === "ImportSpecifier"
|
||||
? t.importDeclaration(
|
||||
[t.importDefaultSpecifier(s.local)],
|
||||
t.stringLiteral(`lucide-react-native/icons/${kebab(s.imported.name)}`)
|
||||
)
|
||||
: t.importDeclaration([s], t.stringLiteral("lucide-react-native"))
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
module.exports = function (api) {
|
||||
api.cache(true);
|
||||
return {
|
||||
@@ -7,6 +32,7 @@ module.exports = function (api) {
|
||||
],
|
||||
plugins: [
|
||||
"react-native-reanimated/plugin",
|
||||
lucidePerIcon
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user