Migrating and Configuring Eslint in Angular 11

In the earlier version, Angular implements the linting with TSLint but with Angular 11 announced that the TSLint linting replaced with the ESLint.

Usage with Nx Monorepos

Nx leans for some, but not for all packages from this project. It does not use the builder to execute ESLint.

Packages included in this Project

The following packages are included in your project.

  • @angular-eslint/builder:This package is used to execute ESLint in your project using standard commands such as ng lint.
  • @angular-eslint/eslint-plugin: This is the ESLint specific package that contains some specific rules that are specific for the Angular projects. It can be combined with other ESLint packages.
  • @angular-eslint/template-parser: This is the ESLint specific parser package that allows you to written the custom ESLint rules in your Angular template.
  • @angular-eslint/eslint-plugin-template:This package is used in conjunction with @angular-eslint/template-parser which allows template specific rules to run.
  • @angular-eslint/schematics: This package is used to add and update the configuration files that are running on the Angular template.

Migrating an Angular CLI project

Step 1: Add the dependencies

To do the migration, run the schematic package to add the @angular-eslint into your project.

ng add @angular-eslint/schematics

After running this command, it will install the packages and add the packages in the package.json file.

{
  "name": "eslint-demo",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "~11.0.1",
    "@angular/common": "~11.0.1",
    "@angular/compiler": "~11.0.1",
    "@angular/core": "~11.0.1",
    "@angular/forms": "~11.0.1",
    "@angular/platform-browser": "~11.0.1",
    "@angular/platform-browser-dynamic": "~11.0.1",
    "@angular/router": "~11.0.1",
    "rxjs": "~6.6.0",
    "tslib": "^2.0.0",
    "zone.js": "~0.10.2"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "~0.1100.2",
    "@angular/cli": "~11.0.2",
    "@angular/compiler-cli": "~11.0.1",
    "@types/jasmine": "~3.6.0",
    "@types/node": "^12.11.1",
    "codelyzer": "^6.0.0",
    "jasmine-core": "~3.6.0",
    "jasmine-spec-reporter": "~5.0.0",
    "karma": "~5.1.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-coverage": "~2.0.3",
    "karma-jasmine": "~4.0.0",
    "karma-jasmine-html-reporter": "^1.5.0",
    "protractor": "~7.0.0",
    "ts-node": "~8.3.0",
    "tslint": "~6.1.0",
    "typescript": "~4.0.2",
    "eslint": "^7.6.0",
    "eslint-plugin-import": "2.22.1",
    "eslint-plugin-jsdoc": "30.7.6",
    "eslint-plugin-prefer-arrow": "1.2.2",
    "@angular-eslint/builder": "0.8.0-beta.3",
    "@angular-eslint/eslint-plugin": "0.8.0-beta.3",
    "@angular-eslint/eslint-plugin-template": "0.8.0-beta.3",
    "@angular-eslint/schematics": "^0.8.0-beta.3",
    "@angular-eslint/template-parser": "0.8.0-beta.3",
    "@typescript-eslint/eslint-plugin": "4.3.0",
    "@typescript-eslint/parser": "4.3.0"
  }
}

Step 2: Run the eslint schematic on a project

After that, you can choose the project that you want to migrate. The following command can run the eslint schematic.

ng g @angular-eslint/schematic:convert-tslint-to-eslint {{ Your project name }}

After running this command, eslintrc.json will be created. Let’s take a look at the configuration that was generated from the above command.

{
  "root": true,
  "ignorePatterns": [
    "projects/**/*"
  ],
  "overrides": [
    {
      "files": [
        "*.ts"
      ],
      "parserOptions": {
        "project": [
          "tsconfig.json",
          "e2e/tsconfig.json"
        ],
        "createDefaultProgram": true
      },
      "extends": [
        "plugin:@angular-eslint/ng-cli-compat",
        "plugin:@angular-eslint/ng-cli-compat--formatting-add-on",
        "plugin:@angular-eslint/template/process-inline-templates"
      ],
      "rules": {
        "@angular-eslint/component-selector": [
          "error",
          {
            "type": "element",
            "prefix": "app",
            "style": "kebab-case"
          }
        ],
        "@angular-eslint/directive-selector": [
          "error",
          {
            "type": "attribute",
            "prefix": "app",
            "style": "camelCase"
          }
        ]
      }
    },
    {
      "files": [
        "*.html"
      ],
      "extends": [
        "plugin:@angular-eslint/template/recommended"
      ],
      "rules": {}
    }
  ]
}

Notice that the configuration is inside in the overrides field because the Angular project has the HTML files and typescript files. We can avoid the conflicts using the ESLint overrides field that allows us to separate rules for different file types.

In the above configuration, we can see the configuration of the @angular-eslint plugin:@angular-eslint/ng-cli-compat and @angular-eslint/ng-cli-compat--formatting-add-on. These two configurations are used for the automatic matching of TSLint rules and ESLint rules.

env: What to include in a linting and what version to be used in your project.

extends: What packages will be extended.

parser: What parser to be used.

parserOptions: The Project setting for typescript.

Changing the configuration

To change the configuration, first we will remove both plugins plugin:@angular-eslint/ng-cli-compat and plugin:@angular-eslint/ng-cli-compat--formatting-add-on from the extends field. After that we can add the plugin of the plugin:@angular-eslint/recommended in the extends field.

Let’s see the updated configuration file.

{
  "root": true,
  "ignorePatterns": [
    "projects/**/*"
  ],
  "overrides": [
    {
      "files": [
        "*.ts"
      ],
      "parserOptions": {
        "project": [
          "tsconfig.json",
          "e2e/tsconfig.json"
        ],
        "createDefaultProgram": true
      },
      "extends": [
        "plugin:@angular-eslint/recommended",
        "plugin:@angular-eslint/template/process-inline-templates"
      ],
      "rules": {
        "@angular-eslint/component-selector": [
          "error",
          {
            "type": "element",
            "prefix": "app",
            "style": "kebab-case"
          }
        ],
        "@angular-eslint/directive-selector": [
          "error",
          {
            "type": "attribute",
            "prefix": "app",
            "style": "camelCase"
          }
        ]
      }
    },
    {
      "files": [
        "*.html"
      ],
      "extends": [
        "plugin:@angular-eslint/template/recommended"
      ],
      "rules": {}
    }
  ]
}

The plugin:@angular-eslint/recommended plugin is used to disable some conflicting rules of the eslint:recommended for usage with the typescript and add the typescript rules. There are another configuration adding in the extends field and the configuration looks like:

"extends": [
        "plugin:@angular-eslint/recommended",
        "eslint:recommended",
        "plugin:@typescript-eslint/recommended",
        "plugin:@typescript-eslint/recommended-requiring-type-checking",
        "plugin:@angular-eslint/template/process-inline-templates"
      ],

In the above configuration, the order of the included plugins matters. If we have included plugin typescript-recommended before the eslint:recommended then the conflicting rules will be enabled.

Adding Prettier

Prettier is used for detecting and automatically fixing the styling issues.

Installing the Prettier

We will be installing the configuration dependencies of the prettier ESLint plugin of the following command:

npm i -D prettier eslint-plugin-prettier eslint-config-prettier

We will install the three configuration dependencies: prettier, eslint-plugin-prettier and eslint-config-prettier. These plugins are needed for fixing the styling but also disabling some styling rules of the ESLint so that there are no conflicts between ESLint and Prettier.

Looking to hire Angular Developer? Your Search ends here.

Integrating Prettier

To integrate the prettier plugin, we need to add the plugin to extends field in the .eslintrc.json file.

{
  "root": true,
  "ignorePatterns": [
    "projects/**/*"
  ],
  "overrides": [
    {
      "files": [
        "*.ts"
      ],
      "parserOptions": {
        "project": [
          "tsconfig.json",
          "e2e/tsconfig.json"
        ],
        "createDefaultProgram": true
      },
      "extends": [
        "plugin:@angular-eslint/ng-cli-compat",
        "plugin:@angular-eslint/ng-cli-compat--formatting-add-on",
        "plugin:@angular-eslint/template/process-inline-templates",
        "plugin:prettier/recommended"
      ],
      "rules": {
        "@angular-eslint/component-selector": [
          "error",
          {
            "type": "element",
            "prefix": "app",
            "style": "kebab-case"
          }
        ],
        "@angular-eslint/directive-selector": [
          "error",
          {
            "type": "attribute",
            "prefix": "app",
            "style": "camelCase"
          }
        ]
      }
    },
    {
      "files": [
        "*.html"
      ],
      "extends": [
        "plugin:@angular-eslint/template/recommended"
      ],
      "rules": {}
    }
  ]

If you want to enable the styling and formatting in the HTML files, then you need to add the code in the HTML entry of the overrides field.

"extends": [
        "plugin:@angular-eslint/template/recommended",
        "prettier/@typescript-eslint",
        "plugin:prettier/recommended"
      ],

In the above code, the prettier code is written at the end of the extends array because the prettier config disables the ESLint rules.

Conclusion

In this blog, we have discussed about ESLint and what packages are included in the project. We saw how to migrate the TSLint project to the ESLint and also learn the installing and integrating of prettier plugin.

19