Create Your Own CRA: The Detailed Guide

Ankit Brahmbhatt
5 min readJul 1, 2024

So, you’ve decided to roll up your sleeves and dive deep into the magical world of React. Maybe you’re tired of using Create React App (CRA) because you’re a rebel at heart, or perhaps you just want to impress your friends at the next coder’s meet-up. Either way, you’re in the right place. Let’s embark on this journey to create your very own version of CRA, complete with all the bells and whistles. And hey, we’ll try to make it fun!

Prerequisites: The Boring but Necessary Stuff

Before we get to the good stuff, make sure you have these installed:

  • Node.js: This is the engine that will run our JavaScript outside the browser. You can grab it here.
  • npm or yarn: These are the package managers that will manage (duh) our project’s dependencies. npm comes with Node.js, but you can use yarn if you’re feeling fancy.

Step 1: Kickstarting Your Project

First things first, let’s create a cozy new directory for our project and move into it. Think of it as building your own little coding cabin in the woods.

mkdir create-my-react-app
cd create-my-react-app

Now, let’s initialize our project with npm. Don’t worry, this won’t hurt a bit.

npm init -y

This command creates a package.json file, which is like your project's diary where all important information is kept. This file will keep track of your project's dependencies, scripts, version, and other metadata. You can think of it as the project’s résumé.

Step 2: Gathering Your Gear (Installing Dependencies)

Imagine you’re packing for an adventure. You need to bring the essentials. For a React project, that means React and ReactDOM. Let’s install them:

npm install react react-dom

But wait, there’s more! To build and bundle our application, we need some heavy-duty tools. Enter Webpack and Babel. These guys are like the Swiss Army knives of the JavaScript world. Let’s install them too:

npm install --save-dev webpack webpack-cli webpack-dev-server babel-loader @babel/core @babel/preset-env @babel/preset-react html-webpack-plugin

Step 3: Setting Up Babel

Babel is like a universal translator for your code. It takes the fancy new JavaScript you write and translates it into something older browsers can understand. Create a .babelrc file in your project’s root and add the following:

{
"presets": ["@babel/preset-env", "@babel/preset-react"]
}

This file tells Babel to use two presets:

  • @babel/preset-env: This handles the conversion of modern JavaScript to a version that works in older browsers.
  • @babel/preset-react: This converts JSX, the syntax used by React, into regular JavaScript.

Step 4: Configuring Webpack

Webpack is our trusty bundler, gathering all our modules and assets and packaging them up neatly. Create a webpack.config.js file in your project’s root directory and add this configuration:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\\\\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
{
test: /\\\\.css$/,
use: ['style-loader', 'css-loader']
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
],
devServer: {
contentBase: path.join(__dirname, 'dist'),
compress: true,
port: 9000
}
};

Here’s a quick breakdown of what’s happening:

  • entry: The starting point of our app. Webpack will start here to build the dependency graph.
  • output: Where Webpack will bundle our files. We specify the directory and the filename for our bundled JavaScript.
  • module: Rules for transforming our code. We use babel-loader to handle JavaScript files and style-loader and css-loader for CSS files.
  • plugins: Extra tools to help Webpack. HtmlWebpackPlugin generates an HTML file that includes our bundled JavaScript.
  • devServer: Configuration for our development server. It serves our files from the dist directory and enables hot reloading on port 9000.

Step 5: Creating Your Project Structure

Time to set up our project folders. Think of it as setting up the rooms in your new coding house.

Create the following structure:

create-my-react-app/

├── bin/
│ └── create-my-react-app.js

├── templates/
│ ├── src/
│ │ ├── index.js
│ │ ├── style.css
│ │ └── index.html
│ └── package.json

├── .babelrc
├── package.json
└── webpack.config.js

Step 6: Writing Your First React Components

Now comes the fun part — writing some actual code! In the templates/src directory, create an index.js file:

import React from 'react';
import ReactDOM from 'react-dom';
import './style.css';
const App = () => (
<div>
<h1>Hello, React!</h1>
<p>Welcome to your custom React setup. You did it!</p>
</div>
);
ReactDOM.render(<App />, document.getElementById('root'));

This file sets up a simple React component and renders it to the DOM. We’re importing our styles from style.css and telling ReactDOM to render our App component into the root element of our HTML.

Next, create a style.css file:

body {
font-family: Arial, sans-serif;
background-color: #f0f0f0;
}
h1 {
color: #333;
}
p {
color: #666;
}

This file contains some basic styles to make our app look a little nicer. Feel free to get creative here!

Finally, create an index.html file:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My React App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>

This file is the skeleton of our web page. It includes a div with an id of root, which is where our React app will be rendered.

Step 7: Creating Your CLI Script

In the bin directory, create a create-my-react-app.js file:

#!/usr/bin/env node
const { program } = require('commander');
const chalk = require('chalk');
const inquirer = require('inquirer');
const shell = require('shelljs');
const fs = require('fs');
const path = require('path');
program
.version('1.0.0')
.description('CLI tool to create a custom React app');
program
.command('init <projectName>')
.description('Initialize a new React project')
.action(async (projectName) => {
const projectPath = path.join(process.cwd(), projectName);
if (fs.existsSync(projectPath)) {
console.log(chalk.red('Project already exists'));
process.exit(1);
}
fs.mkdirSync(projectPath); console.log(chalk.green('Creating project...')); const templatePath = path.join(__dirname, '../templates'); shell.cp('-R', `${templatePath}/*`, projectPath); shell.cd(projectPath); console.log(chalk.green('Installing dependencies...')); shell.exec('npm install'); console.log(chalk.green('Project setup complete!'));
console.log(`\\\\nTo get started:\\\\n\\\\ncd ${projectName}\\\\nnpm start\\\\n`);
});
program.parse(process.argv);

Here’s what’s happening in this script:

  • commander: Helps us create command-line interfaces.
  • chalk: Adds colors to our command-line output to make it more readable (and fun).
  • inquirer: For interactive command-line prompts (we’re not using it yet, but you can add prompts to customize your project setup further).
  • shelljs: Allows us to execute shell commands from within our Node.js script.
  • fs and path: Built-in Node.js modules for working with the file system and file paths.

The script defines a command init which takes a projectName argument. It checks if the project directory already exists, creates it if it doesn't, copies the template files, installs dependencies, and gives the user instructions on how to start their new project.

Step 8: Make Your Script Executable

Open your package.json and add the following section to specify the entry point of your CLI tool:

"bin": {
"create-my-react-app": "./bin/create

To publish your CLI tool so others can use it:

  1. Create a GitHub repository for your project.
  2. Ensure your package.json is properly configured.
  3. Run npm publish to publish to npm (you'll need an npm account).

Conclusion

There you have it! An elementary command-line script for initializing your projects. You can extend it and add all the extra features that CRA supports and much more.

--

--

Ankit Brahmbhatt
Ankit Brahmbhatt

Written by Ankit Brahmbhatt

Ankit is a programmer currently working as a freelance software engineer. Ankit has worked with multiple startups and has seen them going from an idea to a prod

No responses yet