React Manual Setup
Learning outcomes:
- Modularization in JavaScript
- What is a bundler
- Manual React setup using Rollup
Introduction
In the last chapter, we saw how to quickly set up a React development environment in either of two ways: by calling in external <script>
s on a simple HTML page or by using the Create React App tool.
Now in this chapter, which is an optional read, we shall see how to manually set up such an environment. We'll go through a multitude of concepts, including what are bundlers, the role of Babel, what exactly are react
and react-dom
, configuring npm scripts, and so on.
Honestly speaking, configuring React manually isn't that hard as it might seem like. In fact, it's recommended that every single React developer knows what goes behind the curtain when he/she is using a preconfigured, scaffolding tool like CRA.
This knowledge is key to being able to eject from such scaffolding tools and tune them according to our needs. Without a thorough understanding of these technicalities, we are just left to count on these preconfigured tools.
Modularization in JavaScript
When we build complex personal projects — think of a blog app, or a todo app, or a simple music player — it's a common pratice to break down our projects into individual files, or modules. This is often referred to as modularization.
It's exceptionally challenging to work in one single code file that's spans thousands of lines. Yes, we wouldn't have to constantly switch between different files in this case but the length of that one single file is enough to keep as away from even touching the code.
Modularization allows us to work with small individual files, one at a time, and then amalgamate them together to breathe life into a project.
There are multiple benefits of modularization:
- It allows for reusability. A repeated set of utilities could be put inside a module and then that module used wherever those utilities are needed.
- It allows for collaboration. One developer can work on module A, one can work on module B, another can work on module C, and so on.
- It significantly improves maintainability. Finding bugs and fixing them becomes way much easier when developers have smaller files to look into and isolate for testing.
Almost all popular languages recognize the importance of modularization and the fact that those languages would be used to create complex projects, and likewise provide modularization features out of the box.
Talking about JavaScript, even though it didn't begin with robust modularization features, after the advent of ES6, this finally became a reality in the language.
Modularizing our JavaScript projects is good, as in all languages, but not without a slight issue. Remember that we're talking about web apps here and those are served over HTTP.
The more modularized our code base is, that means the more files we need to call in on the client's end to get the app to run; which in turn means the more number of HTTP requests required to be dispatched and their responses consequently parsed; and ultimately, the longer the loading time of the app.
We just can't ignore the effects that loading multiple files have on the latency of a web app.
Apart from this, since ES6 modules are still a relatively recent feature, some old browsers don't support them. This means that if we use modules in our projects, we would be missing on some old browsers, which might be an issue if we want our apps to work correctly on those browsers as well.
Now the best solution to this seems to be to not modularize our JavaScript at all, or do it sparingly. Right?
Well, it would've been exactly this way had it not been for bundlers.
What is a bundler?
A bundler does a very simple job, already apparent in its name:
A bundler essentially does the same thing that we mentioned a moment ago, i.e. putting all of our code in one single file. But it does this without us having to do so.
That is, when using a bundler, we don't have to write our JavaScript code all in one single file (by virtue of the worry that modularization would lead to network latency or browser incompatibility); instead we can keep modularizing our code base while the bundler amalgamates it into one single file.
Bundlers offer benefits to both: an app's developers and its users.
- For developers, they could continue modularizing their projects as much as they need to. No limits.
- For users, they get much better loading times of the app since only a single file is requested for and thereafter delivered to their devices, and also less to almost no wastage of their resources.
Bundlers offer other benefits as well that go way beyond just modularization.
For example, bundlers can be used to minify JavaScript files as they are bundled together to save on countless of bytes and, thus, reduce file sizes. Bundlers can also be used to perform code splitting, which in essence is to call on additional scripts only when they are required by a web application.
In short, bundlers are just amazing!
In the JavaScript community, by far, the most popular bundler is Webpack.
Webpack is a complex beast in itself. There are whole books written purely for just configuring and working with Webpack — that's its level of complexity and configurability!
Besides Webpack, however, there exist a couple other bundler tools as well, lighter in weight and complexity, and suitable for simple projects like the ones we'll be creating throughout this course.
The bundler that we'll be using here is Rollup.

Rollup is an amazing alternative to Webpack, and evolving to become better than ever. The official documentation site explains the tool in an extremely nice way — surely worth a read.
Let's see how to install and set up Rollup, specifically to be able to develop React applications.
Manual setup using Rollup
Once again, before we begin our manual setup, it's important for you to have Node.js installed on your computer — for all our individual tools will be installed using npm.
Create a new react-course directory
With CRA, we supply it with the name of the directory to represent our React project and then it itself creates and configures everything in that directory.
Without CRA, however, we have to create the directory ourselves.
So, first things first, let's go on and create a react-course directory, again under Desktop in Windows. We'll do so using the terminal:
...\Desktop> mkdir react-courseThis command will create an empty directory named react-course in Desktop.
Obviously, the same thing could also be achieved using the graphical interface on Windows, i.e. by right-clicking on the Desktop and then creating a new folder using the context menu.Great! Let's proceed to the next step.
Create a workspace in VS Code
With the directory created, we need to open it up in VS Code as a workspace. To restate it, a workspace in VS Code is basically just a directory holding all the work of a project.
To open up a directory as a workspace, launch VS Code, and then from the Get Started window that shows up, select the Open Folder link. This will open up a file browser panel. From here, locate the react-course directory that you just created and then open it up.
This should create the directory as a new workspace in VS Code.
Over to the next step.
Create a package.json file
With the react-course directory created, next we'll create a package.json file in it.
What is package.json?
The purpose of a package.json file is fairly straightforward.
As we build our project and install numerous packages to drive it, package.json acts like the project's documentation, collecting the names of all the packages installed. This makes our project portable.
For instance, if we plan to publish the project to GitHub, then we only need to publish the actual code of the project along with package.json, NOT the installed packages. Anyone could then easily clone the GitHub repo on his/her machine and just run
npm install
to download the same packages that you were using on your end.Not only this, but package.json also documents the project being created, such as listing its version, the name of its author(s), its short description, its license, and so on. It's much more than just a mere JSON file — it's the core of npm (and other package management systems as well).
Now, you could create a package.json file yourself and then add the necessary details into it, or you could let
npm
do this for you by running the commandnpm init
.npm init
serves to initialize a new project in the current working directory. It asks a couple of questions from us regarding the project, which we can either fill out or leave out and go with the default values, in order to describe our project. In the end,npm init
creates a package.json file in the project.If you want to completely skip this questionaire phase, append a
-y
flag to the command. This simply means that all the defaults should be used for the package.json file.Below we run this command inside our react-course directory:
...\Desktop\react-course> npm init -yWrote to ...\Desktop\react-course\package.json: { "name": "react-course", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }At this stage, our VS Code workspace should look as follows:
package.json in our workspace.Now let's open up the package.json file created:
javascript{ "name": "react-course", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }
Everything is the exact same as mentioned in the console output. Perfect!
Let's move on.
Install Rollup
Once package.json is created, we need to install the bundler tool Rollup, represented by the
rollup
package on npm.Go ahead and type the following command in the console to install Rollup:
...\Desktop\react-course> npm install rollup --save-devIt launches an installer in the console, downloading Rollup, and then ends with the bundler installed locally inside the react-course directory, under a node_modules directory.
Also, as the command completes, our package.json file gets updated automatically to count
rollup
as one of its dependencies, specifically as a developer dependency.What is a dependency?
A dependency is simply anything that our project depends on.
In the case above, our projects depends on the
rollup
package, hence we say thatrollup
is a dependency of the project.package.json keeps track of all the dependencies of our projects. It's because of these dependency lists maintained by package.json that we're able to portably transfer projects containing a package.json file.
The other person using our project only needs the project files and package.json to replicate the same set of tools that we've using for our project on his/her end.
Isn't this amazing?
What is
--save-dev
?The
--save-dev
flag in the command above is used to instruct npm to treat the underlying dependency as a developer dependency.A developer dependency is a dependency that only applies while developing a program. That is, a developer dependency isn't used when actually running an application in the browser.
rollup
is only used when developing our React application, hence it's installed with this--save-dev
flag set.Here's the updated package.json file:
javascript{ "name": "react-course", "version": "1.0.0", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "description": "", "devDependencies": { "rollup": "^3.14.0" } }
Notice the
devDependencies
object. It listsrollup
as a dependency along with a description of which version we're using.Install Babel
We saw Babel in action above when we called on an external Babel library in our HTML page to parse and execute the
<script>
tag supposed to hold our React code.In this manner, Babel was acting as a runtime engine. It was parsing and executing our React code, all on its own. But as we stated before, there's a performance cost of doing all this parsing on the browser.
A much better approach is to parse the code and transpile it upfront to a syntax that can be directly executed by the browser, and do this just once.
Fortunately, Babel can do this as well!
Babel can be, and is customarily, used as a transpiler, converting innovative syntax into normal JavaScript that all modern browsers can easily understand.
In our Rollup setup, as you'll see in the next-to-next step, we'll be using Babel as the transpiler to help convert JSX code into corresponding, parseable JavaScript.
But before that, we first need to install Babel just like we installed Rollup above, and even before that we need to understand how Babel is organized in npm.
Babel is divided into multiple pieces:
- The core piece is represented by the package
@babel/core
. - With this core piece, Babel provides us with numerous plugins to install, depending on whether we want a particular feature or not.
For instance, if we want to write code for old browsers that don't support arrow functions, we can use the plugin
@babel/plugin-transform-arrow-functions
which will help convert them to regular anonymous functions.Managing multiple Babel plugins can quickly become cumbersome because there are too many of them, and that's why Babel provides us with predefined collections of plugins in the form of presets.
The preset that we're interested in for now is
@babel/preset-react
.@babel/preset-react
contains all the necessary plugins to be able to convert JSX code into normal JavaScript code.Let's go on and install both of these packages, which will eventually be used by our Rollup bundler:
...\Desktop\react-course> npm install @babel/core @babel/preset-react --save-devGreat.
Let's move on.
- The core piece is represented by the package
Install core React and React DOM
Recall from the previous chapter that we called in two external
<script>
s in our HTML page to be able to write React code in it. One was for React core while the other one was for React DOM.We need both of these libraries in our manual setup as well.
The React core library is represented by the
react
package while the React DOM library is represented byreact-dom
in npm.Enter the following command to install both of these packages at once:
...\Desktop\react-course> npm install react react-domNotice that we don't have the
--save-dev
flag here. This is because bothreact
andreact-dom
are used while running a React application in the browser; they aren't just used during development.Over to the next step.
Configure Rollup
Let's quickly review what packages we've installed so far in our project. We started off with
rollup
, then installed@babel/core
and@babel/preset-react
, and then finished off withreact
andreact-dom
.At this point, we indeed have almost all the tools that we need to be able to write and run React. But the tools haven't still been integrated together. That's what we're about to do in this section.
Go on and create a rollup.config.mjs file directly inside react-course:
rollup.config.mjs file in VS Code Explorer.So what exactly is this?
Like most tools have their own ways of representing their configuration files, Rollup has one too. It's called rollup.config.mjs.
The .mjs file extension is used because our configuration file would be using ECMAScript modules instead of traditional CommonJS modules used in Node.js. If we were to use the traditional CommonJS modules, we'd be naming our file as rollup.config.js.This is a JavaScript file, not a JSON file (like
package.json
), simply so that we have the all the power and flexibility of JavaScript while making our Rollup configurations.Now, let's roll up our sleeves and get working to configure Rollup to be able to run React code.
We've already covered how to use Rollup to set up a React development environment in this article from our blog. In order to keep this chapter short, we defer the setup of Rollup here to the Installing Rollup and its plugins section of the given article.
So before you proceed forward, get Rollup configured by going through the following link:
Installing Rollup and its plugins
After you're done with this, your react-course directory should look as follows:
react-course directory after Rollup has been configured.And your rollup.config.mjs file should look as follows:
JavaScriptimport nodeResolve from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; import babel from '@rollup/plugin-babel'; import replace from '@rollup/plugin-replace'; export default { input: 'src/index.js', output: { file: 'public/bundle.js', format: 'iife' }, plugins: [ nodeResolve({ extensions: ['.js', '.jsx'] }), babel({ babelHelpers: 'bundled', presets: ['@babel/preset-react'], extensions: ['.js', '.jsx'] }), commonjs(), replace({ preventAssignment: false, 'process.env.NODE_ENV': '"development"' }) ] }
If everything on your end is the same, wonderful!
Here's the index.js file from our react-course directory:
The index.js file in our setup.It's empty and waiting for some code to be added to it, and that's exactly what we'll be doing in the next chapter. Let's keep going.
Configuring a
build
npm scriptOpen up the package.json file and head over to the section that reads
scripts
. In this step, we'll be configuring a manual npm script so that we can very conveniently launch Rollup's bundling process.We'll call the script
build
because Rollup actually 'builds' a bundle by amalgamating all linked modules. This script will be run by entering the commandnpm run build
into the terminal.As for the script itself, it'll simply be
rollup -c -w
. Let's understand what's happening here:rollup
invokes therollup
package that we installed a while ago — it's the very heart of Rollup.- The
-c
flag instructs Rollup to use a configuration file in the underlying directory instead of expecting for the configurations to be provided in the terminal. - The
-w
flag instructs Rollup to watch for any changes to the project and re-bundle if any file therein get modified.
In the following code, we define the
build
script:JSON{ "name": "react-course", "version": "1.0.0", "main": "index.js", "scripts": { "build": "rollup -c -w" "test": "echo \"Error: no test specified\" && exit 1" }, ... }
With the script created, now go on to the terminal again, and enter the command
npm run build
:...\Desktop\react-course> npm run buildThis will commence the bundling process, which might take a few seconds to complete. Once complete, we'll have a bundle.js file in the public directory, containing our bundled code.
Moreover, thanks to the
-w
flag, the process will keep running, watching for changes in our project files and then automatically re-running the bundler in the instance of any file changing.Obviously, since our index.js file is empty right now, the bundle would be empty as well. In the upcoming chapters, however, when we finally write some React code, our bundle would have a lot of code in it.
Anyways, it's time for the final step.
Installing
serve
and configuringnpm start
While Rollup bundles our React project files that resides under src into a single file inside public, we still don't have anything to serve our index.html file from a server.
That is, currently the only way to view the index.html file is to open it up as a mere file from the filesystem (using the
file
URI scheme).However, React discourages developing applications in this way. The recommended approach is to use a web server, serving up the index.html file (using the
http
URI scheme).Fortunately, using the
serve
package from npm, it's really simple to spin up a web server, serving up our public directory.First off, let's install
serve
from npm as a normal dependency:...\Desktop\react-course> npm install serveNext up, let's create an npm
start
script in our package.json, invoking theserve
package. The invocation is pretty simple; just callserve ./public
to serve the public directory over http://localhost:3000:Following we define the
start
script:JSON{ "name": "react-course", "version": "1.0.0", "main": "index.js", "scripts": { "start": "serve ./public" "build": "rollup -c -w" "test": "echo \"Error: no test specified\" && exit 1" }, ... }
Now, go on and run the following command in the terminal (assuming that the previous command
npm run build
is still running in another terminal):...\Desktop\react-course> npm startThis will launch a web server, serving the public directory over http://localhost:3000. Open up the browser and navigate to this URL to see the index.html file in the public directory in action.
Once everything is done, close all the terminals, for you have successfully seen how to launch a React application with this manual setup.
Spread the word
Think that the content was awesome? Share it with your friends!
Join the community
Can't understand something related to the content? Get help from the community.