Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ml] Optimize bundles, reduce page load async chunks by 74% (#179311)
## Summary The `AnomalyExplorerChartsService` was importing the `SWIM_LANE_LABEL_WIDTH` numerical constant from `swimlane_container.tsx`. As a result, the _entirety_ of that file was being included in the async bundle. `AnomalyExplorerChartsService` is loaded asynchronously on page load by the embeddable. By relocating the constant to its own file-- as well as other optimizations (see below)-- we reduce the async page load by 74%, (in dev mode). ### Before - `351k` <img width="1220" alt="Screenshot 2024-03-24 at 10 09 31 AM" src="https://github.com/elastic/kibana/assets/297604/6cea41f5-fb10-41c3-8951-a4be897174f9"> ### After - `93.4k` <img width="1471" alt="Screenshot 2024-04-05 at 11 45 45 AM" src="https://github.com/elastic/kibana/assets/297604/a07e7a19-c1af-4b45-a195-69730fc61b0c"> Unfortunately, this change led to a bloating of async modules, the cause of which is still unclear. The application async chunk weighed in at 2.2 MB compressed! To get this PR to a shippable state, I refactored additional code to bring down duplication and bloat. The result is an `ml` experience that fetches small bundles on demand as someone interacts with it: ![Apr-05-2024 11-51-18](https://github.com/elastic/kibana/assets/297604/75ba423e-7071-4867-ae4b-05308bf319f3) More work can be done to continue to optimize the plugin, of course, but this set of changes is an excellent start, (and case study on bundle load). ### Other optimizations in this PR - Registration of some `start` services are conditional, and contain their own async calls. I've removed these from the register helper, (which itself is a brute-force offload of code from the plugin, but is still loaded every time), and loaded them async if the conditions apply. - Routing in `ml` use factories to create individual routes. In a lot of cases, the pages these routes displayed were not asynchronously loaded, adding tremendous amounts of React code to the root application. - I made all pages loaded by routes async. - In some cases, the components themselves were colocated with the route factory. I moved those to their own files for async import. - Similarly, some state managers were colocated. Those were moved to their own files, as well. - Moved flyouts, modals, expanding rows to `React.lazy` async modules, (using `dynamic` from `@kbn/shared-ux-utility`. - Refactored `export * from` directives from `public/shared.ts` to accurately reflect what is being consumed outside the `ml` plugin, (and also reduce the size of _that_ bundle. - Refactored `lodash` imports to submodule imports to enable tree-shaking, (if ever enabled in webpack). - Moved `getMlGlobalServices` off of the `app.tsx` file for import by others, (to avoid depending on the rest of the code there). - Moved some types to `/common` to avoid importing code, (though, admittedly, types are compiled away). But it felt cleaner to move them out. --------- Co-authored-by: kibanamachine <[email protected]>
- Loading branch information