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:
@@ -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