Skip to main content
Elastic UI
Elastic UI
Getting startedComponentsUtilitiesPatternsContentData visualization
EUI ChangelogGitHub
  • Setup
  • Theming
  • Tree-shaking
  • Working with Emotion
  • Accessibility
  • Testing
  • Elastic UI Framework
  • Tree-shaking

Tree-shaking

Tree-shaking (dead code elimination) allows bundlers to remove unused code from your production builds, reducing the amount of JavaScript shipped to users.

How EUI supports tree-shaking

EUI publishes two build outputs:

  • es/ — ES modules (used by modern bundlers via the module field in package.json)
  • test-env/ — Jest-only CommonJS build (see mapping to the test-env directory)

The es/ build preserves import/export syntax, which bundlers like Webpack, Rollup, and esbuild can statically analyze to determine which exports are actually used.

EUI's package.json also declares:

✄𐘗
json code block:
✄𐘗{ "sideEffects": ["*.css", "*.scss"] }

This tells bundlers that all JavaScript modules are side-effect-free and safe to remove if unused. Only CSS/SCSS files are marked as having side effects.

What you need

For tree-shaking to work, your bundler must resolve @elastic/eui to the ES module build (es/). Most bundlers do this automatically via the module field. Verify that you're importing from the top-level package:

✄𐘗
tsx code block:
✄𐘗import { EuiButton, EuiPanel } from '@elastic/eui';

No special configuration is needed — a properly configured bundler will tree-shake unused components automatically.

Icons and code-splitting

EuiIcon uses dynamic imports to load icon assets only when actually used. Depending on your bundler's configuration, each icon may become a fully separate chunk loaded lazily at runtime, or be otherwise grouped together with other code. It's common for bundlers to decide that based on the minimum and maximum chunk sizes to optimize code delivery efficiency. Please check your bundler documentation to learn more.

✄𐘗
ts code block:
✄𐘗// Simplified example of how EUI maps icon names to dynamic imports const typeToPathMap = { calendar: () => import('./assets/calendar'), check: () => import('./assets/check'), // ... };

This means icon SVGs are not included in your main bundle — they're fetched only when a specific icon renders on the page. However, the mapping object itself (which associates icon names with their chunk references) is always included when EuiIcon is used.

There is an ongoing effort to refactor EuiIcon for improved performance and reduced mapping overhead.

Verifying tree-shaking in your project

To confirm tree-shaking is working:

  1. Webpack: Use webpack-bundle-analyzer to visualize your bundle and check that unused EUI components are not present
  2. Vite/Rollup: Use rollup-plugin-visualizer for a similar analysis

A minimal app importing only EuiButton should produce a production bundle significantly smaller than the full EUI library.

(Advanced) Deep imports

If you need to limit what gets included without relying on top-level tree-shaking, you can use direct subpath imports from the es/ build:

✄𐘗
tsx code block:
✄𐘗import { EuiButton } from '@elastic/eui/es/components/button'; import { keys } from '@elastic/eui/es/services';

Subpath imports are not a guaranteed public API and may change between versions. Prefer top-level imports from @elastic/eui for reliable tree-shaking.

Edit this page

Previous
Shadows
Next
Introduction
  • How EUI supports tree-shaking
  • What you need
  • Icons and code-splitting
  • Verifying tree-shaking in your project
  • (Advanced) Deep imports
EUI is dual-licensed under Elastic License 2.0 and Server Side Public License, v1 | Crafted with ❤️ by Elastic