Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Cases] Reducing the page load bundle size #157492

Merged
merged 15 commits into from
Jun 9, 2023

Conversation

adcoelho
Copy link
Contributor

@adcoelho adcoelho commented May 12, 2023

Summary

Things got a bit out of control ever since we merged #154436.

In this PR I managed to reduce the cases bundle size from 166.0k to 140.0k.

This was done in several different steps:

Removing the usage of query-string

This package took over 0.6% of the size of all chunks.

Screenshot 2023-05-12 at 15 10 52

All functionality it provides could be replaced by the native URLSearchParans.

I removed the package in 1ef0211.

@kbn/cases-components

The cases plugin used imports from @kbn-cases-components in several places, these took up 4.4% of the bundle size.

Screenshot 2023-05-12 at 15 13 48

This would normally be fine but it seemed like webpack's tree shaking wasn't working correctly when doing imports from the top like import {...} from '@kbn/cases-components'.

The plugin bundle seemed to be getting too much unnecessary code so I changed the imports in 547755c to be more specific.

Now @kbn/cases-components only takes up 0.1% of the bundle size.

Screenshot 2023-05-12 at 15 17 24

Removing unnecessary public exports

Code that is shared statically with other plugins will contribute to the page load bundle size of that plugin. This includes exports from the public/index.ts file and any file referenced by the extraPublicDirs manifest property.

I read the above in the documentation and checked what we exported. I found a bunch of things that we were exporting but that actually weren't being used by other plugins.

I removed those unnecessary exports in 6a0ff8c.

Unnecessary exports part 2

After merging the multiple file-related branches we were exporting the imageMimeTypes variable(a quite large array) twice. 53135ec

It belonged to common/ that is referenced in extraPublicDirs so that saved us a few more Ks.

Cases plugin

Code that is shared statically with other plugins will contribute to the page load bundle size of that plugin.

In the cases plugin start we were returning a deprecated function that was not being used anywhere any more.

I removed it -0.9K 🤷

42b30b3

Making the clientAPI lazy

Once again,

Code that is shared statically with other plugins will contribute to the page load bundle size of that plugin.

I was going over everything that our plugin exports to see if something was not used and noticed that the functions we return in cases.api are not used by everyone.

They were already promises so I changed the implementation to lazy load the code.

A good rule of thumb here is that if the chunk is not always needed at setup/start time it might benefit from being lazy loaded. Some plugins need some of this code so we can async import() and reduce the page load bundle size significantly. See e201ab1.

Lazy loading components in the file attachment

During the cases plugin setup step we register the file's internal attachment.

This defines how the file user action will look on the Case Detail page so naturally it requires a bunch of components to be loaded. The mistake here was that we don't need those components to be loaded right away.

I followed React's guidelines for lazy loading all components in the registered object greatly decreasing the bundle size in 1c9ede7.

@adcoelho adcoelho added technical debt Improvement of the software architecture and operational architecture Team:ResponseOps Label for the ResponseOps team (formerly the Cases and Alerting teams) Feature:Cases Cases feature labels May 12, 2023
@adcoelho adcoelho self-assigned this May 12, 2023
@adcoelho adcoelho marked this pull request as ready for review June 9, 2023 09:37
@adcoelho adcoelho requested a review from a team as a code owner June 9, 2023 09:37
@elasticmachine
Copy link
Contributor

Pinging @elastic/response-ops (Team:ResponseOps)

@elasticmachine
Copy link
Contributor

Pinging @elastic/response-ops-cases (Feature:Cases)

@cnasikas cnasikas added the release_note:skip Skip the PR/issue when compiling release notes label Jun 9, 2023
Copy link
Contributor

@js-jankisalvi js-jankisalvi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work!! 🎉


const FileAttachmentEvent = ({ file }: FileAttachmentEventProps) => {
const { isPreviewVisible, showPreview, closePreview } = useFilePreview();
const FileAttachmentEvent = lazy(() =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice approach 👍

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was effective because this attachment type is registered in x-pack/plugins/cases/public/plugin.ts.

Before realizing I was trying to lazy load everything everywhere but it didn't work :D until I realized that the cases app is already mostly lazy loaded, these were the exceptions.

@@ -6,7 +6,7 @@
*/

import * as rt from 'io-ts';
import { CaseStatuses } from '@kbn/cases-components';
import { CaseStatuses } from '@kbn/cases-components/src/status/types';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't aware that not importing from exact folder increases bundle size 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally, it wouldn't because web pack should be able to recognize what is and is not necessary. But it seems we can't fully trust it 😬

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haha.. better to be safe!! 👍

@kibana-ci
Copy link
Collaborator

💛 Build succeeded, but was flaky

Failed CI Steps

Test Failures

  • [job] [logs] FTR Configs #23 / Cloud Security Posture Findings Page SearchBar add filter

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
cases 650 640 -10

Public APIs missing comments

Total count of every public API that lacks a comment. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats comments for more detailed information.

id before after diff
cases 84 64 -20

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
cases 386.9KB 416.4KB +29.5KB

Public APIs missing exports

Total count of every type that is part of your API that should be exported but is not. This will cause broken links in the API documentation system. Target amount is 0. Run node scripts/build_api_docs --plugin [yourplugin] --stats exports for more detailed information.

id before after diff
cases 30 26 -4

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
cases 175.8KB 152.9KB -23.0KB
Unknown metric groups

API count

id before after diff
cases 101 79 -22

async chunk count

id before after diff
cases 23 26 +3

ESLint disabled line counts

id before after diff
enterpriseSearch 19 21 +2
securitySolution 413 417 +4
total +6

Total ESLint disabled count

id before after diff
enterpriseSearch 20 22 +2
securitySolution 497 501 +4
total +6

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

cc @adcoelho

@adcoelho adcoelho merged commit 6710a69 into elastic:main Jun 9, 2023
@kibanamachine kibanamachine added the backport:skip This commit does not require backporting label Jun 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:skip This commit does not require backporting Feature:Cases Cases feature release_note:skip Skip the PR/issue when compiling release notes Team:ResponseOps Label for the ResponseOps team (formerly the Cases and Alerting teams) technical debt Improvement of the software architecture and operational architecture v8.9.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants