Optimize existing image assets with lossless compression (#223998)
## Summary This PR applies **lossless compression** to all SVG and JPG/PNG assets across Kibana using: - [`svgo`](https://github.com/svg/svgo) — for optimizing SVGs - [`image-optimize`](https://www.npmjs.com/package/image-optimize) — for JPG/PNG compression ‼️**Please scroll to ''Unknown metric groups" accordion to see what's the gain for your code.** <img width="542" alt="Screenshot 2025-06-18 at 13 24 20" src="https://github.com/user-attachments/assets/191afb28-44fc-4551-9026-756a8385c66a" /> The goal is to reduce asset size and improve load performance without compromising visual quality. This PR achieves a **23 MB** reduction in asset size across all images bundled in Kibana’s running code—meaning these compressed images directly impact what ships in Kibana. Some assets get bundled into chunks due to our bundling strategy but might not actually be requested at runtime. Additionally, I ran the same optimization script on the docs assets as a harmless extra step, but those savings aren’t included in the 23 MB total. --- ## Why While working on Emotion rewrites, I noticed some SVGs seemed unnecessarily heavy. That led to a broader investigation into our image assets, and it turns out we’re not consistently optimizing them during development or build. --- ## Notes - Visual fidelity of optimized assets has been manually verified — no visible differences - The optimization is **lossless**, meaning no quality degradation - Some assets (like large background images) could benefit further from **lossy compression** --- ## Follow-ups / Ideas 1. **Automate compression in the dev/build pipeline** - e.g. add `svgo` as a pre-commit or CI step for SVGs 2. **Improve CI reporting** - Currently, bundle size diffs for images are hidden under "Unknown metric groups" in the GitHub CI comment. We may want to make these more visible. - 3. **Audit large assets manually** — apply lossy compression where appropriate 4. **Avoid redundant image loading** - e.g. background images on the login page are loaded again on the space selector page since they’re bundled twice. I’m working on a separate PR to address that. ## Snippets I used to apply the compression ``` # Find SVG files find . -type f -iname "*.svg" \ -not -path "*/node_modules/*" \ -not -path "*/functional/*" > svg-files.txt # Compress SVGs while IFS= read -r file; do svgo "$file" done < svg-files.txt ``` This snippet has been used for png and jpg, but the example below is for png: ``` # Find PNG files find . -type f -iname "*.png \ -not -path "*/node_modules/*" \ -not -path "*/functional/*" > png-files.txt # Compress PNGs while IFS= read -r file; do image-optimize -f jpg "$file" done < png-files.txt ```
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 190 KiB After Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 184 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 436 KiB After Width: | Height: | Size: 121 KiB |
Before Width: | Height: | Size: 440 KiB After Width: | Height: | Size: 119 KiB |
Before Width: | Height: | Size: 442 KiB After Width: | Height: | Size: 120 KiB |
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 455 KiB After Width: | Height: | Size: 130 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 247 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 163 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 98 KiB |
Before Width: | Height: | Size: 113 KiB After Width: | Height: | Size: 102 KiB |
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 914 KiB After Width: | Height: | Size: 364 KiB |
Before Width: | Height: | Size: 144 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 194 KiB After Width: | Height: | Size: 42 KiB |
Before Width: | Height: | Size: 162 KiB After Width: | Height: | Size: 40 KiB |