由賽巴斯蒂安·韋伯撰寫✏️
多年來,ESLint 一直是 JavaScript 和 TypeScript 專案 linting 的事實上的標準。本採用指南解釋了為什麼 2024 年仍然如此。
本文介紹了 ESLint 的當前版本,該版本於 2024 年夏季發布(v9.7)。因此,僅描述 v9 的概念和特性,與先前的版本相比,它帶來了一些重大的突破性變化。
如果您想使用舊版而不使用具有平面設定檔的最新配置風格,您可以查閱官方遷移指南。
ESLint 是一個可設定且可擴充的 JavaScript linter,用於執行靜態程式碼分析。它可以幫助您追蹤和解決原始程式碼中的問題,而無需執行它。問題可以是任何事情,從潛在的運行時錯誤、不良的編碼實踐到程式碼格式問題。
作為軟體品質工具,ESLint 旨在使程式碼更加一致和健壯。它藉助斷言(即所謂的 lint 規則)檢查程式碼,了解程式碼的外觀或行為。例如,使用 no-use-before-define 規則,您可以指示 ESLint 在聲明之前遇到函數呼叫時報告違規行為。
此外,可以將每個規則的違規嚴重程度指定為警告或錯誤。因此,在 CI/CD 管道中,檢測步驟可能會因報告的錯誤而失敗,這表明需要調查更大的問題。
在解析器和插件的幫助下,ESLint 可以配置為理解和檢查 TypeScript 或 JavaScript 語法擴充(如 JSX),或 JavaScript 框架(如 React 或 Vue)的概念。
ESLint 的想法是由於當時可用的 linting 工具(例如 JSCS、JSLint 和 JSHint)的不足而產生的。這些工具的規則集和配置功能有些僵化,很難根據特定的專案需求調整規則。
自從 ESLint 的初始版本以來,規則就建構了 ESLint 的主幹。他們可能會提供有關如何手動解決直接顯示在程式碼編輯器內有問題的程式碼位置(帶有標記和覆蓋)的違規問題的建議。
此外,規則可能會提供修復,使 ESLint 能夠自動解決 CLI 或程式碼編輯器中的違規問題;例如,將箭頭函數重構為隱式傳回變體。
除了透過更廣泛的工具和語言支援提供更好的 linting 體驗之外,ESLint 的另一個賣點過去是,現在仍然是可插拔架構。與競爭對手相比,它具有更大的可擴展性和可自訂性,允許開發人員創建和共享自訂規則並將 ESLint 擴展到其核心功能之外。
ESLint 多年來崛起的證據是它與 JSCS 合併,而 JSCS 隨著時間的推移正在節節敗退。自誕生以來,ESLint 已經發生了顯著的發展:
在維護 JavaScript 專案中的程式碼品質和一致性方面,ESLint 是一個出色的工具。將其採用到您的專案中可以顯著增強 DX,確保您的程式碼庫保持乾淨、可讀且沒有錯誤。
ESLint 附帶了許多規則,可以輕鬆地根據專案的要求進行調整。您甚至可以藉助社群外掛程式添加更多規則。此外,解析器可用於擴充 ESLint 的功能。
在深入研究 ESLint 的核心概念和功能之前,我們需要先設定 ESLint 工作流程。
在已有 package.json 的資料夾中,您可以執行下列指令將 ESLint 加入到您的開發專案中。 ESLint 設計用於本地安裝。使用以下命令,您可以執行互動式安裝指南,新增預設的 ESLint 設定:
# run at root level of your project $ npm init @eslint/config@latest
您也可以使用可共享的配置來初始化您的專案。您可以透過執行 Github 搜尋找到其中的許多內容。命名約定是以 eslint-config- 開始自訂配置。
安裝精靈會詢問您幾個有關當前專案設定的問題:完成安裝後,ESLint 建立了一個設定文件,其檔案後綴取決於您選擇的模組變體的類型。對於 ESM,您可以在工作目錄中找到 eslint.config.mjs。作為慣例,.mjs 檔案前綴表示您的專案使用 ESM,但 eslint.config.js 具有相同的效果。
這個所謂的普通 JavaScript 專案的平面配置最初看起來像這樣:
// eslint.config.mjs import globals from "globals"; import pluginJs from "@eslint/js"; export default [ { languageOptions: { globals: globals.browser } }, pluginJs.configs.recommended, ];
透過上面的配置,預設的 ESLint JavaScript npm 套件 @eslint/js 與瀏覽器環境 (globals.browser) 和所有建議的 JS 規則一起使用。讓我們建立一個簡單的 JavaScript 文件,其中包含一些違反規則的內容:
// playground.js var testVar = "This should be 'let' or 'const'"; undefinedFunctionCall();
我們利用 ESLint CLI 和 npx,其路徑與 eslint.config.mjs 所在的路徑相同:
$ npx eslint # all files recursively $ npx eslint playground.js # specific file(s) $ npx eslint *.js # ESLint supports globs
ESLint GitHub 專案是在monorepo 中組織的,您可以透過查看來查閱更多配置選項@eslint/js 包。上面的配置添加了所有建議的規則,這些規則都有錯誤的嚴重程度。我們稍後將了解有關違規嚴重程度的更多資訊。
以下配置示範了使用建議規則的不同變體:
export default [ // ... // pull in all recommended rules pluginJs.configs.recommended, // all but different approach { rules: pluginJs.configs.recommended.rules }, // all but override existing rules { rules: { ...pluginJs.configs.recommended.rules, // change the severity level "no-unused-vars": "warn", }, } ];
import globals from "globals"; export default [ { languageOptions: { globals: globals.browser } }, { rules: { "no-unused-vars": "warn", }, }, ];
如果您發現VS Code 中的ESLint 擴充功能不會回應您的設定更改,則以下選項之一通常會對您有所幫助。
首先,查看 VS Code 的輸出面板,從下拉清單中選擇 ESLint,然後尋找錯誤:其次,在命令面板的幫助下重新啟動內部 ESLint 伺服器並執行 ESLint:Restart ESLint Server .
新增 TypeScript 支援
$ npm i -D eslint @eslint/js @types/eslint__js typescript typescript-eslint@8.0.0-alpha.10 --force
// eslint.config.mjs import eslint from "@eslint/js"; import tseslint from "typescript-eslint"; export default tseslint.config( eslint.configs.recommended, ...tseslint.configs.recommended );
需要了解的關鍵 ESLint 概念和功能
有關平面配置的更多信息
Typically your flat config file is slim, as ESLint comes with reasonable default values for projects. By default, ESLint searches for source files with the suffixes .js, .mjs, and .cjs. In what follows, the terms flat config and eslint.config are used synonymously. The latter is representative of all file extensions (.*js).
When you use typescript-eslint, out-of-the-box ESLint will lint .ts, .tsx, .mts, and .cts files. As another example, all files with prefix .cjs are treated as JS files using CommonJS modules. Further, ecmaVersion: "latest" is the default, so ESLint expects you to work with the most recent version of ECMAScript:
{ files: ["**/*.cjs"], languageOptions: { sourceType: 'commonjs', ecmaVersion: 'latest' }, },
How do you know about these default values? ESLint ships a handy visual tool to inspect your eslint.config. With the ESLint Config Inspector, you learn how the configuration concept works. Similar to the CSS DevTools in browsers, where you can see how the styles come about, you find out what default values are applied or how rules get applied for different file globs: This tool is valuable since the effective configuration object returned by eslint.config may not be apparent when simply looking at the file. This is especially true because you can import external configurations or generate parts of the configuration on the fly. You can run it with the following command:
$ npx @eslint/config-inspector
The concept of eslint.config is pretty straightforward, you have to return an array of config objects. Every config object adds either configuration for all files or a subset of files specified by a file glob. Consequently, multiple config objects can be composed to an overall configuration. If you skip the files property, the config object applies to all files: ESLint takes care to merge all the config objects into one effective configuration. This can be traced with the help of the ESLint Config Inspector.
For files matching *.jsx, the languageOption is configured to interpret JSX files. Otherwise, ESLint does not understand how to handle JSX files. The optional name property is useful in combination with the Config Inspector to improve traceability: The languageOptions property is where ESLint gets to know what module system, ECMAScript version, or language extension you want to use. In the previous example, we told ESLint how to interpret JSX files with languageOptions.parserOptions.ecmaFeatures.jsx property.
You can opt out of the latest ECMAScript version — e.g., ecmaVersion: 2015. ESLint also assumes that ESM is the way you handle JS modules in your project. Therefore, the default is sourceType: "module" for .js and .jsm files. Otherwise, you have to opt out (sourceType: "script"). For .cjs files, the default is sourceType: "commonjs".
Another useful property is languageOptions.globals. In projects for the browser environment, ESLint needs to know global variables like window or console. Otherwise, ESLint incorrectly reports a no-undef error: You can specify your project-specific global variables with languageOptions.globals. For browser projects, you can import globals, which is a JSON file holding predefined global identifiers:
import globals from "globals"; // ... export default [ { name: "globals", languageOptions: { globals: globals.browser, }, }, // ... ];
Again, you can utilize the Config Inspector to see all global variable names: You can read about all configuration capabilities in the official docs.
For many projects, starting with a predefined rule set as provided by @eslint/js is a good choice. These sets provide a broad coverage of common issues and, if required, stylistic preferences.
When you run ESLint, either via CLI or the background process inside your code editor, rule violations are reported. For every violation, ESLint shows the rule ID (e.g., no-undef) and a short violation explanation.
With that rule ID, you can easily navigate to the rule detail page from the rules reference. Alternatively, from the VS Code extension (or any other code editor integration), you can click on the provided link: Every rule has an easy-to-read documentation page following the same structure, including a helpful TOC on the right: The rule details are handy for multiple reasons:
The latter is relevant to finding out how to tweak the rule inside of eslint.config.
There’s an important concept called violation severities. Every rule has a default severity level. You can change the severity level for every rule in eslint.config. There are three levels of severity:
To change a rule’s severity, set the rule ID equal to one of these values. The following example config demonstrates how to tweak different rules:
// eslint.config.js import pluginJs from "@eslint/js"; // override default values const modifiedRules = { // create a copy of the recommended rules to modify ...pluginJs.configs.recommended.rules, // turn rule off 'no-unused-vars': 0, // Require the use of === and !== // change default from error to warning 'eqeqeq': 1, // Disallow the use of variables before they are defined. // Except for hoisted functions 'no-use-before-define': ["error", { "functions": false }] } export default [ { name: "ESLint recommended rules with modifications", rules: modifiedRules, }, ];
The last example, no-use-before-define, demonstrates how to look up the options in the documentation and change them according to your preferences.
Most lint rules fall into one of two to three categories:
The use of stylistic rules falls into the scope of tools such as Prettier, which solely deal with code formatting. ESLint's stylistic rules (e.g., indent) may conflict with such dedicated formatters.
In October 2023, the ESLint team decided to deprecate all formatting rules, mainly for maintainability and architectural reasons. They have reserved the right to remove it from v10 onwards. You still have different options for combining ESLint with code formatting, as I will explain in the next section.
Later, we’ll discuss several options to use ESLint for code formatting.
You've already seen one variant to configure rules inside of eslint.config. Alternatively, to configure rules inside of a file, you can leverage configuration comments:
/* eslint no-unused-vars: "off" */ let unusedVariable; /* eslint eqeqeq: "warn" */ "hello world!" == "hello world" /* eslint no-use-before-define: ["error", { "functions": false }] */ let x = usedBeforeDefined(); function usedBeforeDefined() { return true; }
It's also possible to turn off rules with inline comments. This should only be used temporarily during development. Further, you should only commit these comments to VCS in exceptional cases. You can disable a rule for the whole file or the next line:
// the following disables the rule for the whole file /* eslint-disable eqeqeq */ var testVar = "This should be 'let' or 'const'"; // eslint-disable-next-line no-undef undefinedFunctionCall(); "hello world!" == "hello world"
You can also utilize the code editor integration to add these comments. With VS Code, you can right-click on ESLint errors or warnings and use the Quick Fix feature:
For a rule violation, your code editor may show a rule suggestion when you inspect the violation. In such a case, some problems reported by this rule are manually fixable by the code editor.
With the VS Code ESLint extension, you can do this from a context menu. When you browse through ESLint's Rules Reference, you can easily identify rules with suggestions by a bulb ? icon: Besides rule suggestions that require manual intervention of the developer to fix a violation, rule fixes safely correct violations automatically since they don't alter application logic. Every auto-fixable rule is marked with a wrench ? icon.
This feature is particularly useful for addressing common coding mistakes, formatting inconsistencies, and stylistic issues that adhere to predefined coding standards. To apply these automatic fixes, you can utilize the --fix option from the CLI:
$ npx eslint --fix
Later, we'll see how to establish a productive development workflow in your code editor to perform auto-fix on saving source files.
ESLint has a large community offering many publicly available configurations you can integrate via npm. These shared npm packages can contain one or more of the following concepts: configuration, rules, plugins, processors, and parsers. Here's how these concepts correlate:
Over the years, many popular and widespread shared configurations have been developed. However, with every breaking change in ESLint, the community projects need to migrate. Therefore, it's important to check the compatibility with ESLint v9 support and flat config support in particular before using a third-party npm package: To use a shared ruleset, you can also leverage the CLI option --config. The following installs a third-party configuration, eslint-config-canonical:
$ npm init @eslint/config@latest -- --config eslint-config-canonical
Let's look at an example to install a shared plugin. To add Vue support, we have to install eslint-plugin-vue:
$ npm i -D eslint-plugin-vue
The following eslint.config integrates the recommended ESLint rules in addition to the recommended configuration of eslint-plugin-vue. Further, it overrides one of the available Vue rules:
// eslint.config.js import pluginJs from "@eslint/js"; import pluginVue from "eslint-plugin-vue"; export default [ { rules: pluginJs.configs.recommended.rules }, ...pluginVue.configs["flat/recommended"], { // override default rule settings rules: { // change severity to warning "vue/no-reserved-props": "warn" }, }, ];
If you inspect pluginVue.configs["flat/recommended"], you find out that internally the plugin uses a dedicated processor and parser:
//... module.exports = [ // ... { name: 'vue:base:setup-for-vue', files: ['*.vue', '**/*.vue'], plugins: { // ... }, languageOptions: { parser: require('vue-eslint-parser'), sourceType: 'module', globals: globals.browser }, rules: { 'vue/comment-directive': 'error', 'vue/jsx-uses-vars': 'error' }, processor: 'vue/vue' } ]
The ESLint config inspect also shows this fact for the entry vue:base:setup-for-vue:
This section explains a couple of use cases of using ESLint in projects.
Besides using the CLI option --fix, you can execute auto-fix from your code editor when you save a file. Then, all fixable rule violations in the file are automatically solved. This has multiple advantages:
This workflow is also very handy if you integrate ESLint with code formatting.
As already mentioned, the ESLint team has deprecated all formatting rules and recommends only using logical rules. You can still use these stylistic rules, although their usage is discouraged.
A better approach is to choose one of the two options to enable ESLint supporting code formatting.
The common approach is to integrate ESLint with dedicated code formatting tools, such as Prettier or dprint. For Prettier, the preferred way is to run Prettier as an ESLint rule with eslint-plugin-prettier.
The following steps are required to set this up. First, install all dependencies:
$ npm i -D eslint@latest @eslint/js globals eslint-plugin-prettier eslint-config-prettier prettier
Then, use the plugins in eslint.config.mjs:
import pluginJs from "@eslint/js"; import pluginPrettierRecommended from "eslint-plugin-prettier/recommended"; export default [ { name: "ESLint recommended config", ...pluginJs.configs.recommended, }, { name: "ESLint plugin for Prettier formatting", ...pluginPrettierRecommended, }, ];
Next, the IDE integration is required. For VS Code, make sure to install the extensions for ESLint and Prettier.
Lastly, we need to configure the format on save for VS Code in .vscode/settings.json:
{ "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.fixAll.eslint": "explicit" } }
The npm package eslint-config-prettier eventually disables any ESLint rules dealing with code formatting to avoid conflicts with Prettier. You can see this with the handy ESLint Config Inspector: The second option is to use ESLint Stylistic. The primary focus of this project is on all stylistic rules including code formatting. This project was initiated as ESLint and typescript-eslint teams decided to deprecate formatting/stylistic-related rules.
The following steps are required to use ESLint Stylistic:
$ npm i -D @stylistic/eslint-plugin-js
Then you need to include the plugin into your eslint.config:
import pluginJs from "@eslint/js"; import stylisticJs from "@stylistic/eslint-plugin-js"; export default [ { name: "logical rules only", ...pluginJs.configs.recommended, }, { plugins: { "@stylistic/js": stylisticJs, } } ];
Finally, you need the same .vscode/settings.json as explained above if you want to use the plugin with auto-fixing stylistic issues on save:
Using ESLint with Git commit hooks (with the help of tools like Husky and lint-staged) and within CI/CD pipelines serves complementary purposes to ensure code quality and consistency throughout the development lifecycle.
Integrating ESLint with Git commit hooks ensures that code is automatically linted before it is committed. This helps with catching and fixing linting errors early in the development process, preventing problematic code from entering the codebase. Tools like lint-staged help you to run ESLint only on changed files to improve DX.
As another safety net, you should also integrate ESLint into your CI/CD pipeline. In this section, we discussed how to integrate ESLint into your IDE, which means that ESLint runs on the current file you're working on. In your CI/CD environment, you should lint all your files for every pipeline run.
ESLint has been around for over 10 years. Over the years, there have been many competitors who have gradually lost favor with users. This section provides an overview of the field and how ESLint compares to its competitors.
作為最早的 JavaScript linting 工具之一,JSLint 被譽為 JavaScript linting 的鼻祖。它自以為是,不支援自訂規則配置,設定了嚴格的編碼標準,不允許偏差。
JSHint 作為 JSLint 的一個分支出現,旨在為開發人員提供更多配置選項。儘管如此,它仍然不如 ESLint 靈活,特別是在規則定制和插件支援方面,限制了它對不同項目需求的適應性。上次發布可以追溯到 2022 年。
最初是 TypeScript 的首選 linting 工具,TSLint 自 2019 年起已被棄用,取而代之的是 ESLint,ESLint 擴展了其功能,透過插件包含 TypeScript。 TSLint 的棄用標誌著 TypeScript 社群向更統一的 linting 解決方案的重大轉變。
ESLint 在第一代同行中脫穎而出,自 2013 年以來已成為 JavaScript 生態系統中的主導工具。它的成功歸功於其廣泛的可配置性、插件生態系統以及對自訂規則的支持,使其適用於廣泛的環境編碼風格和專案要求。
JavaScript linting 工具的格局已經從第一代更加固執和僵化的工具發展到第二代注重效能且更易於存取的工具。
作為這些新短絨的一部分,Biome 在 2020 年大流行之後出現,但名稱為 Rome。 Biome 於 2023 年中期創建,作為 Rome 的一個分支,這是一個得到不斷發展的社區支持的活躍計畫。 Biome 專注於更廣泛的範圍,除了 linting 之外還包括程式碼格式化。關於 linting,語言支援尚未與 ESLint 相提並論。
quick-lint-js 於 2021 年推出,承諾增強開發人員工作流程,將自己定位為 ESLint 的補充工具。它專為“即時速度”而設計,可在程式碼編輯器中提供快速回饋,無延遲。該工具的另一個目標是零配置,因此它是固執己見的。該工具針對特定目標群體。
RSLint 是一個相對較新的參與者,專注於提供零配置的 linting 工具。它正處於早期開發階段,尚未準備好投入生產。最新版本是 2022 年發布的,因此尚不清楚開發是否仍在進行中。
從 2023 年 2 月開始,oxlint 並不是要取代 ESLint,而是要對其進行補充,特別是在 ESLint 的性能可能成為瓶頸的場景中。支援JavaScript、TypeScript和一些框架;例如,Vue.js。
作為 Deno 運行時的 linter, deno lint 原生支援 JavaScript 和 TypeScript。它與 Deno 的整合使其與其他產品區分開來,專門針對利用該運行時的專案。
雖然 ESLint 仍然是 JavaScript linting 的基石,但新工具的出現反映了社群對效率、效能和特定專案需求適應性的持續探索。第二代的影響仍在不斷顯現,許多工具找到了自己的定位或成為 ESLint 綜合功能的寶貴補充。
下表將 ESLint 與其目前競爭對手進行了比較:
ESLint | JSHint | Biome | quick-lint-js | RSLint | oxlint | deno lint | |
---|---|---|---|---|---|---|---|
Available since | 2013 | 2010 | 2023 (Rome 2010) | 2020 | 2020 | 2022 | 2020 |
Underlying technology | JS (rewrite w/ Rust announced) | JS | Rust (Rome: JS) | C++ | Rust | Rust | Rust / TS |
License | MIT | MIT | MIT | free GPL v3 | MIT | MIT | MIT |
Average releases per year | 30 | 5 | 60 | 20 | 2 | 45 (parent project oxc) | 20 |
npm downloads per week | 38M | 565K | 531K | 650 | - | 63K | - |
GitHub stars | 24.6K | 9K | 12.7K | 1.5K | 2.7K | 9.8K | 1.5K |
Mentioned in any year of State of JS | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
TS support | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
JSX support | ✅ | ✅ w/ [JSXHint](https://github.com/CondeNast/JSXHint) | ✅ | ✅ | ❌ | ✅ | ❌ |
Vue.js support | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ |
CSS support | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ |
Supports code formatting | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ |
VS Code integration | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ |
IntelliJ integration | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ |
Latest version | 9.7.0 | 2.13.6 | 1.8.3 | 3.2.0 | 0.3.2 | 0.6.0 | 0.60.1 |
Configurability | extensive | minimal | advanced | zero | zero | advanced (ESLint v8 config scheme) | minimal |
Third-party plugin support | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
Third-party rules | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
我的印像是,ESLint 團隊認真對待了一些批評,並在版本 9 中解決了它們——例如,更明智的預設選項來抵消配置的需要。最近發布的部落格文章證實了我的觀點,因為 ESLint 的核心仍然需要進行重大的架構更改,這可能會進一步提高效能。
像 Biome 這樣的計畫無疑是 ESLint 團隊決定進行這些複雜改編的原因之一。競爭對手給出的一些關於為什麼他們自己的解決方案比 ESLint 更好的理由已經過時了。
您應該堅持使用 ESLint 作為您選擇的 linting 工具嗎?我建議在大多數用例中使用 ESLint,尤其是在商業環境中。 ESLint 被廣泛採用,並且由於其廣泛的分佈,開發人員很可能知道如何使用它。
即使是雄心勃勃的競爭對手專案也無法涵蓋開發人員所需的所有用例。例如,截至 2024 年 7 月,Biome 尚未完全支援 CSS 或 Vue.js。社群中還有其他聲音主張使用 ESLint 和 Prettier 作為 linting 和格式化的最佳組合。
對於 ESLint 的複雜性和效能一直存在批評。然而,開發團隊的具體專案經驗、非常好的文件和工具都是支援 ESLint 的很好的論點。
除非您想涵蓋非常具體的用例,例如 IDE 中的即時回饋(這可以透過 fast-lint-js 實現),否則 ESLint 以其豐富的功能集涵蓋了幾乎所有相關的開發用例。
偵錯程式碼總是一項乏味的任務。但你越了解自己的錯誤,就越容易糾正它們。
LogRocket 讓您以新的、獨特的方式理解這些錯誤。我們的前端監控解決方案追蹤使用者與 JavaScript 前端的互動,使您能夠準確查看使用者的操作導致了錯誤。
LogRocket 記錄控制台日誌、頁面載入時間、堆疊追蹤、帶有標頭 + 正文的慢速網路請求/回應、瀏覽器元資料和自訂日誌。了解 JavaScript 程式碼的影響從未如此簡單!
免費試用。
以上是ESLint 採用指南:概述、範例和替代方案的詳細內容。更多資訊請關注PHP中文網其他相關文章!