Setting up an Express backend with ESLint, Prettier, Husky, and lint-staged is crucial for code quality and efficiency. ESLint catches errors and enforces coding standards, Prettier ensures consistent formatting, and Husky with lint-staged prevents issues from entering the codebase. This setup saves time, enhances collaboration, and promotes clean, error-free code.
npm init
yarn add -D typescript
npm install typescript --save-dev
yarn add express mongoose cors
npm install express mongoose cors
yarn add -D @types/express
npm install @types/express --save-dev
yarn add -D @types/cors
npm install @types/cors --save-dev
yarn add -D @typescript-eslint/parser
npm install @typescript-eslint/parser --save-dev
- Run
tsc --init
- Update
tsconfig.json
:
"rootDir": "./src",
"outDir": "./dist",
yarn add dotenv
npm install dotenv
9. Create a .env file at the root of your project directory to set your environment variables. Inside the .env file, add the necessary secrets and configurations. For example:
NODE_ENV=development
PORT=5000
DATABASE_URL=your-database-url //Replace your-database-url with the actual URL for your database.
10. Create a .gitignore file at the root of your project directory to ignore unnecessary files when pushing to GitHub. Add the following content to the .gitignore file:
dist
node_modules
.env
- Import necessary modules:
import dotenv from "dotenv";
import path from "path";
- Load environment variables:
dotenv.config({
path: path.join(process.cwd(), ".env"),
});
- Export configuration:
export default {
port: process.env.PORT,
database_url: process.env.DATABASE_URL,
};
app.ts
(Express application setup)
//app.ts
import express, { Application, Request, Response } from "express";
const app: Application = express();
import cors from "cors";
app.use(cors());
// parser
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.get("/", (req: Request, res: Response) => {
res.send("Hello World!");
});
export default app;
server.ts
(Database connection setup)
import mongoose from "mongoose";
import app from "./app";
import config from "./config";
async function main() {
await mongoose.connect(config.database_url as string);
console.log("Connected to MongoDB");
app.listen(config.port, () => {
console.log(`Server running at port ${config.port}`);
});
}
main();
yarn add -D ts-node-dev
npm install ts-node-dev --save-dev
"start": "ts-node-dev --respawn --transpile-only src/server.ts",
yarn start
npm start
"include": ["src"],
"exclude": ["node_modules"]
yarn add -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin
npm install eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin --save-dev
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": ["@typescript-eslint"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"prettier"
],
"rules": {
"no-unused-vars": "error",
"no-console": "warn",
"no-undef": "error",
"no-unused-expressions": "error",
"no-unreachable": "error",
"@typescript-eslint/consistent-type-definitions": ["error", "type"]
},
"env": {
"browser": true,
"node": true,
"es2021": true
}
}
"lint:check": "eslint --ignore-path .eslintignore --ext .js,.ts .",
"lint:fix": "eslint . --fix"
dist
node_modules
.env
yarn add -D prettier
npm install prettier --save-dev
{
"semi": true,
"singleQuote": true,
"arrowParens": "avoid"
}
"prettier:check": "prettier --ignore-path .gitignore --write \"**/*.+(js|ts|json)\"",
"prettier:fix": "prettier --write .",
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
yarn add -D eslint-config-prettier
npm install eslint-config-prettier --save-dev
yarn add husky --dev
npm install husky --save-dev
yarn add -D lint-staged
npm install lint-staged --save-dev
"scripts": {
//....other scripts
"lint-prettier": "yarn lint:check && yarn prettier:check"
},
"lint-staged": {
"src/**/*.ts": "yarn lint-prettier"
}
yarn husky add .husky/pre-commit "yarn lint-staged"
npx husky add .husky/pre-commit "yarn lint-staged"