Create React App without create-react-app (Typescript)

In my previous post on Create react App from scratch using JS , I got positive responses and many comments on making a post on typescript, hence i decided to do the same task using Typescript with Fast Refresh. Hope you would like this as well! :)

The simplest way to create a basic react app is to run npx create-react-app my-app --template typescript and boom your basic react app will be created but have you ever wondered, can I do that whole process on my own? Well yes, you can.

Pre-requisites: Node js and Vs code. That’s all you need.

Let’s go..!!


1. Open your vs code terminal and run the below commands:

npm init -y

By running this command package.json will be formed, which holds important information required before publishing to NPM and defines attributes of a project that is used by npm to install dependencies, run scripts, and identify the entry point of the project.

npm install react react-dom 

React will be needed to create user interfaces whereas React-Dom is a glue between React and browser DOM.

After running this command, node_modules and package.lock.json will be created. Node modules hold all the dependencies downloaded from npm. Package.lock.json keeps track of the exact version of every package installed and the dependency tree of every package.

npm install --save-dev typescript @types/react @types/react-dom 

To get the support of typescript the above command is used along with types.

npm install --save-dev @babel/core @babel/preset-env  @babel/preset-react @babel/preset-typescript babel-loader

Babel is a JS Compiler that converts modern JS code into vanilla Js code that can be supported in older browsers and environments. Babel-loader transpile JS files using Babel and webpack. Babel’s preset-typescript is used to generate your JS files and you get the ability to work with existing build pipelines.

For further reading visit

2.Create a file .babelrc and copy the code below

    "presets": [
                "runtime": "automatic"

This file is a configuration file for babel whereas presets act as a shareable set of Babel plugins and/or config options.

3.Create a file tsconfig.json and copy the code below

    "compilerOptions": {
        "target": "ES5" ,
        "module": "ESNext" ,
        "moduleResolution": "node" ,
        "lib": [
        ] ,
        "jsx": "react-jsx" ,
        "noEmit": true ,
        "isolatedModules": true ,
        "esModuleInterop": true ,
        "strict": true ,
        "skipLibCheck": true ,
        "forceConsistentCasingInFileNames": true ,
        "resolveJsonModule": true
    "include": [

This file is a configuration file for typescript. The presence of a tsconfig.json file in a directory indicates that the directory is the root of a TypeScript project. The tsconfig.json file specifies the root files and the compiler options required to compile the project.

npm install --save-dev webpack webpack-cli @pmmmwh/react-refresh-webpack-plugin react-refresh

Webpack is a tool that lets you compile JavaScript modules, also known as module bundlers.Given a large number of files, it generates a single file (or a few files) that run your app. Webpack-CLI provides the interface of options webpack uses in its configuration file.React-refresh-webpack-plugin and React-refresh helps in fast Refresh with state retention property.

npm install --save-dev html-webpack-plugin style-loader css-loader file-loader

All these are loaders that help in bundling various files along with webpack.

4.Create a file webpack.config.js and copy the code below

const HtmlWebpackPlugin = require("html-webpack-plugin");
const ReactRefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin");
const path = require("path");
const webpack = require("webpack");

const isDevelopment = process.env.NODE_ENV !== "production";

module.exports = {
  mode: isDevelopment ? "development" : "production",
  entry: "./src/index.tsx",
  devServer: {
    hot: true,
  target: "web",
  output: {
    filename: "bundle.[hash].js",
    path: path.resolve(__dirname, "dist"),
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/index.html",
    isDevelopment && new webpack.HotModuleReplacementPlugin(),
    isDevelopment && new ReactRefreshWebpackPlugin(),
  resolve: {
    modules: [__dirname, "src", "node_modules"],
    extensions: ["*", ".js", ".jsx", ".tsx", ".ts"],
  module: {
    rules: [
        test: /\.ts$|tsx/,
        exclude: /node_modules/,
        loader: require.resolve("babel-loader"),
        options: {
          plugins: [
            isDevelopment && require.resolve("react-refresh/babel"),
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
        test: /\.png|svg|jpg|gif$/,
        use: ["file-loader"],

This config file provides all the required information like an entry point,bundle output filename and path , plugins and various loaders that are being used for webpack to bundle and resolve various kinds of files.
For further reading visit:

5.Create a folder “src” and inside that create a file “App.tsx”

import React from "react";
import  Counter  from "./Counter";
 const App=()=>{
    return (
    <h1>Create React App from Scratch Using Typescript..!!</h1>
export default App;

This is a basic arrow function that returns Create React App from Scratch Using Typescript wrapped inside an h1 tag along with Counter Component.

6.Create another file "Counter.tsx " inside “src” folder.

import { useState } from 'react'

const Counter = () => {
  const [count, setCount] = useState(0)
  return (
      <h3>Update the count and edit src/App.tsx, state is preserved</h3>
      <button onClick={() => setCount((c) => c + 1)}>Count - {count}</button>

export default Counter;

This component returns a basic button with Counter increasing on every click. This components uses react hook "useState" to store the current value of counter.

7.Create a file “index.tsx” which will be the entry point of our code.

import React from "react";
import ReactDOM from "react-dom";
import  App  from "./App";


8.Create another file “index.html”

<html lang="en">

    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>React with Typescript </title>

    <div id="root"></div>


In our configuration, we specified that it should read ./src/index.HTML as a template. We have also set the inject option to true. With that option, Html-webpack-plugin adds a script tag with the path provided by Webpack right into the final HTML page. This final page is the one you get in dist/index.html after running npm run build, and the one that gets served from / when you run npm start.

9.In your package.json write the following lines of code in place of the script tag

"scripts": {
   "start": "webpack serve  --hot --open",
    "build": "webpack --config webpack.config.js --mode development"

You can start your react app by writing npm start and you will see a blank page with Hello React written on it.

Final Output

Finally you are done ..!!

As Fast Refresh was included, even after doing some changes the state would be preserved and the previous state would not be lost. This comes in very handy during development.

It was a longer process than creating React app from scratch with Js as Fast Refresh was included and that’s what create-react-app makes it easier for you. It automates this whole hefty process of making every single file by replacing it with just a single command .