Skip to content

Instantly share code, notes, and snippets.

@silver-xu
Last active May 8, 2024 00:59
Show Gist options
  • Save silver-xu/1dcceaa14c4f0253d9637d4811948437 to your computer and use it in GitHub Desktop.
Save silver-xu/1dcceaa14c4f0253d9637d4811948437 to your computer and use it in GitHub Desktop.
Setup a Node.js project with Typescript, ESLint, Prettier, Husky

Setup a Node.js project with Typescript, ESLint, Prettier, Husky

1_D8Wwwce8wS3auLAiM3BQKA

Starting a personal node project could be easy; starting a team node project could be challenging.

I am a developer currently working in SEEK Australia.

In my experience, common mistakes developer make when starting a projects are:

  • No Linting
  • Lack of compile-time type checking (not really mistake but less desirable in my preference)
  • Inconsistent code styling
  • Linter breaking the build

In this article, I am going to not only to share how to address these above problems, but also some of the best practices we implement in our team at SEEK.

The article assumes the reader knows the basics about nodes and typescripts

Typescript

We can start off by a simple node project consisting only the package.json file

yarn add typescript --dev

After adding the dev dependency, create a ts.config.json file under the root of the node project

{
  "compilerOptions":
    {
      "target": "es2018",
      "module": "commonjs",
      "outDir": "dist",
      "sourceMap": true,
    },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules"],
}

The above are the minimal settings of typescript compiler tsc.

It tells the compiler to

  • use es2018 syntax when generating the distributable
  • use the commonjs module format.
  • generate *.js to /dist folder
  • generate source map
  • include all *.ts file inside /src folder
  • exclude all files inside /node_modules folder

Fancy configuration of ts.config.json is beyond the scope of this article

Adding the following line to package.json

{
  "scripts":{
    "build": "tsc"
  }
}

To build, run the following in shell

yarn build

ESLint

We have a handful choices of linting tools for node development, but the de-factor standard these days for typescript is ESLint. Partnering with prettier it really improves consistency and productivity of a development team.

Again we are starting off by adding the dev dependencies

yarn add eslint @typescript-eslint/eslint-plugin @typescript-eslint/parser --dev

ESLint does not support typescript out of the box. Fortunately we are able to add the typescript support by these two packages @typescript-eslint/eslint-plugin @typescript-eslint/parser thanks to the ESLint team's modular design.

The next thing is to create a .eslintrc file. It does not have a file extension but the default is JSON format:

{
  "parser": "@typescript-eslint/parser",
  "extends": ["plugin:@typescript-eslint/recommended"],
  "parserOptions": { "ecmaVersion": 2018, "sourceType": "module" },
  "rules": {}
}

It tells the ESLint linter to:

  • use Typescript parser
  • use Recommended Typescript preset for linting
  • use ES2018 and module sourceType to match ts.config settings

Add the following lines in package.json:

{
  "scripts": {
    "lint": "eslint src/**/*.ts",
    "format": "eslint src/**/*.ts --fix"
  }
}

To lint, run the following in shell

yarn lint

To format the code to comply with linting rules, run the following in shell

yarn format

Prettier

Prettier drastically improves team consistency by automatically formatting the code. To enable prettier, we first install it by running:

yarn add prettier --dev

Configure prettier by adding a .prettierrc to the root of the project with the following content

{
    "semi": true,
    "trailingComma": "all",
    "singleQuote": true,
    "printWidth": 120,
    "tabWidth": 2
}

The setting let Prettier to

  • Ensure semi colon at the end of each statement
  • Ensure trailing comma at the end of each statement
  • Convert all double quotes to single quotes where applicable
  • Break into new lines for all lines greater than 120 characters wide
  • Ensure tab width is 2 characters

In Visual Studio Code, Ctrl (CMD) + P then select Format Code, or enable Format on Save in settings for best result.

Husky

No matter how careful I am, I always endup with situations where I changed and committed the code to Github without linting, and that can lead to failure CI builds.

A good pratcice is to lint before commit. Husky is a very popular plugin to achieve so.

Install Husky by

yarn add husky --save-dev

Husky does not have its own configuration files. Instead we will add its config into package.json:

{
  "husky": {
    "hooks": {
      "pre-commit": "yarn lint"
    }
  }
}

Next time you commit, husky would exit the git commit when the code does not pass linting.

The End

There are so many more things you could do to your project to ensure productivity, consistency and coding styles, but I think this is a good start. This article will be subject to improvements to the latest changes and practices.

If you find this article useful please let me know.

@claranceliberi
Copy link

Hi 👋,

good job 🎉

but i have question,
why we use eslint with typescript files, when we run javascript files? 🤔

we need to improve code quality in javascript file to run faster so, should we use eslint with compiled (builded) javascripts? 🤗
and how?

I think we also need to improve code readability , to make it easy for other dev's to read our codes

@mikoloism
Copy link

mikoloism commented Jun 19, 2021

I think we also need to improve code readability , to make it easy for other dev's to read our codes

Actually YES 🤗

@ehaynes99
Copy link

we need to improve code quality in javascript file to run faster so, should we use eslint with compiled (builded) javascripts?
and how?

Linting is purely a cosmetic ruleset for the source code. It's not for compiled code, and definitely not related in any way to execution speed.

@maelfosso
Copy link

Thank you very much

@peterkitonga
Copy link

Thank you for this awesome gist.

@nealchen-cn
Copy link

This is very helpful!

@axelgar
Copy link

axelgar commented Oct 20, 2021

Hey @silver-xu thank you so much for this, really useful!
Only one small question I think for the command to add husky as a dev dependancy the --save-dev is for npm rather than yarn and the correct one would actually be the ones you were using for prettier, etc. right?
Again thanks for this 👏

@Ritcabuchi
Copy link

Thanks, very useful!

@RambousekTomas
Copy link

Thank you!

@wutangpaul
Copy link

Should it not be tsconfig.json rather than ts.config.json?

@Muzzamil1
Copy link

Thanks for this great article.
I normally like to apply linting while saving the file. Add these lines in the setting.json

"editor.formatOnSave": true,
"editor.codeActionsOnSave": [
    "source.fixAll.format",
    "source.fixAll.eslint"
  ],

@divinrkz
Copy link

divinrkz commented Dec 2, 2021

DANG!,
Really needed this.

@ginabethrussell
Copy link

Thank you. This was excellent. You may want to edit the line to install husky to use --dev instead of --save-dev for yarn .

@mikhailkaryamin
Copy link

Good job!

@Shadi-Ayoub
Copy link

Neat and to the point. Thank you!

@imhardayalsingh
Copy link

Should it not be tsconfig.json rather than ts.config.json?

Yes

@imhardayalsingh
Copy link

Thanks, very useful!

@toluolatubosun
Copy link

Amazing article 🍻

@silavsale
Copy link

Great, thanks! 🥇

@blanho
Copy link

blanho commented Feb 11, 2023

thanks, mate

@rockyessel
Copy link

Hello, there, im not new to nodejs, but new to using typescript with node.js.
and I followed the article, and got an error at the .eslintrc
`
$ npm run lint

backend_api@1.0.0 lint
eslint src/**/*.ts

Oops! Something went wrong! :(

ESLint: 8.34.0

ESLint couldn't find the config "react-app" to extend from. Please check that the name of the config is correct.

The config "react-app" was referenced from the config file in "C:\Users\essel_r\Desktop\everfile\package.json".

If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.`

@wutangpaul
Copy link

You might need to install the ESLint plugin?

npm i eslint-plugin-react-app

@sumitbopche01
Copy link

Amazing. Thank You

@heitor931
Copy link

Amazing...

@avinashbuddana
Copy link

Thanks For sharing !!!

@Shahidkhan0786
Copy link

$ eslint src/**/*.ts
node:internal/modules/cjs/loader:1078
throw err;
^

Error: Cannot find module 'G:\g\hami'\Marquee\node_modules\eslint\bin\eslint.js'
at Module._resolveFilename (node:internal/modules/cjs/loader:1075:15)
at Module._load (node:internal/modules/cjs/loader:920:27)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
at node:internal/main/run_main_module:23:47 {
code: 'MODULE_NOT_FOUND',
requireStack: []
}

Node.js v18.15.0
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this comman

Kindly help me to solve this

@iamAravindks
Copy link

some of you have an issue regarding husky set up , then do this

Edit package.json > prepare script and run it once:

npm pkg set scripts.prepare="husky install"
npm run prepare
Add a hook:

npx husky add .husky/pre-commit "npm run lint"
git add .husky/pre-commit

then try to make a commit

@buravlev-arthur
Copy link

Using this manual second time. It save a lot of time. Thanks!

@laoshaw
Copy link

laoshaw commented Mar 7, 2024

eslint-config-prettier might be added

@adrianchinjen
Copy link

Hi, I created my own template with the help of this. Thanks, I am creating my own template for my personal projects which is based on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment