DEV Community

Alex Adam
Alex Adam

Posted on • Edited on • Originally published at alexadam.dev

3

Create a React project from scratch, with TypeScript and Webpack

A step by step guide on how to create a React project from scratch, with TypeScript and Webpack 5.

You can find the full source code here: https://github.com/alexadam/project-templates/tree/master/projects/react-app

Setup

Prerequisites:

  • node
  • yarn

Create the project's folder:

mkdir react-app
cd react-app
Enter fullscreen mode Exit fullscreen mode

Generate a default package.json file with yarn:

yarn init -y
Enter fullscreen mode Exit fullscreen mode

Install React, TypeScript and Webpack:

yarn add react react-dom

yarn add --dev @types/react \
        @types/react-dom \
        awesome-typescript-loader \
        css-loader \
        html-webpack-plugin \
        node-sass \
        sass-loader \
        style-loader \
        typescript \
        webpack \
        webpack-cli \
        webpack-dev-server
Enter fullscreen mode Exit fullscreen mode

Add build, dev & clean scripts in the package.json file:

 ....
  },
  "scripts": {
    "clean": "rm -rf dist/*",
    "build": "webpack",
    "dev": "webpack serve"
  }
Enter fullscreen mode Exit fullscreen mode

Configure TypeScript by creating the file tsconfig.json with:

{
  "compilerOptions": {
    "incremental": true,
    "target": "es5",
    "module": "commonjs",
    "lib": ["dom", "dom.iterable", "es6"],
    "allowJs": true,
    "jsx": "react",
    "sourceMap": true,
    "outDir": "./dist/",
    "rootDir": ".",
    "removeComments": true,
    "strict": true,
    "moduleResolution": "node",            
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "experimentalDecorators": true
  },
  "include": [
    "client"
  ],
  "exclude": [
    "node_modules",
    "build",
    "dist"
  ]
}
Enter fullscreen mode Exit fullscreen mode

To configure Webpack, make a file webpack.config.js containing:

const path = require("path");

const app_dir = __dirname + '/client';

const HtmlWebpackPlugin = require('html-webpack-plugin');
const HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
  template: app_dir + '/index.html',
  filename: 'index.html',
  inject: 'body'
});

const config = {
  mode: 'development',
  entry: app_dir + '/app.tsx',
  output: {
    path: __dirname + '/dist',
    filename: 'app.js',
    publicPath: '/'
  },
  module: {
    rules: [{
        test: /\.s?css$/,
        use: [
          'style-loader',
          'css-loader',
          'sass-loader'
        ]
      }, {
        test: /\.tsx?$/,
        loader: "awesome-typescript-loader",
        exclude: /(node_modules|bower_components)/
      },
      {
        test: /\.(woff|woff2|ttf|eot)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        exclude: [/node_modules/],
        loader: "file-loader"
      },
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        exclude: [/node_modules/],
        loader: "file-loader"
      },
      {
        test: /\.(pdf)$/i,
        exclude: [/node_modules/],
        loader: "file-loader",
        options: {
          name: '[name].[ext]',
        },
      },
    ]
  },
  plugins: [HTMLWebpackPluginConfig],
  resolve: {
    extensions: [".ts", ".tsx", ".js", ".jsx"]
  },
  optimization: {
    removeAvailableModules: false,
    removeEmptyChunks: false,
    splitChunks: false,
  },
  devServer: {
    port: 8080,
    // open: true,
    hot: true,
    inline: true,
    historyApiFallback: true,
  },
};
module.exports = config;
Enter fullscreen mode Exit fullscreen mode

Example App

Create a folder named client (in the project's folder):

mkdir client
cd client
Enter fullscreen mode Exit fullscreen mode

Make a simple React component, in the file numbers.tsx:

import React, {useState} from 'react';

interface INumberProps {
  initValue: number
}

const Numbers = (props: INumberProps) => {
  const [value, setValue] = useState(props.initValue)

  const onIncrement = () => {
    setValue(value + 1)
  }

  const onDecrement = () => {
    setValue(value - 1)
  }

  return (
    <div>
      Number is {value}
        <div>
          <button onClick={onIncrement}>+</button>
          <button onClick={onDecrement}>-</button>
        </div>
    </div>
  )
}
export default Numbers
Enter fullscreen mode Exit fullscreen mode

Create the main React component (the entry point), in the file app.tsx:

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import Numbers from './numbers';

ReactDOM.render(
    <Numbers initValue={42} />,
    document.getElementById('app') as HTMLElement
  );
Enter fullscreen mode Exit fullscreen mode

Next, add the index.html:

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>React TypeScript</title>
</head>

<body>
  <div id="app"></div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Then, run yarn dev and open http://localhost:8080/ in a browser.

Use this project as a template

You can save the Setup steps as a shell script:

#!/bin/sh

rm -rf node_modules
rm package.json

yarn init --yes

yarn add react react-dom

yarn add --dev @types/react \
        @types/react-dom \
        awesome-typescript-loader \
        css-loader \
        html-webpack-plugin \
        node-sass \
        sass-loader \
        style-loader \
        typescript \
        webpack \
        webpack-cli \
        webpack-dev-server

# Remove the last line
sed -i.bak '$ d' package.json && rm package.json.bak

# append the scripts commads
cat <<EOT >> package.json
   ,"scripts": {
      "clean": "rm -rf dist/*",
      "build": "webpack",
      "dev": "webpack serve"
   }
}
Enter fullscreen mode Exit fullscreen mode

Delete the node-modules folder and, when you want to start a new project, you can copy the contents of react-app to the new location:

mkdir new-project
cd new-project

# copy the react-app folder content to the new project
rsync -rtv /path/to/../react-app/ .

./init.sh
Enter fullscreen mode Exit fullscreen mode

Top comments (0)

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more