May 14th, 2019 - 5 min read
In this how to guide I'd like to explain how you can easily setup a React app from scratch with-out using Create React App (CRA)
But let me summarize the features we're having with this setup:
Typescript support should be easy to add but not added here.
First create a new directory with mkdir your-new-project
and cd your-new-project
then inside the directory run yarn init -y
to initialze your project.
Next we can install our dependencies with yarn add react react-dom sass
and yarn add @babel/core parcel-bundler @babel/plugin-proposal-class-properties @babel/preset-react -D
to install the devDependencies.
Now you're having every dependency ready. Let's create our scripts and wire everything into the scripts section of the package.json
file.
We can start by adding the following scripts & main entry to package.json
:
{
...,
"main": "./public/index.html",
"scripts": {
"start": "parcel ./public/index.html --open",
"build": "parcel build ./public/index.html"
},
...
}
To start the development server you can run yarn start
and this will launch the devServer with hot reloading for us.
build
is creating the production files into dist
directory.
So the basic setup is ready and we can add the missing files to have something we can render in the browser.
Create an index.html
file with the following content in the folder public
:
<!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>Parcel example app</title>
</head>
<body>
<div id="root"></div>
<script src="../src/index.js">
</script>
</body>
</html>
Here we're adding the div where React will be rendered and the script tag with a relative path one level up because we're in folder public
. The index.js
is the entry point of our application and that's the next file we will add.
The index.js
is your React app similar to the following code:
import React, { Component } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
import styles from "./styles.scss";
class App extends Component {
state = {
message: "Hello from React",
clickCount: 0
};
incCounter = () => {
this.setState(({ clickCount }) => ({
clickCount: clickCount + 1
}));
};
render() {
const { message, clickCount } = this.state;
return (
<div className={styles.message}>
<h1>{message}</h1>
<p>clicked {clickCount}</p>
<button onClick={this.incCounter}>Click me</button>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("app"));
// Enable Hot Module Reloading
if (module.hot) {
module.hot.accept();
}
I think I don't have to go into every detail here. state = { }
and incCounter
are class properties and we need the Babel plugin @babel/plugin-proposal-class-properties
to have them correctly handled.
The last line will enable hot reloading. So after saving your changes Parcel will rebuild your app and automatically reload the browser for you.
The Sass file is loaded by Parcel for us and you can access the imported style with styles.message
because we have created a class named .message
inside the file.
If you prefer to use css modules you have to add a .postcssrc
and add the following configuration in it:
{
"modules": true,
}
Then you can use the css file as a module like in the code snippet above. With-out postcss you could only load it with import "styles.css"
and access the style with .message
and add it with className="message"
.
For more details to the postcss setup you can have a look in the docs.
With yarn start
you launch the devServer and it will automatically open a browser window with your rendered app.
If everything is working as expected your app will look like in the following Codesandbox:
I think this setup is containing everything to get a basic React app up an running. Or am I missing an important feature of Create-React-App? But I think everything is available.
When would I use this setup? I think for small demos or when it's important to customize the setup. E.g. I'm trying to use it for an Electron app where I need to have Stylus for styling as the existing app relies on it.
Adding Stylus to a Create-React-App is a bit hard and would probably require to eject
.
I think some customizations are possible with Parcel like adding Stylus.
Anyway I think there are edge-cases where it's probably not possible or difficult to customize Parcel. But for now I'll give it a try.
For larger apps where you don't have to customize CRA I think it's OK to use. Even small customizations are possible either by ejecting or using react-app-rewired (which seems a bit out-dated & doesn't fully support CRA 2.x - so I wouldn't use it right now).