Skip to content

Commit 1b3ded9

Browse files
committed
feat: lazy loading and code splitting.
1 parent 80c1520 commit 1b3ded9

File tree

9 files changed

+1909
-1478
lines changed

9 files changed

+1909
-1478
lines changed

craco.config.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ module.exports = {
2424
},
2525
webpack: {
2626
configure: (webpackConfig, { env, paths }) => {
27-
// Disable sourcemaps for production if needed
28-
// if (env === 'production') {
29-
// webpackConfig.devtool = false;
30-
// }
27+
// Disable sourcemaps for production
28+
if (env === 'production') {
29+
webpackConfig.devtool = false;
30+
}
3131

3232
// Add a rule to ignore source map warnings from node_modules
3333
webpackConfig.module.rules.push({

public/posts/posts.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,22 @@
11
[
2+
{
3+
"slug": "reducing-react-app-size",
4+
"title": "Reducing React App Bundle Size: A Practical Guide",
5+
"date": "2025-11-27",
6+
"updated": "2025-11-27",
7+
"description": "How I reduced the main bundle size by over 70% using code splitting and disabling source maps.",
8+
"tags": [
9+
"react",
10+
"performance",
11+
"optimization",
12+
"lazy-loading",
13+
"craco"
14+
],
15+
"category": "dev",
16+
"filename": "reducing-react-app-size.txt",
17+
"authors": ["fezcode"],
18+
"image": "/images/defaults/visuals-2TS23o0-pUc-unsplash.jpg"
19+
},
220
{
321
"slug": "mastering-tailwind-centering",
422
"title": "Mastering Tailwind CSS: The \"Absolute Centering\" Trick",
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
Web performance is crucial for user experience. A slow-loading website can drive visitors away before they even see your content. Recently, I noticed that **Fezcodex** was taking a bit too long to load, so I decided to investigate and optimize the production build.
2+
3+
Here's how I managed to reduce the main bundle size by over **70%**, shrinking `main.js` by approximately **590 kB**.
4+
5+
## The Diagnosis
6+
7+
When I ran the build command, I noticed the generated `main.js` file was quite large. In a standard Create React App (CRA) setup, the entire application is often bundled into a single JavaScript file. This means a user has to download *every* page and component just to see the homepage.
8+
9+
## Strategy 1: Code Splitting with `React.lazy` and `Suspense`
10+
11+
The most effective way to reduce the initial bundle size is **Code Splitting**. Instead of loading the entire app at once, we split the code into smaller chunks that are loaded on demand.
12+
13+
React provides built-in support for this via `React.lazy` and `Suspense`.
14+
15+
### Before:
16+
All pages were imported statically at the top of the routing file:
17+
18+
```javascript
19+
import HomePage from '../pages/HomePage';
20+
import BlogPage from '../pages/BlogPage';
21+
import ProjectsPage from '../pages/ProjectsPage';
22+
// ... diverse imports
23+
```
24+
25+
### After:
26+
I refactored the imports to be lazy loaded:
27+
28+
```javascript
29+
import React, { lazy, Suspense } from 'react';
30+
import Loading from './Loading'; // A simple spinner component
31+
32+
// Lazy Imports
33+
const HomePage = lazy(() => import('../pages/HomePage'));
34+
const BlogPage = lazy(() => import('../pages/BlogPage'));
35+
const ProjectsPage = lazy(() => import('../pages/ProjectsPage'));
36+
// ...
37+
```
38+
39+
And wrapped the routes in `Suspense`:
40+
41+
```javascript
42+
function AnimatedRoutes() {
43+
return (
44+
<Suspense fallback={<Loading />}>
45+
{/* Routes ... */}
46+
</Suspense>
47+
);
48+
}
49+
```
50+
51+
This change ensures that the code for `BlogPage` is only downloaded when the user actually navigates to `/blog`.
52+
53+
### How Does the Builder Know?
54+
55+
You might wonder: *How does the build tool (Webpack, in this case) know to separate these files?*
56+
57+
It all comes down to the **dynamic `import()` syntax**.
58+
59+
1. **The Trigger:** Standard imports (e.g., `import X from 'Y'`) are static; Webpack bundles them immediately. When Webpack encounters `import('...')`, it recognizes a **split point**.
60+
2. **Chunk Generation:** Webpack cuts that specific module (and its unique dependencies) out of the main bundle and creates a separate file, known as a **chunk**.
61+
3. **The Glue:** The main bundle retains a tiny instruction. It effectively says, "When the application needs this component, send a network request to fetch this specific chunk file."
62+
63+
`React.lazy` and `Suspense` simply manage the UI state (like showing the loading spinner) while that asynchronous network request is happening.
64+
65+
## Strategy 2: Disabling Source Maps in Production
66+
67+
Source maps are incredibly useful for debugging, as they map the minified production code back to your original source code. However, they are also very large.
68+
69+
By default, Create React App generates source maps for production builds. While the browser only downloads them if you open the developer tools, they still occupy space on the server and can slow down deployment pipelines.
70+
71+
I disabled them in my `craco.config.js` (since I'm using CRACO to override CRA settings):
72+
73+
```javascript
74+
webpack: {
75+
configure: (webpackConfig, { env }) => {
76+
// Disable sourcemaps for production
77+
if (env === 'production') {
78+
webpackConfig.devtool = false;
79+
}
80+
return webpackConfig;
81+
},
82+
},
83+
```
84+
85+
## The Results
86+
87+
The impact was immediate and significant.
88+
89+
* **Before:** `main.js` was heavy, containing the entire application logic.
90+
* **After:** `main.js` reduced by **~590 kB**.
91+
92+
Now, the initial load is snappy, and users only download what they need. If you're building a React app with many routes, I highly recommend implementing code splitting early on!

public/rss.xml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,24 @@
99
<link>https://fezcode.com</link>
1010
</image>
1111
<generator>RSS for Node</generator>
12-
<lastBuildDate>Wed, 26 Nov 2025 19:00:46 GMT</lastBuildDate>
12+
<lastBuildDate>Thu, 27 Nov 2025 12:50:03 GMT</lastBuildDate>
1313
<atom:link href="https://fezcode.com/rss.xml" rel="self" type="application/rss+xml"/>
14-
<pubDate>Wed, 26 Nov 2025 19:00:46 GMT</pubDate>
14+
<pubDate>Thu, 27 Nov 2025 12:50:03 GMT</pubDate>
1515
<copyright><![CDATA[2025 Ahmed Samil Bulbul]]></copyright>
1616
<language><![CDATA[en]]></language>
1717
<managingEditor><![CDATA[samil.bulbul@gmail.com (Ahmed Samil Bulbul)]]></managingEditor>
1818
<webMaster><![CDATA[samil.bulbul@gmail.com (Ahmed Samil Bulbul)]]></webMaster>
1919
<ttl>60</ttl>
20+
<item>
21+
<title><![CDATA[Reducing React App Bundle Size: A Practical Guide]]></title>
22+
<description><![CDATA[[object Object]]]></description>
23+
<link>https://fezcode.com/#/blog/reducing-react-app-size</link>
24+
<guid isPermaLink="false">https://fezcode.com/#/blog/reducing-react-app-size</guid>
25+
<dc:creator><![CDATA[Ahmed Samil Bulbul]]></dc:creator>
26+
<pubDate>Thu, 27 Nov 2025 00:00:00 GMT</pubDate>
27+
<content:encoded><![CDATA[<p>Web performance is crucial for user experience. A slow-loading website can drive visitors away before they even see your content. Recently, I noticed that <strong>Fezcodex</strong> was taking a bit too long to load, so I decided to investigate and optimize the production build.</p>
28+
<p><a href="https://fezcode.com/#/blog/reducing-react-app-size">Read more...</a></p>]]></content:encoded>
29+
</item>
2030
<item>
2131
<title><![CDATA[Mastering Tailwind CSS: The "Absolute Centering" Trick]]></title>
2232
<description><![CDATA[[object Object]]]></description>

0 commit comments

Comments
 (0)