Unlocking the Power of JavaScript: Reduce Your NPM Package Size by 99%

Ali Osman Menekse
Insider Engineering
5 min readSep 25, 2023
Photo by Austin Ramsey on Unsplash

Let me continue to kick off my writings with beloved book quotes.

Planning is important, but the most important part of every plan is to plan on the plan not going according to plan
- Morgan Housel

In this article, I will discuss how we improved Lighthouse metrics from 38% to 82% and reduced FCP (First Contentful Paint) time from 5.7 seconds to around 1.0~1.7 seconds in projects where we use the Design System package.

Lighthouse Metrics
Lighthouse Metrics

Let me begin by explaining how we got here. We as Insider development team have developed 11 different products for our company, and to better manage the front-end part of these products, we utilized the Design System. You can find the relevant article here.

Since the Design System contained all components, a 13.6 MB JavaScript file was built. As you can imagine, downloading a 13.6 MB package for the initial load, even if you’re using a single-page application, gives a negative impression of your performance and doesn’t make the user happy.

13 MB design system file that has been built

So, what did we do?

We started by separating the products from each other, and now each of them continues to exist in separate repositories. This helped us reduce FCP from 5.7 seconds to 3.4 seconds. However, the topic of how we separated the products is for another article.

We have a VueJS NPM package which we build with Webpack. Initially, we switched from Webpack to Vite, which reduced the package size from 13.6 MB to 6 MB. But that wasn’t enough.

6 MB (gzip:1.3 MB) design system file that has been built

So, what was different about Vite?

  1. Fast Development Server: Vite can start the development server quickly, allowing you to see changes instantly. This significantly speeds up the development process and provides real-time feedback.
  2. Modular Development: Vite has a modular structure, giving each component and module its own scope. This allows you to work on independent modules.
  3. Dynamic Import Support: Vite supports dynamic imports, which allows it to better analyze dependencies and only compile the modules that are used.
  4. ESModule Usage: Vite uses the ESModule standard, enabling the use of modern JavaScript modules, which are more efficient than older module systems like CommonJS.
Webpack Bundle Mechanism
Vite Bundle Mechanism

6 MB (gzip:1.3 MB) with Vite seemed sufficient, right?

When we built the Design System, it was producing a single JavaScript file and assets. This meant that on each refresh, we had to load 1.3 MB. As you can see in the code below, in index.js, we were exporting all components, resulting in a single large built JS file. Yes, we had reduced it to 1.3 MB with Vite, but it needed to be further reduced.

Exported Design System Components

This is where we decided that using RollupJS to go for a component-based build system would be more logical. Each component could now be exported individually, and during the build, each component would only be built for itself. This way, we wouldn’t have to load unnecessary components for the page the user entered. This allowed us to download smaller pieces without being affected by bandwidth throttling, providing faster returns for other necessary requests, and ensuring that our page opened earlier.

But how?

We configured each component individually, resulting in a unique JS build for each one. This approach enables us to use each component separately as needed.

vite.config.js (Function can be written for this part)

As a result, we successfully reduced the package size to as low as 4 KB, depending on the components used, with an average component size of 35 KB.

The size of the built design system components
Lighthouse Metrics

In summary, in this article, we discussed ways to improve Lighthouse metrics and FCP time significantly in projects using the Design System package. First, we understood how a 13.6 MB JavaScript file negatively affected the user experience and took various steps to address this issue.

First, we organized the projects into separate repositories, reducing FCP from 5.7 seconds to 3.4 seconds. Then, we switched from Webpack to Vite, which reduced the package size from 13.6 MB to 6 MB. By using RollupJS to export each component individually, we were able to reduce the package size even further, resulting in a download size as low as 4KB, allowing users to download only the necessary components which has enabled users to experience FCP times as fast as 1~ second.

However, the journey to improving performance is not over. There are more steps we can take to make our web applications faster and more efficient. I’ll discuss these topics in my upcoming articles. Until then, stay tuned!

  • Fallbacks for font loading
  • Minification
  • Compression
  • Image optimization
  • Code splitting
  • Metric tracking
  • CDN usage
  • Lazy loading
  • Browser caching.

If you are interested in topics related to front-end architecture, be sure to check out this article. Don’t forget to follow the Insider Engineering Blog for more insightful articles! ✍️

--

--