ESLint, TypeScript, and Prettier Config Files
How to setup the modern frontend project
It is easy to get started with the front-end development. Many libraries provide the starter kits. You type one command, execute, and boom. The project is ready.
Yet, when the modification is necessary, things are just so interwoven. So much headache. So much waste of time going through the doc to doc. You have to solve the puzzle.
Here is my personal solution to that puzzle. The puzzle comprising ESLint, TypeScript, and Prettier configs.
When I start a new project or add modification to the ongoing project, I use the following config files as a starting point.
TypeScript
tsconfig.json
{
"compilerOptions": {
"allowJs": false,
"allowSyntheticDefaultImports": false,
"esModuleInterop": false,
"forceConsistentCasingInFileNames": true,
"isolatedModules": false,
"jsx": "react",
"lib": ["DOM", "ES2018"],
"module": "ESNext",
"moduleResolution": "Node",
"noEmit": false,
"outDir": "./dist/",
"resolveJsonModule": false,
"skipLibCheck": true,
"strict": true,
"target": "ESNext",
"useDefineForClassFields": true
},
"include": ["src/ts/**/*"]
}
One thing to note is that I set "noEmit": false. This is because I manage the build task with Gulp, which uses Webpack and ts-loader. In many cases you simply use TypeScript or other bundlers with the TypeScript plugin for transpilation. In which case "noEmit": true is the right configuration.
For more information on tsconfig, see Intro to the TSConfig Reference.
Bundlers
You may need to configure based on the bundler you use:
Prettier
.prettierrc
{
"printWidth": 80,
"tabWidth": 2,
"semi": false,
"useTabs": true,
"singleQuote": true,
"jsxSingleQuote": false,
"trailingComma": "es5",
"bracketSpacing": true,
"bracketSameLine": false,
"arrowParens": "always",
"proseWrap": "never",
"htmlWhitespaceSensitivity": "css",
"vueIndentScriptAndStyle": false,
"endOfLine": "lf",
"embeddedLanguageFormatting": "auto",
"singleAttributePerLine": false,
"trailingCommaPHP": true,
"overrides": [
{
"files": "*.html",
"options": {
"printWidth": 999
}
},
{
"files": ["*.json"],
"options": {
"tabWidth": 4,
"useTabs": false
}
},
{
"files": "*.php",
"options": {
"braceStyle": "1tbs"
}
}
]
}
I prefer tabs over spaces, like Richard Hendricks, with the corresponding indent size to two spaces.
I don’t like HTML tags being wrapped into multi-line for each attribute. To prevent this, I set "printWidth": 999 for HTML files.
PHP
In order to make Prettier effective on PHP files, I install the additional package @prettier/plugin-php:
# npm
npm install --save-dev @prettier/plugin-php
# yarn
yarn add --dev prettier @prettier/plugin-php
# pnpm
pnpm add --save-dev@prettier/plugin-php
Ignore Files
Here is also my .prettierignore file. It would be better to exclude the files that you don’t code or modified by the tools.
.prettierignore
/build
/dist
/font
/img
/node_modules
/vendor
.env
package.json
ESLint
You need a bit of work to integrate ESLint with TypeScript and Prettier.
ESLint–TypeScript Package
Ironically, Microsoft does not provide the ESLint plugin for their tool. Luckily we have a community backup. It’s typescript-eslint.
# npm
npm install --save-dev @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint typescript
# yarn
yarn add --dev @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint typescript
# pnpm
pnpm add --save-dev @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint typescript
ESLint–Prettier Package
Prettier does have its own ESLint plugin eslint-config-prettier.
#npm
npm install --save-dev eslint-config-prettier
# yarn
yarn add --dev eslint-config-prettier
#pnpm
pnpm add --save-dev eslint-config-prettier
Config
As of September 2023, ESLint is amid of updating their config scheme. The name of the new default config file is eslint.config.js. However, typescript-eslint does not yet support the new scheme. So we are going to stick to the deprecating .eslintrc.js for a while.
.eslintrc.js
/* eslint-env node */
module.exports = {
env: {
browser: true,
es2021: true,
},
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'prettier',
],
globals: {
axios: 'readonly',
jQuery: 'readonly',
},
overrides: [],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
plugins: ['@typescript-eslint'],
rules: {
'no-unused-vars': 'off', // Required by @typescript-eslint/no-unused-vars
'padding-line-between-statements': [
'error',
{ blankLine: 'always', prev: ['class', 'function'], next: '*' },
{
blankLine: 'always',
prev: '*',
next: ['class', 'function', 'return', 'try'],
},
{
blankLine: 'always',
prev: ['import', 'for', 'if', 'switch', 'while'],
next: ['const', 'expression', 'let'],
},
{
blankLine: 'always',
prev: ['const', 'expression', 'let'],
next: ['for', 'if', 'switch', 'try', 'while'],
},
{
blankLine: 'always',
prev: ['const', 'expression', 'import', 'let'],
next: 'export',
},
{ blankLine: 'always', prev: ['for', 'switch', 'while'], next: 'if' },
{ blankLine: 'always', prev: ['if', 'switch', 'while'], next: 'for' },
{ blankLine: 'always', prev: ['if', 'for', 'while'], next: 'switch' },
{ blankLine: 'always', prev: ['if', 'for', 'switch'], next: 'while' },
],
/* @typescript-eslint */
'@typescript-eslint/consistent-type-imports': [
'error',
{
prefer: 'type-imports',
disallowTypeAnnotations: true,
fixStyle: 'separate-type-imports',
},
],
'@typescript-eslint/no-unused-vars': [
'error',
{ vars: 'all', args: 'all' },
],
},
root: true,
}
Integration with Front-End Libraries
If you use one of the following modern front-end libraries, you might need the additional configuration.
- React
- Vue
- Angular
- Svelte
- Preact
Bonus
As a bonus content, I present my personal editor config and VS Code setting files.
Editor Config
.editorconfig
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = tab
indent_size = 2
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.json]
indent_style = space
indent_size = 4
VS Code
.vscode/settings.json
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"editor.tabSize": 2,
"editor.insertSpaces": false,
"editor.detectIndentation": false,
"eslint.enable": true
}