Skip to main content
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

  • 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
  • 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
  • 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

1

Install metro-config

Install @ui-kitten/metro-config as a dev dependency
2

Configure Metro

Create or update metro.config.js with Eva config
3

Update ApplicationProvider

Spread {...eva} in ApplicationProvider props
4

Remove customMapping

Remove customMapping prop if specified
5

Clear Cache

Restart bundler with --reset-cache
6

Test Thoroughly

Test all screens to ensure themes render correctly
7

Configure CI/CD

Add bootstrap step to your build pipeline
8

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

Build docs developers (and LLMs) love