FEATURED · 精选文章

使用 ESLint Node.js API 构建自定义集成:从入门实战到完整 API 参考

发布时间 / 2026/9/10 22:19:46
来源 / 创域科博编辑部
栏目 / 资讯中心
使用 ESLint Node.js API 构建自定义集成:从入门实战到完整 API 参考 使用 ESLint Node.js API 构建自定义集成从入门实战到完整 API 参考【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint本文以 ESLint 官方“集成指南”为骨架系统讲解如何通过 Node.js API 将 ESLint 的检查与自动修复能力嵌入编辑器、代码评审、学习平台或自研 CLI 等工具并给出可运行的完整示例。读完本文你将掌握ESLint类的实例化与全部核心方法、Linter/SourceCode/RuleTester等程序化接口的适用场景以及如何借助仓库内真实源码与测试用例验证集成行为。什么是“ESLint 集成”为什么需要 Node.js APIESLint 除了命令行工具之外还暴露了一套 Node.js API供希望“把 ESLint 的功能集成进其他应用”的开发者使用。这套 API 的目的是让插件作者和工具作者不必经过命令行接口就能直接调用 ESLint 的核心能力。官方 集成指南 明确说明使用 Node.js API 集成 ESLint 的前提是熟悉 JavaScriptESLint 本身由 JavaScript 编写并具备一定的 Node.js 基础ESLint 运行在 Node.js 上。什么场景下值得自己动手写一个集成根据 Node.js API 入门教程 的归纳典型场景包括代码编辑器与 IDE在输入时提供实时代码质量反馈并高亮潜在问题。多数编辑器已有现成插件但当现有插件无法满足特定需求时就需要定制集成自定义 linter 工具构建组合多个 linter、或增加特定功能的工具时把 ESLint 集成进来以提供 JavaScript 检查能力代码评审工具集成 ESLint 可自动识别代码库中的潜在问题减少人工评审负担学习平台在教学或训练环境中提供实时反馈帮助学习者改进编码习惯、掌握最佳实践开发者工具集成在打包器、测试框架等工具中直接集成 ESLint或作为插件接入。环境准备与项目初始化跟随教程实操前请确认环境满足以下条件Node.js^20.19.0、^22.13.0或24npm用于安装依赖与初始化项目文本编辑器任意熟悉的编辑器即可。官方教程建议把eslint安装为普通依赖dependencies而非开发依赖devDependencies因为你的集成工具在运行时需要调用它。仓库中配套的示例项目 docs/_examples/integration-tutorial-code/package.json 正是如此声明的示例锁定eslint ^10.0.0{ name: integration-tutorial-code, private: true, version: 1.0.0, scripts: { test: node example-eslint-integration.test.js }, dependencies: { eslint: ^10.0.0 } }初始化步骤官方教程使用npm_tabs宏同时给出 npm / yarn / pnpm 三种包管理器的命令本文以 npm 为例mkdir eslint-integration cd eslint-integration npm init -y # 生成 package.json npm install eslint # 作为运行时依赖安装 touch example-eslint-integration.js入门实战用 ESLint 类完成“检查 修复 输出”这是 Node.js API 入门教程 的核心内容整个集成只有四个函数依次完成“建实例 → 检查并修复 → 输出结果 → 整合导出”。Step 1导入并配置 ESLint 实例从eslint包导入ESLint类CommonJS 环境用requireESM 环境可等价写作import { ESLint } from eslint并通过构造函数选项定制行为const { ESLint } require(eslint); // Create an instance of ESLint with the configuration passed to the function function createESLintInstance(overrideConfig) { return new ESLint({ overrideConfigFile: true, overrideConfig, fix: true, }); }这里的关键选项含义overrideConfigFile: true禁止 ESLint 自动在文件系统中搜索配置文件如eslint.config.js完全交由overrideConfig控制适合把配置内嵌进工具自身overrideConfig以对象形式提供配置它会在任何既有配置之后追加生效fix: true启用自动修复模式lintFiles/lintText会在结果中携带output修复文本。Step 2检查文件并落盘自动修复ESLint#lintFiles()接受一个字符串或字符串数组作为目标路径支持普通文件路径、目录路径与 glob 模式ESLint.outputFixes()是静态方法接收lintFiles的结果并把修复后的代码写回源文件// Lint the specified files and return the results async function lintAndFix(eslint, filePaths) { const results await eslint.lintFiles(filePaths); // Apply automatic fixes and output fixed code await ESLint.outputFixes(results); return results; }注意lintFiles本身不会修改目标文件只有显式调用outputFixes才会把修复写入磁盘。若某个结果对应的源文件已不存在outputFixes对该文件静默跳过。Step 3输出检查结果结果输出方式应服务于你的集成场景例如渲染到用户界面。示例中直接打印到控制台并通过errorCount与warningCount汇总问题数量// Log results to console if there are any problems function outputLintingResults(results) { // Identify the number of problems found const problems results.reduce( (acc, result) acc result.errorCount result.warningCount, 0, ); if (problems 0) { console.log(Linting errors found!); console.log(results); } else { console.log(No linting errors found.); } return results; }Step 4整合为可复用模块把以上函数组装进一个入口函数lintFiles配置可以内联传入也可改为从配置文件加载或使用默认配置// Put previous functions all together async function lintFiles(filePaths) { // The ESLint configuration. Alternatively, you could load the configuration // from an eslint.config.js file or just use the default config. const overrideConfig { languageOptions: { ecmaVersion: 2018, sourceType: commonjs, }, rules: { no-console: error, no-unused-vars: warn, }, }; const eslint createESLintInstance(overrideConfig); const results await lintAndFix(eslint, filePaths); return outputLintingResults(results); } // Export integration module.exports { lintFiles };完整可运行代码见 docs/_examples/integration-tutorial-code/example-eslint-integration.js。用仓库配套测试验证集成行为教程示例还自带一个测试文件 docs/_examples/integration-tutorial-code/example-eslint-integration.test.js它直接require上述集成模块对样例文件 docs/_examples/integration-tutorial-code/sample-data/test-file.js故意包含未使用变量y、result、subtract以及多处console.log执行lintFiles并断言lintResults[0].messages.length为 6问题总数触发的规则集合大小为 2集合中包含no-console规则。这份测试既是集成模块的验收用例也直观演示了LintResult.messages中ruleId字段的用法。运行方式为npm test对应node example-eslint-integration.test.js。深入 Node.js APIESLint 类完整参考教程只是冰山一角。官方 Node.js API 参考 对ESLint类做了完整定义它是最适合在 Node.js 应用中使用的首要类但依赖 Node.js 的fs模块与文件系统不能在浏览器中使用若要在浏览器端检查代码应改用Linter类。构造函数new ESLint(options)new ESLint(options)创建实例options可整体省略省略时全部采用默认值。从 lib/eslint/eslint.js 的源码结构看选项被分组处理并贯穿实例的整个生命周期。官方文档把选项划分为六组文件枚举File Enumeration选项类型默认值说明cwdstringprocess.cwd()工作目录必须是绝对路径errorOnUnmatchedPatternbooleantrue为false时lintFiles找不到目标文件也不抛错globInputPathsbooleantrue为false时lintFiles不解释 glob 模式ignorebooleantrue为false时lintFiles不遵循配置中的ignorePatternsignorePatternsstring[] \| nullnull额外忽略的文件模式相对cwd解析passOnNoPatternsbooleanfalse为true时缺失模式会让本次检查短路且不报告失败warnIgnoredbooleantrue文件列表包含被忽略文件时给出警告检查行为Linting选项类型默认值说明allowInlineConfigbooleantrue为false时抑制源码中的指令注释如eslint-disable并覆盖配置里的noInlineConfigbaseConfigConfig \| Config[] \| nullnull被本实例所有配置扩展的基底配置可定义配置文件中未设置的默认项overrideConfigConfig \| Config[] \| nullnull在既有配置之后追加的配置教程即用此传入内联规则overrideConfigFilenull \| true \| stringnullnull时自动搜索配置文件true时禁止搜索字符串时使用该路径的配置文件pluginsRecordstring, Plugin \| nullnull插件实现表键为插件 ID值为实现ruleFilter({ruleId, severity}) boolean() true过滤需要执行的规则statsbooleanfalse为true时在结果中附加性能统计见 Stats 类型自动修复Autofix选项类型默认值说明fixboolean \| (message) booleanfalsetrue时进入自动修复模式传入谓词函数则仅修复其返回true的消息fixTypes(directive\|problem\|suggestion\|layout)[] \| nullnull限定参与自动修复的规则类型缓存Cache-related选项类型默认值说明cachebooleanfalsetrue时lintFiles缓存结果并在文件未变更时复用。注意升级插件后 ESLint 不会自动清缓存需手动删除缓存文件lintText即使传了filePath也不使用缓存cacheLocationstring.eslintcache缓存文件写入位置cacheStrategystringmetadata变更检测策略metadata或content抑制Suppressions选项类型默认值说明applySuppressionsbooleanfalsetrue时自动把抑制文件中的抑制项应用到lintFiles/lintText的结果lintText须同时提供filePath才生效suppressionsLocationstringeslint-suppressions.json抑制文件路径可绝对路径或相对cwd其他选项Other Options选项类型默认值说明concurrencynumber \| auto \| offoff默认在调用线程内串行检查设为整数时最多使用该数量的 worker 线程并行检查auto自动选择。开启后其余选项必须可结构化克隆cloneableflagsstring[][]为本实例启用的特性开关实例方法lintFiles 与 lintTexteslint.lintFiles(patterns)检查匹配 glob 模式的文件并返回结果参数patternsstring | string[]目标文件可含文件路径、目录路径、glob 模式返回值PromiseLintResult[]。eslint.lintText(code, options)检查内存中的源码文本。默认使用cwd构造函数选项对应目录下生效的配置若要使用其他配置可传options.filePathESLint 会为lintFiles对该路径加载的同一配置。注意若filePath对应文件被配置忽略方法返回空数组若同时设置了warnIgnored则返回一个包含“文件被忽略”警告的LintResult返回类型同样是LintResult[]即便实际只有一个结果以保持与lintFiles的接口一致未传filePath时result.filePath为字符串text。官方示例检查文本并格式化输出const { ESLint } require(eslint); const testCode const name eslint; if(true) { console.log(constant condition warning) }; ; (async function main() { // 1. Create an instance const eslint new ESLint({ overrideConfigFile: true, overrideConfig: { languageOptions: { ecmaVersion: 2018, sourceType: commonjs }, }, }); // 2. Lint text. const results await eslint.lintText(testCode); // 3. Format the results. const formatter await eslint.loadFormatter(stylish); const resultText formatter.format(results); // 4. Output it. console.log(resultText); })().catch(error { process.exitCode 1; console.error(error); });其他实例方法eslint.getRulesMetaForResults(results)返回对象键为结果中触发检查问题的规则 ID值为该规则的元信息如可用eslint.calculateConfigForFile(filePath)计算某文件最终生效的配置常用于调试禁止传目录路径eslint.findConfigFile(filePath?)查找本实例会使用的配置文件绝对路径无配置文件如overrideConfigFile: true时返回undefinedeslint.isPathIgnored(filePath)判断某文件是否被配置忽略忽略返回trueeslint.loadFormatter(nameOrPath?)加载格式化器将LintResult转为可读文本。取值允许省略加载内置stylish、内置格式化器名称、第三方格式化器名称如foo→eslint-formatter-foo、foo→foo/eslint-formatter、foo/bar→foo/eslint-formatter-bar、或包含路径分隔符的格式化器文件路径如./开头。返回LoadedFormattereslint.hasFlag(flagName)判断某个特性开关是否开启。静态成员ESLint.versionESLint 版本字符串如7.0.0ESLint.defaultConfigESLint 内部使用的默认配置供需要按相同默认值计算配置的工具使用注意默认配置会随版本变化不应依赖具体键值ESLint.fromOptionsModule(optionsURL)从模块加载选项创建实例。由于concurrency要求其余选项可克隆以传给 worker 线程而“从模块加载”时 worker 拿到的是模块 URL 而非选项对象因此该限制对fromOptionsModule不适用。示例// eslint-options.js import config from ./my-eslint-config.js; export default { concurrency: auto, overrideConfig: config, overrideConfigFile: true, stats: true, };// main.js const optionsURL new URL(./eslint-options.js, import.meta.url); const eslint await ESLint.fromOptionsModule(optionsURL);ESLint.outputFixes(results)把自动修复后的代码写回对应文件文件不存在则跳过ESLint.getErrorResults(results)复制结果并剔除警告仅保留错误。上述方法在 lib/eslint/eslint.js 中均有对应实现例如static async outputFixes(results)第 804 行、static getErrorResults(results)第 835 行、async lintFiles(patterns)第 961 行、async lintText(code, options)第 1104 行、async loadFormatter(name)第 1233 行、calculateConfigForFile第 1330 行、findConfigFile第 1356 行、isPathIgnored第 1376 行。结果与消息的数据类型LintResult每次lintFiles/lintText返回包含filePath绝对路径未知时为textmessagesLintMessage[]suppressedMessagesSuppressedLintMessage[]fixableErrorCount/fixableWarningCount可自动修复的错误/警告数errorCount含可修复错误与致命错误、fatalErrorCount、warningCountoutput修复后的源码文本无任何可修复消息时为undefinedsource原始源码文本当存在消息或存在output时为undefinedstatsstats选项开启时的性能统计usedDeprecatedRules使用的已弃用规则信息info对应规则的新版deprecated元数据见 规则弃用。LintMessagemessages数组中的单个问题包含ruleId触发规则名ESLint 核心而非规则生成时为nullseverity1警告 /2错误、fatal解析错误等与规则无关的致命错误为truemessage、messageId规则未使用 messageId 时为undefinedline/column1 起始的起止行列、endLine/endColumn非区间时为undefinedfixEditInfo不可修复时为undefinedsuggestions建议列表供编辑器等 API 使用者按需选用。SuppressedLintMessage除与LintMessage相同的字段外还有suppressions: { kind, justification }[]。EditInfo表示一次文本编辑等价于sourceCodeText.slice(0, range[0]) text sourceCodeText.slice(range[1])range[number, number]0 起始的待移除区间两值相等即纯插入textstring待添加文本空字符串即纯删除。LoadedFormatter提供format(results, resultsMeta?)方法把LintResult[]转为文本resultsMeta主要用于 CLI可含color、maxWarningsExceeded普通调用通常无需传入第二个参数。loadESLint()跨版本集成的兼容入口需要同时支持不同 ESLint 版本的集成工具可使用loadESLint()获取正确的ESLint实现const { loadESLint } require(eslint); const DefaultESLint await loadESLint(); // CLI 基于 process.cwd() 使用的默认版本 const FlatESLint await loadESLint({ useFlatConfig: true }); // 显式 flat config const LegacyESLint await loadESLint({ useFlatConfig: false }); // 旧版不可用时回退 flat config随后用返回的构造器实例化const eslint new DefaultESLint();。若不确定返回的构造器使用哪套配置系统可读取其configType属性flat或eslintrc。官方建议若无需同时支持新旧两套配置系统直接使用ESLint构造器即可。从 lib/api.js 可见当前仓库中loadESLint()直接返回 flat config 的ESLint实现。SourceCode复用已解析的代码SourceCode表示 ESLint 检查的已解析源码既在内部使用也允许外部把“已解析好的代码”交给 ESLint。通过文本字符串与 ESTree 格式的 AST需含位置、区间、注释与 token 信息构造const SourceCode require(eslint).SourceCode; const code new SourceCode(var foo bar;, ast);缺少必需信息时构造会抛错构造器会自动剥离 Unicode BOM此时 AST 也必须基于剥离后的文本解析const code new SourceCode(\uFEFFvar foo bar;, ast); assert(code.hasBOM true); assert(code.text var foo bar;);静态方法SourceCode.splitLines(code)将源码按行切分为数组const codeLines SourceCode.splitLines(var a 1;\nvar b 2;); // [var a 1;, var b 2;]Linter不依赖文件系统的轻量级核心Linter对象执行真正的 JS 代码求值不做任何文件系统操作也不处理配置文件——它只负责解析和报告代码。因此除非在浏览器环境否则应优先使用ESLint类浏览器场景可参考官方 demo 的做法。构造时可传cwd选项供规则通过context.cwd读取未传时在 Node.js 下归一化为process.cwd()浏览器下为undefined详见 自定义规则中的 Context 对象。Linter#verify()verify(code, config, options?)是Linter最重要的方法接受三个参数code待检查源码字符串或SourceCode实例config配置对象或配置对象数组如需从文件系统读取配置请改用ESLint#lintFiles()/ESLint#lintText()options可选filename关联文件名、preprocess/postprocess插件中的 Processors、filterCodeBlock决定采纳哪些代码块省略时默认只采纳*.js代码块提供后覆盖默认行为、disableFixestrue时不生成fix/suggestions、allowInlineConfigfalse时禁用内联注释修改规则、reportUnusedDisableDirectivestrue时对未使用的eslint-disable指令报告、ruleFilter规则谓词。若第三个参数是字符串则视为filename。const Linter require(eslint).Linter; const linter new Linter(); const messages linter.verify( var foo;, { rules: { semi: 2 } }, { filename: foo.js }, );verify()返回消息数组每条消息除LintMessage所述字段外还可能含endLine/endColumn/fix/suggestions无则省略。可通过linter.getSuppressedMessages()获取上次运行的被抑制消息无上次运行时返回空数组const messages linter.verify( var foo bar; // eslint-disable-line -- Need to suppress, { rules: { semi: [error, never] } }, { filename: foo.js }, ); const suppressedMessages linter.getSuppressedMessages(); console.log(suppressedMessages[0].suppressions); // [{ kind: directive, justification: Need to suppress }]也可通过linter.getSourceCode()取回上次verify()使用的SourceCode文本与 AST。Linter#verifyAndFix()verifyAndFix(code, config)类似verify但额外执行自动修复逻辑等价于命令行--fix返回对象含fixed是否已修复、output修复后文本无修复时与原输入相同、messages剩余未被自动修复的消息const messages linter.verifyAndFix(var foo, { rules: { semi: 2 }, }); // { fixed: true, output: var foo;, messages: [] }其他 Linter 成员linter.version与Linter.version实例/类上的语义化版本号linter.getTimes()单文件解析、修复、检查耗时对应 Stats 的times属性linter.getFixPassCount()自动修复轮数对应fixPasses属性linter.hasFlag(flagName)判断特性开关如new Linter({ flags: [x_feature] })后linter.hasFlag(x_feature)为true。RuleTester为规则编写可靠测试eslint.RuleTester是编写规则测试的实用工具ESLint 内置规则自身就使用它插件作者同样可以。基础用法use strict; const rule require(../../../lib/rules/my-rule), RuleTester require(eslint).RuleTester; const ruleTester new RuleTester(); ruleTester.run(my-rule, rule, { valid: [ { code: var foo true, options: [{ allowFoo: true }] }, ], invalid: [ { code: var invalidVariable true, errors: [{ message: Unexpected invalid variable. }], }, ], // optional assertionOptions: { requireMessage: true, requireLocation: false, requireData: true, }, });构造器接受可选对象作为用例默认值如new RuleTester({ languageOptions: { ecmaVersion: 2015 } })不传时使用 ESLint 默认值languageOptions: { ecmaVersion: latest, sourceType: module }静态方法RuleTester.setDefaultConfig(config)为后续实例设置默认配置RuleTester.getDefaultConfig()读取RuleTester.resetDefaultConfig()重置RuleTester#run(name, rule, tests)的tests对象含valid/invalid数组与可选的assertionOptions。测试用例valid/invalid 通用的属性name可选便于定位、code必填、options传给规则的选项数组不含严重级别、before/after用例执行前/后钩子、filename对依赖文件名的规则有用、only排他运行调试。invalid 用例额外支持errors必填数字表示期望的错误数量对象数组则逐个断言。错误对象可断言message或messageId二选一、data与messageId配合校验消息文本占位符、line/column/endLine/endColumn、suggestions也可以直接用字符串代替对象等价于断言messageoutput规则修复代码时必填单轮自动修复后的输出为null或省略则断言不产生自动修复。断言选项assertionOptionsrequireMessagetrue/message/messageId强制校验消息断言方式、requireLocationtrue时每个错误对象必须含位置属性、requireDatatrue/error/suggestion强制带占位符的messageId必须给出data。测试修复通过 invalid 用例的output属性断言修复结果如code: var foo;→output: var bar;。官方特别提醒ESLint 会尽力应用所有修复但不保证全部应用因此应“每个修复类型单独一个测试用例”当两个修复冲突作用于同一段代码时RuleTester只应用第一个。测试建议suggestions在 errors 对象的suggestions键上定义数字表示数量数组则逐项断言desc或messageId二选一、data、output应用该建议后的代码ruleTester.run(my-rule-for-no-foo, rule, { valid: [], invalid: [ { code: var foo;, errors: [ { suggestions: [ { desc: Rename identifier foo to bar, output: var bar; }, ], }, ], }, ], });定制 describe / itRuleTester依次按以下规则寻找测试运行函数① 若RuleTester.describe/RuleTester.it以及可选的RuleTester.itOnly被设置为函数则直接使用② 否则使用全局globalThis.describe/globalThis.it兼容 Mocha 等框架it.only处理only: true用例③ 否则按顺序同步执行所有用例失败即抛错——也就是说不借助任何测试框架直接用 Node.js 执行调用RuleTester.run的测试文件即可。若要在整个项目强制统一的断言选项官方给出两种用户侧模式子类化RuleTester并覆写run()或封装一个合并assertionOptions的辅助函数两者都把调用方传入的选项后置合并以保持优先。从源码看这套 API 的真实构成当前仓库 lib/api.js 是整个程序化入口的统一出口它把四个核心构件一并导出module.exports { Linter, // 来自 lib/linter轻量级核心 loadESLint, // 兼容多版本的构造器加载函数 ESLint, // 来自 lib/eslint/eslint.js主类 RuleTester, // 规则测试工具 SourceCode, // 已解析源码表示 };其中ESLint的实现lib/eslint/eslint.js依赖 Node.js 的fs/worker_threads等模块并借助 lib/eslint/eslint-helpers.js 完成processOptions、findFiles、verifyText、lintFile、createLintResultCache等底层工作concurrency选项对应的多线程检查由 lib/eslint/worker.js 承载缓存则由 lib/cli-engine/lint-result-cache.js 实现。仓库测试目录 tests/lib/eslint 中还有针对ESLint类行为的系统化测试可作为理解各选项边界行为的补充证据。结语通过本文你已经掌握了三条层次的集成能力第一用ESLint类完成“检查 自动修复 输出”的完整实战闭环并可用仓库配套测试验证第二熟悉ESLint构造函数六大分组选项与全部实例/静态方法可针对编辑器、代码评审、学习平台等场景定制行为第三理解Linter、SourceCode、RuleTester、loadESLint等程序化接口的分工与取舍。这套知识可以直接迁移到真实工具开发中——例如为编辑器插件提供实时反馈或为团队自研 CLI 提供可编程的 lint 能力。若需深入配置对象细节可继续阅读 配置指南若要编写自定义规则供集成调用可参考 自定义规则文档 与 插件文档。【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻