Babel Plugin
Bundle icons at build time for 0ms first render - no network requests, no loading states.
The Babel plugin is optional. rn-iconify works out of the box with runtime fetching. Use this for production optimization.
Installationโ
The Babel plugin is included with rn-iconify:
npm install rn-iconify
Configurationโ
Add to your babel.config.js:
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: [
['rn-iconify/babel', {
// Icons are auto-detected from your source code
// No manual configuration needed!
}],
],
};
How It Worksโ
The Babel plugin automatically:
- Scans your code - Finds all icon usages like
<Mdi name="home" /> - Collects icon names - Tracks which icons are used in each file
- Fetches at build time - Downloads SVG data from Iconify API
- Generates cache - Creates a local cache file with all icon data
- Instant runtime - Icons render immediately without network requests
// Your code - plugin detects these automatically
<Mdi name="home" />
<Heroicons name="user" />
prefetchIcons(['mdi:settings', 'lucide:camera'])
Configuration Optionsโ
module.exports = {
plugins: [
['rn-iconify/babel', {
// Include specific patterns (supports wildcards)
include: [
'mdi:*', // All Material Design Icons
'heroicons:*', // All Heroicons
],
// Exclude patterns
exclude: [
'mdi:test-*', // Skip test icons
],
// Output path for generated cache
outputPath: '.rn-iconify-cache',
// Enable verbose logging
verbose: true,
// Disable the plugin temporarily
disabled: false,
}],
],
};
Options Referenceโ
| Option | Type | Default | Description |
|---|---|---|---|
include | string[] | [] | Icon patterns to include (wildcards supported) |
exclude | string[] | [] | Icon patterns to exclude |
outputPath | string | .rn-iconify-cache | Generated cache location |
verbose | boolean | false | Log detected icons during build |
disabled | boolean | false | Disable the plugin |
Pattern Matchingโ
Use glob patterns for flexible icon selection:
plugins: [
['rn-iconify/babel', {
include: [
'mdi:home*', // home, home-outline, home-variant, etc.
'mdi:arrow-*', // All arrow icons
'heroicons:*-solid', // All solid Heroicons
],
exclude: [
'mdi:*-off', // Exclude disabled variants
],
}],
],
Auto-Detectionโ
By default, the plugin auto-detects icons from your code:
// All of these are automatically detected:
// JSX usage
<Mdi name="home" />
<Heroicons name="user" />
<Lucide name="camera" />
// prefetchIcons calls
prefetchIcons(['mdi:home', 'mdi:settings'])
Bundle Size Impactโ
Bundled icons add to your JavaScript bundle:
| Icons Bundled | Approximate Size |
|---|---|
| 10 icons | ~5 KB |
| 100 icons | ~50 KB |
| 1,000 icons | ~500 KB |
The plugin only bundles icons it detects in your code. If you use dynamic icon names, consider using the include option to ensure they're bundled.
Dynamic Icon Namesโ
Dynamic icon names aren't auto-detected. Use include to bundle them:
// Not detected (dynamic name)
const iconName = `mdi:${state}`;
<Mdi name={iconName} />
// Solution: Add to include list
['rn-iconify/babel', {
include: ['mdi:loading', 'mdi:success', 'mdi:error'],
}]
Expo Configurationโ
For Expo projects, modify babel.config.js:
module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: [
['rn-iconify/babel', {
verbose: __DEV__, // Only log in development
}],
],
};
};
Clearing Cacheโ
After changing configuration, clear Metro cache:
# React Native CLI
npx react-native start --reset-cache
# Expo
npx expo start --clear
Build Outputโ
With verbose: true, you'll see detected icons during build:
[rn-iconify] Build started. Project root: /path/to/project
[rn-iconify] Detected 47 unique icons across 23 files
[rn-iconify] Icon sets: mdi (28), heroicons (12), lucide (7)
[rn-iconify] Generating bundle...
[rn-iconify] Bundle generated: .rn-iconify-cache/icons.json (15.2 KB)
Generated Filesโ
The plugin creates a cache directory:
.rn-iconify-cache/
โโโ icons.json # Icon data
โโโ icons.js # JavaScript module
Add to .gitignore:
.rn-iconify-cache/
CI/CD Integrationโ
Ensure icons are bundled in CI:
# .github/workflows/build.yml
- name: Build App
run: |
npm install
npx react-native bundle \
--platform android \
--dev false \
--entry-file index.js \
--bundle-output ./android/app/src/main/assets/index.android.bundle
Troubleshootingโ
Icons Not Bundlingโ
- Check icon component names are correct (
Mdi, notmdi) - Clear Metro cache
- Enable verbose mode to see detected icons
['rn-iconify/babel', {
verbose: true,
}]
Network Errors During Buildโ
The plugin needs network access to fetch icons. If behind a proxy:
# Set proxy environment variables
export HTTP_PROXY=http://proxy.example.com:8080
export HTTPS_PROXY=http://proxy.example.com:8080
Large Bundle Sizeโ
- Review what icons are being bundled (use
verbose: true) - Use specific includes instead of wildcards
- Add excludes for unused icon variants
Performance Comparisonโ
| Method | First Render | Bundle Size | Network |
|---|---|---|---|
| Runtime fetch | ~100-500ms | Minimal | Required |
| Prefetch | ~0ms (after prefetch) | Minimal | Required |
| Babel plugin | 0ms | Increases | None |
Recommended Strategyโ
- Development: Let plugin auto-detect icons
- Production: Review bundled icons, optimize with includes/excludes
- Critical path: Ensure navigation and common UI icons are bundled
// babel.config.js
const isProduction = process.env.NODE_ENV === 'production';
module.exports = {
plugins: [
['rn-iconify/babel', {
verbose: !isProduction,
// In production, explicitly include only needed icons
include: isProduction ? [
'mdi:home',
'mdi:settings',
'mdi:account',
'mdi:arrow-left',
] : [],
}],
],
};
Next Stepsโ
- CLI Tools - Analyze icon usage
- Offline Bundles - Full offline support
- Architecture - How bundling works