React from scratch Part 1
Jakob Klamser
Posted on August 29, 2020
In this series we will get to know React, Webpack, Babel and Redux. For the first part of this series we will begin with a basic setup. Let's get started!
Prerequisites
In this guide we will be using npm to install all the dependencies and kick start the project.
So make sure you got npm installed on your machine!
Basic setup
First of all we create a folder to store our project in and go into it to initialize npm:
$ mkdir getting-started-react
$ cd ./getting-started-react
$ npm init -y
Now we are gonna add some of our dependencies and a new folder called src:
$ mkdir src
$ npm i react react-dom
Inside that src directory we need to create a file called index.js with the following content:
import React, { StrictMode } from 'react';
import ReactDOM from 'react-dom';
const App = () => {
return <div>Hello World!</div>;
};
ReactDOM.render(
<StrictMode>
<App />
</StrictMode>,
document.querySelector('#root'),
);
The function App returns a div with the content Hello World.
After that we call the render method of ReactDOM to insert our div into the HTML document.
The div will be inserted into the HTML-Element with the id of root.
For the code above to work we need to create such an HTML document.
So let's create a file called index.html with this content:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Getting Started: React</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app!</noscript>
<div id="root"></div>
</body>
</html>
In this file you see the HTML-Element with the id root!
Webpack and Babel
The next step is to setup our development server and bundle our files, so we can actually see what we just created.
For that we need to add some more dependencies to our project and a new folder:
$ mkdir webpack
$ npm i webpack webpack-cli
$ npm i -D @babel/core babel-loader @babel/preset-env @babel/preset-react @babel/plugin-transform-runtime babel-plugin-transform-class-properties html-webpack-plugin webpack-dev-server
What exactly did we install here? Here is a small overview, for more information click the links:
- webpack: Webpacks purpose is to bundle JavaScript files for the usage in the browser. It is highly configurable.
- webpack-cli: A command line interface for the bundler Webpack.
- html-webpack-plugin: A plugin for webpack to simplify the generation of HTML files.
- webpack-dev-server: A webpack dev server with live reloading mechanism.
- @babel/core: Babel takes your ECMAScript 2015 and onwards and makes it backwards compatible for older browsers.
- babel-loader: To use babel in conjunction with webpack you need this loader for webpack.
- @babel/preset-env: Handles backwards compatibility for older browsers.
- @babel/preset-react: Handles React plugin in babel.
- @babel/plugin-transform-runtime: Reduces code size.
- babel-plugin-transform-class-properties: Transforms static class properties in babel.
Now that we have all our dependencies installed it is time to configure webpack, babel and our webpack-dev-server.
First of all we start with configuring babel by creating a new file in our root directory called .babelrc with the following configuration:
{
"presets":
[
"@babel/preset-env",
"@babel/preset-react"
],
"plugins": [
"babel-plugin-transform-class-properties",
["@babel/plugin-transform-runtime", {
"regenerator": true
}]
]
}
With that we configured which presets and plugins babel should use.
After that we create our webpack configuration. For that we need a new file called webpack.config.js in our webpack directory.
The configuration is as follows:
const path = require('path');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const baseURL = path.resolve(__dirname, '..');
module.exports = {
entry: path.resolve(baseURL, 'src', 'index.js'),
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: `${baseURL}/src/index.html`,
filename: './index.html',
inject: 'body',
})
]
};
We added the babel-loader to our webpack config and configured our HtmlWebPackPlugin to find the index.html we created earlier.
For that we used path to get the correct path at any time.
Now it is time to get the webpack-dev-server started. To do that we modify our scripts in our package.json:
"scripts": {
"start": "webpack-dev-server --mode development --open --config ./webpack/webpack.config.js",
"build": "webpack --mode production --config ./webpack/webpack.config.js"
},
If you run the following command now, a browser window should open and display Hello World!
$ npm start
More Loaders
Next we will be adding more loaders to our webpack configuration. We need loaders for our stylesheets and for our assets, e.g. PNG-, JPG-Files.
First we go ahead and add the necessary loaders as dependencies to our package.json.
$ npm i -D sass sass-loader style-loader css-loader file-loader
For this project I chose to use SASS instead of CSS, that's why we need to install the npm package sass too.
Next we install all the loaders necessary to break down our SASS to CSS and then load it into our HTML.
To use these loaders we need to modify our webpack.config.js like that:
const path = require('path');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const baseURL = path.resolve(__dirname, '..');
module.exports = {
entry: path.resolve(baseURL, 'src', 'index.js'),
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
},
{
test: /\.s[ac]ss$/i,
exclude: /node_modules/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
'sass-loader',
],
},
{
test: /\.(png|jpe?g|gif)$/,
loader: 'file-loader'
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: `${baseURL}/src/index.html`,
filename: './index.html',
inject: 'body',
})
]
};
Important to note is that the style-loader needs to be the first in the use-array, as webpack loads him as last.
So first we collect all sass and css files and then we load them via the style-loader into the DOM.
The file-loader resolves files into a url that you can use in your js-files.
Styles and assets
Last but not least we will add a scss-file and an image to our project, to see if our loaders work as expected.
For that we create a file called index.scss in the src-folder and add the following content:
body {
background-color: red;
}
To use this file we simply add the following line to the import-statements of index.js:
import './index.scss';
If you start your development server now, our project should have a red background color.
Next up we will add a new subfolder to the src-folder called assets.
Just put in some random image inside the assets folder.
To display this image we have to change up our index.js like this:
import React, { StrictMode } from 'react';
import ReactDOM from 'react-dom';
import './index.scss';
import img from './assets/your-image-name.png';
const App = () => {
return (
<div>
<img src={img} />
<div>Hello World!</div>
</div>
);
};
ReactDOM.render(
<StrictMode>
<App/>
</StrictMode>,
document.querySelector('#root'),
);
We import the image at the top of the file and then use it as the src-attribute in the HTML-img-tag.
If you restart your webpack-dev-server via npm start, you should be able to see the image you put into the assets-folder.
Conclusion
So we are done for part 1 of this series. We setup a basic react-app with webpack as our bundler and babel for the backwards-compatibility.
We configured webpack to accept SCSS, HTML, JavaScript and image files.
And we added webpack-dev-server as our development server, to quickly see what we changed in the browser.
In the next part we start with creating a real application with react.
All the code for this multipart series can be found in this GitHub-Repository.
Posted on August 29, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.