React Typescript Template From Scratch

usage

build

yarn build

start

cd build
npx serve

Basic Setup Step

  1. mkdir src build
  2. npm init --y
  3. create src/index.html
  4. install react dependencies
yarn add react react-dom
  1. install typescript dev dependencies
yarn add -D typescript @types/react @types/react-dom
  1. create tsconfig.json
  2. create src/App.tsx
  3. create src/index.tsx
  4. install babel dev dependencies
yarn add -D @babel/core @babel/preset-env @babel/preset-react @babel/preset-typescript @babel/plugin-transform-runtime
  1. create .babelrc in project root directory
{
  "presets": [
    "@babel/preset-env",
    [
      "@babel/preset-react",
      {
        "runtime": "automatic"
      }
    ],
    "@babel/preset-typescript"
  ],
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "regenerator": true
      }
    ]
  ]
}
  1. install webpack dev dependencies
yarn add -D webpack webpack-cli webpack-dev-server html-webpack-plugin
  1. install babel-loader package to transpiling source code.
yarn add -D babel-loader
  1. create webpack directory
  2. create webpack/webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: path.resolve(__dirname, "..", "./src/index.tsx"),
  resolve: {
    extensions: [".tsx", ".ts", ".js"],
  },
  module: {
    rules: [
      {
        test: /\.(ts|js)x?$/,
        exclude: /node_modules/,
        use: [
          {
            loader: "babel-loader",
          },
        ],
      },
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.(?:ico|gif|png|jpg|jpeg)$/i,
        type: "asset/resource",
      },
      {
        test: /\.(woff(2)?|eot|ttf|otf|svg|)$/,
        type: "asset/inline",
      },
    ],
  },
  output: {
    path: path.resolve(__dirname, "..", "./build"),
    filename: "bundle.js",
  },
  mode: "development",
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, "..", "./src/index.html"),
    }),
  ],
  stats: "errors-only",
};
  1. add start scripts in package.json
"scripts": {
  "start": "webpack serve --config webpack/webpack.config.js --open"
}

Styles Setup Step

  1. install dev dependencies.
yarn add -D css-loader style-loader
  1. add configuration in webpack.config.js
{
  test: /\.css$/,
  use: ["style-loader", "css-loader"],
},
  1. create declarations.d.ts then add declare
declare module "*.png"
  1. add configuration for images in webpack.config.js
{
  test: /\.(?:ico|gif|png|jpg|jpeg)$/i,
  type: "asset/resource",
},
  1. add asset/inline configuration to serve inline images like svg.
{
  test: /\.(woff(2)?|eot|ttf|otf|svg|)$/,
  type: "asset/inline",
},

Setup multiple environment for production and development.

  1. create webpack.dev.js, webpack.prod.js, webpack.common.js

webpack.dev.js

const webpack = require("webpack");

module.exports = {
  mode: "development",
  devtool: "cheap-module-source-map",
  plugins: [
    new webpack.DefinePlugin({
      "process.env.name": JSON.stringify("Vishwas"),
    }),
  ],
};

webpack.prod.js

const webpack = require("webpack");

module.exports = {
  mode: "production",
  devtool: "source-map",
  plugins: [
    new webpack.DefinePlugin({
      "process.env.name": JSON.stringify("Codevolution"),
    }),
  ],
};

webpack.common.js

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: path.resolve(__dirname, "..", "./src/index.tsx"),
  resolve: {
    extensions: [".tsx", ".ts", ".js"],
  },
  module: {
    rules: [
      {
        test: /\.(ts|js)x?$/,
        exclude: /node_modules/,
        use: [
          {
            loader: "babel-loader",
          },
        ],
      },
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.(?:ico|gif|png|jpg|jpeg)$/i,
        type: "asset/resource",
      },
      {
        test: /\.(woff(2)?|eot|ttf|otf|svg|)$/,
        type: "asset/inline",
      },
    ],
  },
  output: {
    path: path.resolve(__dirname, "..", "./build"),
    filename: "bundle.js",
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, "..", "./src/index.html"),
    }),
  ],
  stats: "errors-only",
};

webpack.config.js

const { merge } = require("webpack-merge");
const commonConfig = require("./webpack.common.js");

module.exports = (envVars) => {
  const { env } = envVars;
  const envConfig = require(`./webpack.${env}.js`);
  const config = merge(commonConfig, envConfig);
  return config;
};
  1. add scripts
"scripts": {
  "start": "webpack serve --config webpack/webpack.config.js --env env=dev --open",
  "build": "webpack --config webpack/webpack.config.js --env env=prod",
},
  1. Change App.tsx to check environment.
import "./styles.css";
import IMAGE from "./react.png";
import LOGO from "./logo.svg";

export const App = () => {
  return (
    <>
      <h1>
        React Typescript Webpack Starter Template - {process.env.NODE_ENV} {process.env.name}
      </h1>
      <img src={IMAGE} alt="React Logo" width="300" height="300" style={{ objectFit: "cover" }} />
      <img src={LOGO} alt="React Logo" width="300" height="300" style={{ objectFit: "cover" }} />
    </>
  );
};

ESLint Setup

Install Dev Dependencies

yarn add -D eslint

yarn add -D eslint-plugin-react-hooks

yarn add -D @typescript-eslint/parser @typescript-eslint/eslint

yarn add -D eslint-plugin-import eslint-plugin-jsx-a11y

.eslintrc.js

module.exports = {
  parser: "@typescript-eslint/parser",
  parserOptions: {
    ecmaVersion: 2020,
    sourceType: "module",
  },
  settings: {
    react: {
      version: "detect",
    },
  },
  extends: [
    "plugin:react/recommended",
    "plugin:react-hooks/recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:import/errors",
    "plugin:import/warnings",
    "plugin:import/typescript",
    "plugin:jsx-a11y/recommended",
  ],
  rules: {
    "no-unused-vars": "off",
    "@typescript-eslint/no-unused-vars": ["error"],
    "@typescript-eslint/no-var-requires": "off",
    "react/prop-types": "off",
    "react/jsx-uses-react": "off",
    "react/react-in-jsx-scope": "off",
    "@typescript-eslint/explicit-module-boundary-types": "off",
  },
};

Add script to package.json

"scripts": {
  "lint": "eslint --fix \"./src/**/*.{js,jsx,ts,tsx,json}\""
},

Prettier Setup

Install Dev dependencies

yarn add -D prettier eslint-config-prettier eslint-plugin-prettier

.prettierrc.js

module.exports = {
  semi: false,
  trailingComma: "es5",
  singleQuote: true,
  printWidth: 80,
  tabWidth: 2,
  endOfLine: "auto",
};

add scripts to package.json

"scripts": {
  "format": "prettier --write \"./src/**/*.{js,jsx,ts,tsx,json,css,scss,md}\""
},

How to prevent linting and forammting errors from being committed repository

yarn add -D husky@4 lint-staged

Add configuration to package.json

"husky": {
  "hooks": {
    "pre-commit": "lint-staged"
  }
},
"lint-staged": {
  "src/**/*.{js,jsx,ts,tsx,json}": [
    "eslint --fix"
  ],
  "src/**/*.{js,jsx,ts,tsx,json,css,scss,md}": [
    "prettier --write"
  ]
}

babel runtime

Install

yarn add -D @babel/runtime @babel/plugin-transform-runtime

.babelrc

{
  "presets": [
    "@babel/preset-env",
    [
      "@babel/preset-react",
      {
        "runtime": "automatic"
      }
    ],
    "@babel/preset-typescript"
  ],
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "regenerator": true
      }
    ]
  ]
}

webpack-plugin

yarn add -D copy-webpack-plugin

webpack-bundle-analyzer

yarn add -D webpack-bundle-analyzer