When we initializing the study of react and searching by a tutorial in many cases the create-react-app is used to create de application. However, some people cite some negatives in this approach like: hard configuration, maintainability and soon.
So in this post we will desmonstrates how to setup a React project without the create-react-app.
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.
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
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:
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
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
- 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
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:
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
The .eslintrc.json, .prettierrc, tsconfig.json, custom.d.ts are:
.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"]
}
}
}
}
.prettierrc
{
"singleQuote": true,
"trailingComma": "es5"
}
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"rootDir": "src",
"outDir": "public",
"jsx": "react",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src", "custom.d.ts"]
}
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:
yarn add react react-dom
The project structure is:
To complete we need create:
- public/index.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
import React from "react";
import { render } from "react-dom";
import Index from "./pages";
render(<Index />, document.getElementById("root"));
- src/pages/index.tsx
import React from "react";
export default function src() {
return (
<div className="container">
<h1>Hello World!</h1>
</div>
);
}
Now add in package.json:
"scripts": {
"build": "webpack --mode production",
"dev": "webpack-dev-server --mode development"
}
And at root folder run:
yarn dev
Top comments (4)
Bom dia Renato, ótimo post parabéns, só não consegui fazer funcionar o plugin babel-plugin-root-import, sabe se ele funciona com typescript? eu fiz as configs no arquivo babelrc e eslintrc e ele acha as pastas porem quandodo coloco o nome da imagem(image.svg ou image.png) ele fica dando erro...
module "*.png"
Unable to resolve path to module '~/assets/png/1.icone.png'
se eu coloco o caminho relativo comum('../assets/png/1.icone.png') funciona....sabe o q pode ser?
Hi Erik, tanks by comments!
To that with React.JS we need use: customize-cra and react-app-rewired. I already did it, but I not wrote a post about it. So I found this article that could help you whit it.
This is my repo with this config.
In TypeScript I believe we config the tsconfig.json with:
Obs: My repo and the article not use TypeScript.
Best regard
I believe
should be
Hi Jerry, thanks for watching. I fixed that.