How to reduce Javascript file load time?
Introduction
JavaScript typically takes a significant amount of time to load a file that has a large size.
If you use a bundler, it will create a bundle file with a very large size, making it difficult for us to manage the code inside it and often resulting in unused JavaScript code.
Here is how you can solve it.
Code Splitting & Dynamic Imports
The technique of Code Splitting is needed to make the file smaller and load them on demand. This practice can also be done by create multiple files to split your code, making them easier to manage and helping to avoid unused JavaScript code.
Let's assume you have a React component that you want to load asynchronously:
import React from 'react';
const MyComponent = () => {
return (
<div>
<h1>Antek-antek async!</h1>
</div>
);
};
export default MyComponent;
Now, you can use Dynamic Imports to load this component only when needed:
import React, { useState } from 'react';
const App = () => {
const [isComponentLoaded, setIsComponentLoaded] = useState(false);
let MyComponent;
const loadComponent = async () => {
if (!MyComponent) {
MyComponent = (await import('./MyComponent')).default;
setIsComponentLoaded(true);
}
};
return (
<div>
<h1>My App</h1>
<button onClick={loadComponent}>Load Component</button>
{isComponentLoaded && <MyComponent />}
</div>
);
};
export default App;
In this example, the MyComponent
is loaded only when the "Load Component" button is clicked. This is a simple form of code splitting where you dynamically import a module when it's needed.
Keep in mind that the specific implementation might vary based on your build tools and bundlers (Webpack, Parcel, etc.).
Tree shaking
The term "tree shaking" in the context of JavaScript and build tools refers to the process of eliminating dead (unused) code from your final bundled JavaScript file.
The name "tree shaking" is metaphorical and comes from the idea of shaking a tree to make the dead leaves fall off, leaving only the healthy and needed parts.
Here's a breakdown of the metaphor:
- Tree
- In the context of JavaScript bundling, the "tree" often represents the entire module dependency tree of your application. Each module can have dependencies on other modules, forming a tree-like structure.
- Shaking
- "Shaking" implies the process of removing or eliminating unwanted or dead parts. In the case of tree shaking, it refers to the removal of unused code or modules.
Many popular bundlers, such as webpack, Rollup, or Vite, use a tree-shaking approach while building the JavaScript chunks that you ship to the browser.
To facilitate tree shaking in a bundle, always use the modern ES6 syntax in your JavaScript code.
// default import
import CheckMeDuringBundle from 'Components'
// named import
import { CheckMeDuringBundle } from 'Components'
// default export
export default CheckMeDuringBundle
// named export
export { CheckMeDuringBundle }
Javascript Minification
JavaScript typically takes a significant amount of time to load a file that has a large size.
To address this issue, you can employ "JavaScript Minification," which reduces the time required for browsers to download your files.
Minifying all your code took a considerable amount of time. To expedite this process, you can utilize online "JavaScript Minifier" online tools or libraries such as Terser, Uglify, Babel-minify, the Google Closure Compiler (recommended), and so on.
Below is an example of a JavaScript code before and after minification:
Before
function addNumbers(a, b) {
// This function adds two numbers
return a + b;
}
let result = addNumbers(5, 10);
console.log("Result:", result);
After
function addNumbers(a,b){return a+b}let result=addNumbers(5,10);console.log("Result:",result);
Load your Javascript file asynchronously
JavaScript introduces two attributes (async and defer) to help determine whether you want to load your JavaScript asynchronously or defer its loading (in parallel).
Async: Follows a load-first order, where the script that loads first runs first. It can load at any time without waiting for the page to finish rendering or parsing.
Defer: Follows a code order, where the script that is called first runs first. It is executed after the DOM has loaded, been rendered, or parsed, and before DOMContentLoaded.
In many cases, adding both async and defer is recommended to prevent issues with async not working, with defer serving as a fallback.
<script async defer src="file.js"></script>
Another tips
- Lazy loading (I will post about it after this one).
- Check for unused and deprecated libraries and remove them from your bundler.
- Choose minimal libraries; avoid using something like lodash.