Setup a React.JS Project with TypeScript, ESLint and Prettier without create-react-app
Tags: react, typescript, babel, eslint
Published: 2020-01-14 20:14:11

When we initializing the study of react and searching by a tutorial in many cases the [create-react-app](https://create-react-app.dev/) is used to create de application. However, some people cite some negatives in this approach like: [hard configuration](https://dev.to/bettercodingacademy/you-should-stop-using-create-react-app-m81), [maintainability](https://medium.com/@imbudhiraja/webpack-vs-create-react-app-cb72c47f8100) and soon.

So in this post we will desmonstrates how to setup a React project without the [create-react-app](https://create-react-app.dev/).

For this task we need install and configure: a JavaScript compiler (transpiler) to convert our source code in a way that the browser understand; a model bundler to loading and compile modules to a single file.

# JavaScript compiler (babel)

We use Babel is a to convert new JavaScript code into compatible version that the browsers can understand. As an alternative we can use [sucrase](https://github.com/alangpierce/sucrase).

## Plugins and presets

All transformations that Babel apply are informed to it through plugins and an array of plugins can be informed as a preset.

## Install Babel, plugins and presets

```shell

mkdir your_project_folder && cd your_project_folder

yarn init -y

yarn add @babel/core @babel/cli @babel/preset-env
@babel/preset-react @babel/plugin-transform-typescript -D

yarn add @babel/polyfill core-js
```

Now at root of project, create the file babel.config.js with the content:

```javascript
module.exports = {
  presets: ["@babel/preset-env", "@babel/preset-react"],
  plugins: ["@babel/plugin-transform-typescript"]
};
```

# Model bundler (webpack)

Webpack is a module bundler for JavaScript applications. Webpack will mapping all modules dependencies creating a bundle file.

## Install webpack

```shell
yarn add webpack webpack-cli -D
```

Now we need create a file called webpack.config.js at root project. Inside that file we will see some configurations:

- resolve: help to find models that are required by the application.
- devServer: use to configure the [webpack-dev-server](https://github.com/webpack/webpack-dev-server)
- entry: says to webpack what is the entry point.
- module.rules: an array of rules that determine the loader to each file.

## Install loaders and dev sever

```shell
yarn add babel-loader style-loader css-loader file-loader source-map-loader ts-loader webpack-dev-server eslint-loader -D
```

Put in the webpack.config.js file the content:

```javascript
const path = require("path");

module.exports = {
  resolve: {
    extensions: [".tsx", ".ts", ".js"]
  },
  devServer: {
    contentBase: path.join(__dirname, "public"),
    compress: true,
    port: 3000
  },
  entry: path.resolve(__dirname, "src", "index.tsx"),
  output: {
    path: path.resolve(__dirname, "public"),
    filename: "bundle.js"
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: ["babel-loader", "eslint-loader"]
      },
      {
        test: /\.ts(x?)$/,
        exclude: /node_modules/,
        use: [{ loader: "ts-loader" }, { loader: "eslint-loader" }]
      },
      {
        test: /\.css$/,
        use: [{ loader: "style-loader" }, { loader: "css-loader" }]
      },
      {
        test: /\.(png|svg|jpg|gif)$/i,
        use: ["file-loader"]
      },
      {
        enforce: "pre",
        test: /\.js$/,
        loader: "source-map-loader"
      }
    ]
  }
};
```

# ESLint, Prettier and TypeScript

For that install and configuration we can use [How to setup a React.JS Project with typcript, ESLint and Prettier](https://dev.to/renatobentorocha/how-to-setup-a-react-js-project-with-typcript-eslint-and-prettier-8mn)

The .eslintrc.json, .prettierrc, tsconfig.json, custom.d.ts are:

```json
.eslintrc.json

{
  "env": {
    "browser": true,
    "es6": true
  },
  "globals": {
    "Atomics": "readonly",
    "SharedArrayBuffer": "readonly"
  },
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaFeatures": {
      "jsx": true
    },
    "ecmaVersion": 2018,
    "sourceType": "module"
  },
  "plugins": ["react", "@typescript-eslint", "prettier"],
  "extends": [
    "plugin:react/recommended",
    "airbnb",
    "plugin:prettier/recommended",
    "plugin:@typescript-eslint/eslint-recommended",
    "plugin:@typescript-eslint/recommended"
  ],
  "rules": {
    "react/prop-types": "off",
    "import/extensions": [
      "error",
      "ignorePackages",
      {
        "js": "never",
        "jsx": "never",
        "ts": "never",
        "tsx": "never"
      }
    ],
    "import/prefer-default-export": "off",
    "prettier/prettier": "error",
    "@typescript-eslint/explicit-function-return-type": "off",
    "@typescript-eslint/no-unused-vars": "off",
    "@typescript-eslint/no-var-requires": "off",
    "react/jsx-filename-extension": [
      1,
      { "extensions": [".js", ".jsx", ".ts", ".tsx"] }
    ]
  },
  "settings": {
    "import/resolver": {
      "node": {
        "extensions": [".js", ".jsx", ".ts", ".tsx"]
      }
    }
  }
}
```

```json
.prettierrc

{
  "singleQuote": true,
  "trailingComma": "es5"
}
```

```json
tsconfig.json

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "rootDir": "src",
    "outDir": "public",
    "jsx": "react",
    "strict": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src", "custom.d.ts"]
}
```

```typescript
custom.d.ts;

declare module "*.svg" {
  import React = require("react");
  export const ReactComponent: React.SFC<React.SVGProps<SVGSVGElement>>;
  const src: string;
  export default src;
}

declare module "*.png" {
  const src: string;
  export default src;
}
```

The finally packages to install are:

```shell
yarn add react react-dom
```

The project structure is:

![](https://raw.githubusercontent.com/renatobentorocha/react-babel-typescript/master/project_structure.png)

To complete we need create:

- public/index.html

```html
<!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>ReactJS</title>
  </head>
  <body>
    <div id="root"></div>

    <script src="./bundle.js"></script>
  </body>
</html>
```

- src/index.tsx

```typescript
import React from "react";
import { render } from "react-dom";

import Index from "./pages";

render(<Index />, document.getElementById("root"));
```

- src/pages/index.tsx

```typescript
import React from "react";

export default function src() {
  return (
    <div className="container">
      <h1>Hello World!</h1>
    </div>
  );
}
```

Now add in package.json:

```json
"scripts": {
    "build": "webpack --mode production",
    "dev": "webpack-dev-server --mode development"
  }
```

And at root folder run:

```shell
yarn dev
```

![](https://raw.githubusercontent.com/renatobentorocha/react-babel-typescript/master/home.png)

[source code](https://github.com/renatobentorocha/react-babel-typescript)