Initial NodeJS Express application configuration
-
Install NodeJS - https://nodejs.org/en/download/. Recommended NVM.
-
Create project:
npm init -y
-
ExpressJS - Web Server for REST API.
- install:
npm i express
-
TypeScript - We'll be doing Type Driven Development
- install together with types for
NodeJS
andExpress
and TS Node
npm i -D typescript @types/express @types/node ts-node
- you can also install TypeScript compiler globally by running:
npm i -g typescript
- add TypeScript compiler buid command to NPM:
{ "scripts": { "build:ts": "tsc", } }
- if you installed
tsc
globally you can init TypeScript config by running:
tsc --init
- or you can just create the tsconfig.json file, e.g.:
{ "compilerOptions": { "target": "es2020", "module": "commonjs", "outDir": "./dist", "strict": true, "strictNullChecks": true, "noUnusedLocals": true, "noImplicitReturns": true, "esModuleInterop": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, }, "include": ["./src"], }
- install together with types for
-
ESLint - We'd like to have static code analysis:
- install using npx and going through wizard. This will generate install all packages and generate needed files (suggested is to use ECMA Modules, TypeScript, )
npx eslint --init √ How would you like to use ESLint? · style √ What type of modules does your project use? · esm √ Which framework does your project use? · none √ Does your project use TypeScript? · No / Yes √ Where does your code run? · node √ How would you like to define a style for your project? · guide √ Which style guide do you want to follow? · standard √ What format do you want your config file to be in? · JSON
- or using the
npm
:
npm i -D @typescript-eslint/eslint-plugin eslint-config-standard eslint eslint-plugin-import eslint-plugin-node eslint-plugin-promise @typescript-eslint/parser
- this should generate .eslintrc.json file with ESLint configuration:
{ "env": { "es2020": true, "node": true }, "extends": [ "standard" ], "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": 12, "sourceType": "module" }, "plugins": [ "@typescript-eslint" ], "rules": { } }
- add .eslintignore to configure exclusion for files that we don't want to analyse:
/node_modules/* # build artifacts dist/*coverage/* # data definition files **/*.d.ts # custom definition files /src/types/
-
Prettier, as we aim to write pretty code:
- install:
npm i -D prettier eslint-config-prettier eslint-plugin-prettier
- add .prettierrc.json with Prettier config:
{ "tabWidth": 2, "singleQuote": true }
- add Prettier plugin to .eslintrc.json to make sure that then collide with each other:
{ "env": { "es2020": true, "node": true }, "extends": [ "plugin:@typescript-eslint/recommended", "prettier/@typescript-eslint", <-- added "plugin:prettier/recommended" <-- added ], "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": 12, "sourceType": "module" }, "plugins": [ "@typescript-eslint" ], "rules": { } }
- if you're using VSCode, I recommend to install Prettier plugin
-
Define tasks for ESLint and Prettier in package.json:
- checks:
{ "scripts": { "lint": "npm run lint:eslint && npm run lint:prettier", "lint:prettier": "prettier --check \"src/**/**/!(*.d).{ts,json,md}\"", "lint:eslint": "eslint src/**/*.ts", } }
- fixes:
{ "scripts": { "lint:eslint": "eslint src/**/*.ts", "prettier:fix": "prettier --write \"src/**/**/!(*.d).{ts,json,md}\"", } }
-
Husky is a tool that enables to run scripts on precommit git hook. We'll use it to run
ESLint
andPrettier
to make sure that code is formatted and following rules.- install version 4 (Starting for version 5 it's free only for OSS projects):
npm i -D husky@4
- add Husky configuration to package.json:
{ "husky": { "hooks": { "pre-commit": "npm run lint" } } }
-
Nodemon to have hot-reload of the running Express server code.
- install:
npm i -D nodemon
- add script to package.json to run Express server with Nodemon:
{ "scripts": { "dev:start": "nodemon src/index.ts", } }
- you can run dev script as:
npm run dev:start
- open in browser http://localhost:5000/ and check if you see result:
{ "greeting": "Hello World!" }
See more in #1.