By default, UI Kitten processes Eva Design System themes at runtime, which can impact initial load time and performance. This guide shows you how to precompile themes during build time for better performance.
Overview
Runtime theme processing can cause:
Slower app startup
Delayed first render
Performance issues with mapping customization
Compatibility issues with certain navigation libraries
Precompiling themes solves these issues by processing Eva themes during your build process instead of at runtime.
Installation
Install the UI Kitten Metro Config package:
npm install --save-dev @ui-kitten/metro-config
Update Application Provider
Modify your app to use precompiled themes:
import React from 'react' ;
import * as eva from '@eva-design/eva' ;
import { ApplicationProvider } from '@ui-kitten/components' ;
export default () => (
< ApplicationProvider { ... eva } theme = { eva . light } >
{ /* Your app content */ }
</ ApplicationProvider >
) ;
By spreading {...eva}, you tell UI Kitten to use precompiled mapping if available. If not found, it falls back to runtime compilation.
Notice we no longer need the customMapping prop - it’s handled automatically by the build process.
Metro Bundler Configuration
Metro is the JavaScript bundler for React Native. Configure it to precompile Eva themes during the build.
Bare React Native Projects
Create or update metro.config.js at your project root:
const MetroConfig = require ( '@ui-kitten/metro-config' );
const evaConfig = {
evaPackage: '@eva-design/eva' ,
// Optional: Specify custom mapping if you use mapping customization
// customMappingPath: './custom-mapping.json',
};
module . exports = (() => {
// Start with your existing config or an empty object
const previousConfig = {};
// Merge with UI Kitten config
const uiKittenConfig = MetroConfig . create ( evaConfig , previousConfig );
// Return the merged config
return uiKittenConfig ;
})();
Expo Projects
For Expo projects, merge with Expo’s default Metro config:
const { getDefaultConfig } = require ( 'expo/metro-config' );
const MetroConfig = require ( '@ui-kitten/metro-config' );
const evaConfig = {
evaPackage: '@eva-design/eva' ,
// Optional: Specify custom mapping if you use mapping customization
// customMappingPath: './custom-mapping.json',
};
module . exports = ( async () => {
// Get Expo's default config
const defaultConfig = await getDefaultConfig ( __dirname );
// Merge with UI Kitten config
const uiKittenConfig = MetroConfig . create ( evaConfig , defaultConfig );
// Return the merged config
return uiKittenConfig ;
})();
Configuration Options
evaPackage
Specifies which Eva Design System package to compile:
const evaConfig = {
evaPackage: '@eva-design/eva' , // or '@eva-design/material'
};
customMappingPath
Path to your custom mapping file if you use mapping customization :
const evaConfig = {
evaPackage: '@eva-design/eva' ,
customMappingPath: './custom-mapping.json' ,
};
Omit this option if you don’t customize Eva mappings.
Restart Bundler
After configuring Metro, restart your bundler with cleared cache:
npm start -- --reset-cache
Command Line Interface
For CI/CD environments or manual builds, use the CLI to precompile themes:
Basic Usage
ui-kitten bootstrap @eva-design/eva
With Custom Mapping
ui-kitten bootstrap @eva-design/eva ./path-to/custom-mapping.json
This generates precompiled mapping files that UI Kitten will use at runtime.
CI/CD Integration
Add to your build pipeline:
# .github/workflows/build.yml
name : Build
on : [ push ]
jobs :
build :
runs-on : ubuntu-latest
steps :
- uses : actions/checkout@v2
- name : Install dependencies
run : npm install
- name : Precompile Eva themes
run : npx ui-kitten bootstrap @eva-design/eva
- name : Build app
run : npm run build
Custom Mapping
If you customize Eva Design System mappings, specify the path:
Create Custom Mapping
Create custom-mapping.json:
{
"components" : {
"Button" : {
"meta" : {},
"appearances" : {
"filled" : {
"mapping" : {
"borderRadius" : 8 ,
"paddingHorizontal" : 24
}
}
}
}
}
}
Configure Metro
Update metro.config.js to include your custom mapping:
const MetroConfig = require ( '@ui-kitten/metro-config' );
const evaConfig = {
evaPackage: '@eva-design/eva' ,
customMappingPath: './custom-mapping.json' , // Your custom mapping
};
module . exports = MetroConfig . create ( evaConfig );
CLI with Custom Mapping
ui-kitten bootstrap @eva-design/eva ./custom-mapping.json
Material Design Theme
UI Kitten also supports Eva’s Material Design theme:
const evaConfig = {
evaPackage: '@eva-design/material' ,
};
Update your app:
import React from 'react' ;
import * as material from '@eva-design/material' ;
import { ApplicationProvider } from '@ui-kitten/components' ;
export default () => (
< ApplicationProvider { ... material } theme = { material . light } >
{ /* Your app content */ }
</ ApplicationProvider >
) ;
Verify Precompilation
Check if themes are precompiled:
import React , { useEffect } from 'react' ;
import * as eva from '@eva-design/eva' ;
import { ApplicationProvider } from '@ui-kitten/components' ;
export default () => {
useEffect (() => {
// Check if mapping is precompiled
if ( eva . mapping ) {
console . log ( '✅ Using precompiled Eva mapping' );
} else {
console . log ( '⚠️ Falling back to runtime compilation' );
}
}, []);
return (
< ApplicationProvider { ... eva } theme = { eva . light } >
{ /* Your app content */ }
</ ApplicationProvider >
);
};
Performance Comparison
Precompilation typically provides:
50-70% faster initial render - App starts up quicker
Reduced memory usage - No runtime theme processing
Smoother navigation - Especially with React Native Navigation
Better bundle optimization - Smaller JavaScript bundle
Advanced Configuration
Multiple Eva Packages
If you switch between Eva and Material themes:
const MetroConfig = require ( '@ui-kitten/metro-config' );
// Compile Eva theme
const evaPrecompiled = MetroConfig . create ({
evaPackage: '@eva-design/eva' ,
});
// You'll need to run bootstrap for each theme separately
module . exports = evaPrecompiled ;
Custom Transformer
If you use custom Metro transformers:
const MetroConfig = require ( '@ui-kitten/metro-config' );
const evaConfig = {
evaPackage: '@eva-design/eva' ,
};
const customConfig = {
transformer: {
// Your custom transformer options
getTransformOptions : async () => ({
transform: {
experimentalImportSupport: false ,
inlineRequires: true ,
},
}),
},
};
module . exports = MetroConfig . create ( evaConfig , customConfig );
React Native Navigation (Wix)
If you use React Native Navigation instead of React Navigation, precompilation is especially important:
npm install --save-dev @ui-kitten/metro-config
Configure as shown above, then restart your bundler. This eliminates the performance issues that can occur with React Native Navigation.
Troubleshooting
Themes Still Compiling at Runtime
Verify metro.config.js is in your project root
Ensure you restarted the bundler with --reset-cache
Check that @ui-kitten/metro-config is installed
Confirm {...eva} spread is used in ApplicationProvider
Custom Mapping Not Working
Verify the path in customMappingPath is correct
Ensure the mapping JSON is valid
Check that the mapping file exists before running Metro
Try running the CLI command manually to test
Build Errors After Configuration
Clear Metro cache: npm start -- --reset-cache
Delete node_modules and reinstall: rm -rf node_modules && npm install
Check for conflicting Metro configurations
Ensure all peer dependencies are installed
Run npx ui-kitten bootstrap before the build step
Ensure @ui-kitten/metro-config is in devDependencies
Check that the Eva package is installed in CI environment
Best Practices
When changing Metro configuration, always restart with cleared cache: npm start -- --reset-cache
Add generated files to .gitignore: # UI Kitten generated files
node_modules/@eva-design/*/mapping.json.compiled
Test your app with and without precompilation to ensure compatibility.
Use bundle analyzers to verify precompilation reduces bundle size: npx react-native-bundle-visualizer
Production Checklist
Install metro-config
Install @ui-kitten/metro-config as a dev dependency
Configure Metro
Create or update metro.config.js with Eva config
Update ApplicationProvider
Spread {...eva} in ApplicationProvider props
Remove customMapping
Remove customMapping prop if specified
Clear Cache
Restart bundler with --reset-cache
Test Thoroughly
Test all screens to ensure themes render correctly
Configure CI/CD
Add bootstrap step to your build pipeline
Monitor Performance
Measure startup time and verify improvement
Next Steps
Theming Learn more about Eva Design System theming
Web Support Optimize your web build with precompiled themes