eslint-plugin-prettier: eslint-plugin-prettier is very slow

What version of eslint are you using? v7.2.0 What version of prettier are you using? v2.0.5 What version of eslint-plugin-prettier are you using? v3.1.3 Please paste any applicable config files that you’re using (e.g. .prettierrc or .eslintrc files)

{
  "extends": [
    "eslint:recommended",
    "plugin:import/errors",
    "plugin:import/warnings",
    "plugin:promise/recommended",
    "plugin:prettier/recommended"
  ],
  "plugins": [
    "import",
    "promise"
  ],
  "env": {
    "node": true,
    "es2017": true,
    "browser": true,
    "commonjs": true
  },
  "parserOptions": {
    "ecmaVersion": 2018,
    "sourceType": "module"
  },
  "globals": {
    "Component": true,
    "Page": true,
    "wx": true,
    "App": true
  },
  "ignorePatterns": [
    "dist/*",
    "examples/dist/*",
    "src/common/async-validator/*",
    "examples/pages/filter/components/wemark"
  ],
  "rules": {
    "space-before-function-paren": "off",
    "indent": ["error", 2,{
      "SwitchCase":1
    }],
    "quotes": [
      "error", "single", {
        "allowTemplateLiterals": false
      }
    ],
    "semi": ["error"],
    "no-console": [
      "warn", {
        "allow": ["info", "warn", "error"]
      }
    ],
    "no-undef": "error",
    "no-useless-escape": "off",
    "eqeqeq": ["error", "always"],
    "promise/always-return": "off"
  }
}
{
  "singleQuote": true,
  "trailingComma": "none",
  "arrowParens": "avoid",
  "quoteProps": "preserve",
  "printWidth": 120
}

What source code are you linting? JavaScript、JSON、LESS What did you expect to happen? less time What actually happened? It takes a long time

image

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 40
  • Comments: 26 (4 by maintainers)

Commits related to this issue

Most upvoted comments

eslint: 8.11.0 prettier: 2.6.0 eslint-plugin-prettier: 4.0.0

Rule Time (ms) Relative
prettier/prettier 153133.363 98.3%
vue/attribute-hyphenation 648.661 0.4%
@typescript-eslint/no-unused-vars 595.310 0.4%
no-redeclare 176.444 0.1%
padding-line-between-statements 144.199 0.1%
max-len 120.984 0.1%
vue/valid-next-tick 42.244 0.0%
no-restricted-imports 40.963 0.0%
@typescript-eslint/no-empty-function 39.269 0.0%
@typescript-eslint/no-loss-of-precision 39.268 0.0%

This should be fixed as of v3.3.0.

I’ve known for a while that not clearing the prettier config cache is the fix for this but wanted to see if there was a way to get the performance speedup without impacting usage in editors - as with this change eslint plugins in editors keep using old cached prettier config instead of spotting when you make changes to prettier config.

The solution is easy but not ideal: “When you make a config change you may need to restart your editor for it to notice”. I couldn’t find fix that avoided that, but the size of the speedup is worth needing that extra step as 99% of the time you’re not fiddling with settings.

@BPScott Can this problem be solved?

Seeing the same thing:

Rule                              | Time (ms) | Relative
:---------------------------------|----------:|--------:
prettier/prettier                 | 11580.842 |    57.7%
import/namespace                  |  4941.682 |    24.6%
react/no-deprecated               |   465.174 |     2.3%
import/no-extraneous-dependencies |   450.004 |     2.2%
react/no-direct-mutation-state    |   312.252 |     1.6%
import/no-unresolved              |   237.725 |     1.2%
simple-import-sort/sort           |   185.009 |     0.9%
react/no-string-refs              |   181.877 |     0.9%
react/require-render-return       |   160.600 |     0.8%
no-unused-vars                    |   159.425 |     0.8%

package.json

{
   "eslint": "6.8.0",
    "eslint-config-prettier": "6.9.0",
    "eslint-import-resolver-babel-module": "5.1.1",
    "eslint-plugin-import": "2.19.1",
    "eslint-plugin-jsx-a11y": "6.2.3",
    "eslint-plugin-prettier": "3.1.2",
    "eslint-plugin-react": "7.17.0",
    "eslint-plugin-react-hooks": "2.3.0",
    "eslint-plugin-simple-import-sort": "5.0.0",
    "eslint-plugin-testcafe": "0.2.1",
    "prettier": "1.19.1",
}
.eslintrc.js
const typescriptEslintRecommendedRules = require('@typescript-eslint/eslint-plugin').configs.recommended.rules;

const config = {
"env": {
  "browser": true,
  "commonjs": true,
  "es6": true,
  "node": true
},
"extends": [
  "eslint:recommended",
  "plugin:react/recommended",
  "plugin:import/errors",
  "plugin:import/warnings",
  "plugin:jsx-a11y/recommended",
  "plugin:prettier/recommended"
],
"parser": "babel-eslint",
"parserOptions": {
  "ecmaFeatures": {
    "jsx": true
  },
  "ecmaVersion": 2019,
  "sourceType": "module"
},
"plugins": ["react-hooks", "simple-import-sort"],
"rules": {
  "import/order": "off",
  "jsx-a11y/label-has-associated-control": "off",
  "jsx-a11y/no-onchange": "off",
  "jsx-a11y/anchor-is-valid": [
    "error",
    {
      "components": ["Link"],
      "specialLink": ["hrefLeft", "hrefRight"],
      "aspects": ["invalidHref", "preferButton"]
    }
  ],
  "react/react-in-jsx-scope": "off",
  "react/display-name": "off",
  "react-hooks/rules-of-hooks": "error",
  "react-hooks/exhaustive-deps": "warn",
  "simple-import-sort/sort": "error",
  "import/no-extraneous-dependencies": ["error", { "devDependencies": false }]
},
"settings": {
  "react": {
    "version": "detect"
  },
  "import/resolver": {
    "babel-module": {},
    "node": {
      "extensions": [".js", ".jsx", ".ts", ".tsx"]
    }
  }
},
"overrides": []
};

config.overrides.push({
files: ["**/*.ts", "**/*.tsx"],
parser: "@typescript-eslint/parser",
parserOptions: {
  ecmaFeatures: {
    jsx: true
  },
  ecmaVersion: 2019,
  sourceType: 'module',
  project: './tsconfig.json',
},
extends: config.extends.concat(["plugin:@typescript-eslint/recommended"]),
plugins: config.plugins.concat(['@typescript-eslint']),
rules: Object.assign({}, config.rules, typescriptEslintRecommendedRules, {
  "@typescript-eslint/no-this-alias": "warn",
  "@typescript-eslint/camelcase": "warn",
  "@typescript-eslint/no-explicit-any": "off",
  "@typescript-eslint/explicit-function-return-type": "off",
  "@typescript-eslint/no-unused-vars": "off",
  "@typescript-eslint/no-use-before-define": "off",
  "@typescript-eslint/camelcase": "off",
  "@typescript-eslint/no-empty-function": "off",
  "for-direction": "off",
  "no-useless-escape": "off",
  "react/prop-types": "off",
})
});

// Allow test files to import devDependencies
config.overrides.push({
files: ["**/*.test.js", "**/*.test.ts", "**/*.test.tsx", "functional-tests/**/*.js"],
rules: {
  "import/no-extraneous-dependencies": ["error", { "devDependencies": true }]
}
});

config.overrides.push({
"files": ["functional-tests/**/*.js"],
"plugins": [
  "testcafe"
],
"extends": "plugin:testcafe/recommended"
});

module.exports = config;

I had a large js file with 30K line of code in my project’s root directory. adding it to the .prettierignore file solved the issue for me. so, I think that the issue is not with the prettier plugin it’s related to projects, just look for the large files and prettierignore it.

I was reading a tweet regarding this today and thought I should give it a try, I was surprised to see the results (this is a React Native, Typescript codebase).

TIMING=1 npm run lint:

Rule                              | Time (ms) | Relative
:---------------------------------|----------:|--------:
prettier/prettier                 |  1333.671 |    91.6%
react/no-string-refs              |    46.890 |     3.2%
@typescript-eslint/no-unused-vars |     7.696 |     0.5%
semi                              |     4.267 |     0.3%
react-native/no-inline-styles     |     4.207 |     0.3%
react-hooks/exhaustive-deps       |     3.590 |     0.2%
react-hooks/rules-of-hooks        |     3.248 |     0.2%
no-obj-calls                      |     2.784 |     0.2%
no-div-regex                      |     2.560 |     0.2%
no-undef-init                     |     2.220 |     0.2%

cat package.json | grep -E "eslint|prettier":

    "@react-native-community/eslint-config": "^2.0.0",
    "@typescript-eslint/eslint-plugin": "^3.2.0",
    "@typescript-eslint/parser": "^3.2.0",
    "eslint": "^7.1.0",
    "eslint-config-prettier": "^6.11.0",
    "eslint-plugin-prettier": "^3.1.3",
    "eslint-plugin-react-hooks": "^4.0.4",
    "prettier": "^2.0.5",

cat .prettierrc.js:

module.exports = {
  bracketSpacing: true,
  jsxBracketSameLine: true,
  singleQuote: true,
  trailingComma: 'all',
  semi: false,
};

cat .eslintrc.js:

module.exports = {
  root: true,
  extends: [
    '@react-native-community',
    'prettier/@typescript-eslint',
    'plugin:prettier/recommended',
    'plugin:react-hooks/recommended',
  ],
  parser: '@typescript-eslint/parser',
  plugins: ['@typescript-eslint'],
  rules: {
    semi: [2, 'never'],
  },
  overrides: [
    {
      files: ['**/*.test.js', '**/*.test.jsx', '**/*.test.ts', '**/*.test.tsx'],
      env: {
        jest: true,
      },
    },
  ],
}

I’m not accustomed with prettier cli’s API so I don’t know how to trigger the Timing=1 to compare the results, neither could I capture the output of eslint --debug’s output in order to do anything meaningful with the results (they show up on the screen too fast and then are not piped to stdout npm run lint -- --debug > res.txt).

This may help someone: I was able to reduce the time from 4 seconds to 370ms on my small project by creating a .prettierignore file:

build
coverage
.gitlab
.vscode
node_modules

Same here, prettier takes a lot of time, which results in really bad developer experience

Rule Time (ms) Relative
prettier/prettier 4426.921 84.0%
import/order 412.818 7.8%
react/no-direct-mutation-state 91.420 1.7%
@typescript-eslint/no-unused-vars 71.658 1.4%
react/no-typos 39.917 0.8%
react/require-render-return 33.776 0.6%
no-empty-character-class 11.034 0.2%
react-hooks/exhaustive-deps 10.065 0.2%
no-restricted-globals 9.641 0.2%
react-hooks/rules-of-hooks 8.002 0.2%
lint success