Performance Pattern
Bundle Splitting
When building a modern web application, bundlers such as Webpack or Rollup take an applicationâs source code, and bundle this together into one or more bundles. When a user visits a website, the bundle is requested and loaded in order to display the data to the userâs screen.
JavaScript engines such as V8 are able to parse and compile data thatâs been requested by the user as itâs being loaded. Although modern browsers have evolved to parse and compile the code as quickly and performantely as possible, the developer is still in charge of optimizing two steps in the process: the loading time and execution time of the requested data. We want to make sure weâre keeping the execution time as short as possible to prevent blocking the main thread.
Even though modern browsers are able to stream the bundle as it arrives, it can still take a significant time before the first pixel is painted on the userâs device. The bigger the bundle, the longer it can take before the engine reaches the line on which the first rendering call has been made. Until that time, the user has to stare at a blank screen for quite some time, which can be.. highly frustrating!
We want to display data to the user as quickly as possible. A larger bundle leads to an increased amount of loading time, processing time, and execution time. It would be great if we could reduce the size of this bundle, in order to speed things up.
Instead of requesting one giant bundle that contains unnecessary code, we can split the bundle into multiple smaller bundles!
By bundle-splitting the application, we can reduce the time it takes to load, process and execute a bundle! By reducing the loading and execution time, we can reduce the time it takes before the first content has been painted on the userâs screen, the First Contentful Paint, and the time it takes before the largest component has been rendered to the screen, the Largest Contentful Paint.
Although being able to see data on our screen is great, we donât just want to see the content. In order to have a fully functioning application, we want users to be able to interact with it as well! The UI only becomes interactive after the bundle has been loaded and executed. The time it takes before all content has been painted to the screen and has been made interactive, is called the Time To Interactive.
A bigger bundle doesnât necessarily mean a longer execution time. It could happen that we loaded a ton of code that the user wonât even use! Maybe some parts of the bundle will only get executed on a certain user interaction, which the user may or may not do!
The engine still has to load, parse and compile code thatâs not even used on the initial render before the user is able to see anything on their screen. Although the parsing and compilation costs can be practically ignored due to the browserâs performant way of handling these two steps, fetching a larger bundle than necessary can hurt the performance of your application. Users on low-end devices or slower networks will see a significant increase in loading time before the bundle has been fetched.
The first part still had to be loaded and processed, even though the engine only used the last part of the file in order to . Instead of intially requesting parts of the code that donât have a high priority in the current navigation, we can separate this code from the code thatâs needed in order to render the initial page.
By bundle-splitting the large bundle into two smaller bundles, main.bundle.js and emoji-picker.bundle.js, we reduce the initial loading time by fetching a smaller amount of data.
In this project, weâll cover some methods that allow us to bundle-split our application into multiple smaller bundles, and load the resources in the most efficient and performant ways.