Add Code Splitting to Reduce JS Bundle Size #5670

Closed
DispatchCommit wants to merge 12 commits from feat/code-splitting into feat/go-live
DispatchCommit commented 2021-03-14 10:33:44 +01:00 (Migrated from github.com)

Our current JS Bundle has now begun to bloat to nearly an entire 5mb!

Well, 4.97mb to be exact.... That is a large file, and with a 10mb/s internet connection, that's approximately 5 seconds to load.

The reason this file is such a large size is because that 5mb file contains all the javascript, for the entire site, regardless of whether we ever even see any of the pages it contains the code for.

As the react docs say:

Code-splitting your app can help you “lazy-load” just the things that are currently needed by the user, which can dramatically improve the performance of your app. While you haven’t reduced the overall amount of code in your app, you’ve avoided loading code that the user may never need, and reduced the amount of code needed during the initial load.

One way to split a bundle is to use Route-based code splitting.

Deciding where in your app to introduce code splitting can be a bit tricky. You want to make sure you choose places that will split bundles evenly, but won’t disrupt the user experience.
A good place to start is with routes. Most people on the web are used to page transitions taking some amount of time to load. You also tend to be re-rendering the entire page at once so your users are unlikely to be interacting with other elements on the page at the same time.

Enter some multicursor editing of the imports and adding a suspense wrapper to the component, and voila, code splitting is added.

I also took this opportunity to reorganize some of the imports to be more alphabetical because with the amount of imports as we have in this file, it makes finding the import you're want easier.

Enough explanation, how about the results?

The resulting bundle js size is... smaller. 10% smaller.

I managed to reduce the bundle size from 4.97mb to 4.40mb. Not a huge improvement, but this is a very simple way to code split, without having to spend much time or effort identifying where our largest assets exist, and how to code split those separately.

At some later point, we can revisit code-splitting in-depth, but for now, this gives a fair size reduction to the initial js bundle, and anything is still better than nothing.

note: I haven't verified that every route still works and functions properly without any issue, so there may be slight issues.
One potential flaw I can think of is that we may not want to lazy load an error page / error template, in case whatever error we encounter disrupts our network and may prevents us from dynamically loading an error component and page. So this should be investigated and explored to some degree.

All the codesplit files generated:
image

Bundle size before codesplitting diet:
image

Bundle size after codesplitting diet:
image

Time to compile old bunlde js file without codesplitting:

Time: 123230ms

Time to compile codesplit js file:

Time: 119687ms

The timing difference seems identical within an reasonable window of error margins (though if anything it suggests codesplitting was slightly faster though, but that's likely timing error)

/endoptimization

Our current JS Bundle has now begun to bloat to nearly an entire 5mb! Well, 4.97mb to be *exact*.... That is a large file, and with a 10mb/s internet connection, that's approximately 5 seconds to load. The reason this file is such a large size is because that 5mb file contains *all* the javascript, for the *entire* site, regardless of whether we ever even see any of the pages it contains the code for. As the react docs say: > Code-splitting your app can help you “lazy-load” just the things that are currently needed by the user, which can dramatically improve the performance of your app. While you haven’t reduced the overall amount of code in your app, you’ve avoided loading code that the user may never need, and reduced the amount of code needed during the initial load. One way to split a bundle is to use [Route-based code splitting](https://reactjs.org/docs/code-splitting.html#reactlazy). > Deciding where in your app to introduce code splitting can be a bit tricky. You want to make sure you choose places that will split bundles evenly, but won’t disrupt the user experience. > A good place to start is with routes. Most people on the web are used to page transitions taking some amount of time to load. You also tend to be re-rendering the entire page at once so your users are unlikely to be interacting with other elements on the page at the same time. Enter some multicursor editing of the imports and adding a `suspense` wrapper to the component, and voila, code splitting is added. I also took this opportunity to reorganize some of the imports to be more alphabetical because with the amount of imports as we have in this file, it makes finding the import you're want easier. ## Enough explanation, how about the results? The resulting bundle js size is... smaller. **10%** smaller. I managed to reduce the bundle size from 4.97mb to 4.40mb. Not a *huge* improvement, but this is a very simple way to code split, without having to spend much time or effort identifying where our largest assets exist, and how to code split those separately. At some later point, we can revisit code-splitting in-depth, but for now, this gives a fair size reduction to the initial js bundle, and anything is still better than nothing. **note**: I haven't verified that every route still works and functions properly without any issue, so there may be slight issues. One potential flaw I can think of is that we may not want to lazy load an error page / error template, in case whatever error we encounter disrupts our network and may prevents us from dynamically loading an error component and page. So this should be investigated and explored to some degree. All the codesplit files generated: ![image](https://user-images.githubusercontent.com/45262335/111063627-9ff28800-8464-11eb-88cb-54b8c8a6627e.png) Bundle size before codesplitting diet: ![image](https://user-images.githubusercontent.com/45262335/111063640-b00a6780-8464-11eb-8334-b3cd07b3eeda.png) Bundle size after codesplitting diet: ![image](https://user-images.githubusercontent.com/45262335/111063655-c1537400-8464-11eb-92ca-cdd3548bdf63.png) Time to compile old bunlde js file without codesplitting: ``` Time: 123230ms ``` Time to compile codesplit js file: ``` Time: 119687ms ``` The timing difference seems identical within an reasonable window of error margins (though if anything it suggests codesplitting was slightly faster though, but that's likely timing error) /endoptimization
neb-b commented 2021-03-22 00:59:39 +01:00 (Migrated from github.com)

closing this for now

closing this for now

Pull request closed

Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: LBRYCommunity/lbry-desktop#5670
No description provided.