Why your React App is so FAST (just like the Flash guys from TBBT above😜) & Optimised? Is it just React which does all this? The Answer is NO. Let's see how ✍🏻
Our Production code, we need it to be:
Minified (removing comments, etc)
Compressed
bundled the files,
Optimise the images if any,
Code Splitting,
Chunking
So a lot of processing needs to be done on local before you ship the code to PRODUCTION. This is how we are going to put energy & ignite our APP. *Does React is doing all these things? A big NO.*A bundler helps you to do all these above things. Eg: Webpack, Parcel, Vite, etc
When you use npx create react app. This created react app is already ignited and is production ready. It uses Webpack.
But we'll do everything from scratch & know how to build a production ready app without using npx create react app. You should know that so much engineering goes behind the scenes.
There are a lot of packages, libraries, etc that are required to make our production ready app & not just React. It is making fast but to an extent but there are a lot of other things. Let's see how can we get those packages into our project.
FYI : NPM - It's full form is not Node Package Manager. But it is everything (go to npm website/github and click on logo) except Node Package Manager. It manages packages but it's full form isn't that.
npm init - Initialise npm into our project
Package.json - A configuration for NPM
We're going to use Parcel as our Bundler & Ignite our App.
npm install -D parcel
-D stands for dev-dependency ⬇️
There are 2 types of dependency that our APP can have:
1. Normal Dependency: Can be used on Production also.
2. Dev Dependency: Required under Development Phase.
Package.json basically keeps the track of all the dependencies/packages installed.
- stores approx or exact version of dependencies installed
"parcel":"^2.8.3" (Carrot sign ^ : Allows automatic minor upgrades 2.8.3- > 2.8.4)
"parcel":"~2.8.3" (Tilde sign ~ : Allows automatic major upgrades 2.8.3 -> 3.0.0)
It is always safe to use Carrot sign (^) because minor upgrades are okay, but if we allow automatic major upgrades, something may break in code.
Package-lock.json - Locks the version or - stores exact version of all the dependencies & their transitive dependencies which our project is using.
"parcel": {
"version": "2.8.3",
"integrity": "sha512-.......", // A hash - To verify same version is on dev machine & as well as prod }
.....
}
Node Modules -Database to all the dependencies & transitive that our project will ever need
We needed a bundler & we installed Parcel as our Dependency. Now Parcel has its own package.json file which has it's own dependency. And these all dependencies may again have their own package.json file & dependencies. And so on... This is called as Transitive Dependencies.
All our project dependencies & transitive dependencies have their own folder consisting package.json. That's the reason node module are such huge. We do not include them (in .gitignore) when pushing to git repo or production. As this can be generated using**package.json & package-loc.json files (should be present in repo)
npm - to install a package
npx - to execute a package
Earlier we used CDN Links to import React into our project. (Refer Blog https://smitd.hashnode.dev/core-react-js-fundamentals). But its a costly operation as we make a separate network call.
Having React in our Node Modules only is a much faster way right! (like any other dependency)
So how do we do that? npm install react
&npm install react-dom
(As a normal dependency obviously)
And then we import React & ReactDOM into our JS file.
Also the script tag should be of type="module" in order to use import export in js file: <script type="module" src="App.js"></script>
And now we are using React & ReactDOM from node modules and not from any CDN links
Parcel - A BEAST
It Provides us:
- Dev Build
- Local Server
- HMR - Hot Module Replacement (Automatically Refreshing our page / Build AGAIN if any new changes saved in file)
- File Watching Algorithm (written in C++: Keeping Track of every save in project)
- Caching - Faster Builds (.parcel-cache) Due to this It always takes lesser time if we keep refreshing
- Image Optimisation (as image loading is the most costly thing on webpage)
- Minification of files on production
- Bundling
- Compress
- Content Hashing - Parcel automatically includes content hashes in the names of all output files. This enables long-term browser caching, because the output is guaranteed not to change unless the name does.
- Code Splitting - It supports zero-configuration code splitting out of the box. This allows you to split your application code into separate bundles that can be loaded on demand, resulting in smaller initial bundle sizes and faster load times.
- Differential Bundling - support of older browsers (Provide different type of bundle for different browsers and older versions - will add required things)
- Diagnostics
- Error Handlings (Good errors & suggestions)
- HTTPs (You can test on https)
- Tree Shaking Algorithm - (Remove unused code for you 😱 - if only 3 functions in use out of 5 -> it'll remove 2 unused fn.)
- Lazy Dev Builds
- Different Dev & Production Builds (Production takes more time - since it has more optimisation)
That's why we need a lot more things in order to make our web app faster & it's not just React.
Dev Buildnpx parcel index.html
-> Generates a Development build of your project & hosts it on http://localhost:1234/ and puts it up in the dist folder. And when we save new changes and it gets refreshed (Uses HMR)
Production Buildnpx parcel build index.html
-> Now it'll do tree shaking, bundle, minify, compress all files into 3 files - html, css & js (all in one line or fully compressed) - ThisPRODUCTION READYbuild is highly optimised and now ready to serve to users. It'll be Fast, Performant & Optimised
Folders or files which can be regenerated. Eg: node_modules
, dist
& .parcel-cache
.
-> Include these files in .gitignore
so that it cannot be pushed in git repo.
Let's make our APP compatible for older versions of browsers as well. For that we will use browserslist which is a transitive dependency of Parcel & is already been installed in node_modules.
//package.json
"browserslist": [
"last 2 Chrome versions",
"last 2 Firefox versions",
// "last 2 versions"
]
// This means that it'll definitely work in above mentioned configuration (Browser App versions)
// and might or might not work for the rest
It'll create different bundles i.e add some extra code if needed, for older browser versions. We sometimes don't want that to keep our code light. It actually depends on our App's end users.
If your app is a government website then it should for sure have support of oldest browser versions (almost 99% users should be able to use it).
(Explore https://browserslist.dev/ to see more possible configurations)
So using Parcel which has it's own dependencies eg: Browserslist, Babel, for HMR it might have some dependency, similarly for Tree-shaking, Caching, File-watching, etc. With all this stuff:
We have created our own create-react-app 💪
We have now created a Production Ready Build Application 🚀
as we have successfully IGNITED OUR APP ⚡️.
Thank you! Stay tuned for my upcoming blogs 🔥