ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

ESLint no-restricted-modules 规则详解:用 require 精确限制 Node.js 模块使用

ESLint no-restricted-modules 规则详解:用 require 精确限制 Node.js 模块使用 ESLint no-restricted-modules 规则详解用 require 精确限制 Node.js 模块使用【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint本规则用于在 ESLint 中禁用通过require加载的指定 Node.js 模块从而从规则层面约束开发者可用的 API 范围例如禁止文件系统访问、锁定内部依赖边界。读完本文你将掌握no-restricted-modules的字符串、paths、gitignore 风格patterns三种配置形式、自定义错误消息写法以及该规则在 lib/rules/no-restricted-modules.js 中的底层匹配实现与测试验证方式。为什么要限制模块的使用在 Node.js/CommonJS 中模块是一个组织在单个 JavaScript 文件中的简单或复杂功能可以贯穿整个应用复用。require关键字用于将模块导入应用它支持动态加载——模块名可以不预先固定也可以在真正需要时才按条件加载。然而能用不等于该用。在某些场景下团队希望限制开发者的可选能力例如在浏览器端渲染或沙箱化环境中禁止通过fs模块直接读写文件系统在基础设施代码中统一收敛child_process、net、tls等高风险模块的入口强制团队内部的模块使用规范例如统一从门面facade模块引入而不是直接 require 底层实现逐步淘汰某些废弃或存在安全风险的第三方依赖。no-restricted-modules正是为这类治理需求而设计的它允许你显式声明本应用不允许使用的模块名单凡是require命中的模块都会在静态检查阶段被报告出来从源头阻止不合规的模块引入。规则详情该规则允许你指定不希望出现在应用中的模块。规则类型为suggestion建议类默认不启用recommended: false需要显式在配置中开启。检测对象是require(...)调用表达式规则只对第一参数为字符串字面量或静态模板字面量的情况生效——如果传入的是变量、表达式或动态拼接的模板字符串规则无法静态判断因而不会报告这一点在下面的源码实现剖析中会详细展开。配置选项详解规则接受一个或多个字符串作为选项被限制的模块名列表。形式一字符串列表最简单的配置直接列出所有被禁止的模块名no-restricted-modules: [error, foo-module, bar-module]形式二paths 对象也可以传入一个包含paths列表的对象效果与字符串列表等价no-restricted-modules: [error, { paths: [foo-module, bar-module] }]形式三paths gitignore 风格 patterns当需要限制某个模块的子路径如lodash/pick或某一整族模块时可配合patterns使用。patterns采用 gitignore 风格的匹配语法支持*通配与!否定no-restricted-modules: [error, { paths: [foo-module, bar-module], patterns: [foo-module/private/*, bar-module/*,!baz-module/good] }]上面的配置含义是foo-module与bar-module本身被精确禁止同时foo-module/private/下的所有子模块、bar-module/下的所有子模块也都被禁止但baz-module/good这个模块被!排除在限制之外。值得注意的是patterns只作用于 require 的模块名且基于ignore库实现见下文源码分析因此!取反规则具备 gitignore 语义的优先级逻辑。自定义错误消息可以为任意要限制的路径指定自定义消息有两种等价的写法。直接使用namemessage对象no-restricted-modules: [error, { name: foo-module, message: Please use bar-module instead. } ]或将对象嵌套进paths数组no-restricted-modules: [error,{ paths:[{ name: foo-module, message: Please use bar-module instead. }] }]自定义消息会追加在默认错误消息之后最终输出形如foo-module module is restricted from being used. Please use bar-module instead.。需要特别留意自定义错误消息只能用于精确路径不能用于patterns——因为一个模块可能同时匹配多个 pattern无法确定该使用哪一条自定义消息。一次性限制所有 Node.js 核心模块如果需要全面收紧可把 Node.js 核心模块全部列入限制名单以下为当前仓库文档提供的完整核心模块列表{ no-restricted-modules: [error, assert,buffer,child_process,cluster,crypto,dgram,dns,domain,events,freelist,fs,http,https,module,net,os,path,punycode,querystring,readline,repl,smalloc,stream,string_decoder,sys,timers,tls,tracing,tty,url,util,vm,zlib ] }这样配置后任何require(fs)、require(http)等核心模块调用都会被 ESLint 报告为错误。正确与错误代码示例以下示例均假设受限模块为fs、cluster、lodash。不正确的代码—— 精确限制字符串命中的模块/*eslint no-restricted-modules: [error, fs, cluster]*/ const fs require(fs); const cluster require(cluster);不正确的代码——paths方式限制/*eslint no-restricted-modules: [error, {paths: [cluster] }]*/ const cluster require(cluster);不正确的代码—— pattern 命中子模块/*eslint no-restricted-modules: [error, { patterns: [lodash/*] }]*/ const pick require(lodash/pick);正确的代码—— 未命中任何限制/*eslint no-restricted-modules: [error, fs, cluster]*/ const crypto require(crypto);正确的代码—— pattern 命中但被!排除且模块本身不在受限名单内/*eslint no-restricted-modules: [error, { paths: [fs, cluster], patterns: [lodash/*, !lodash/pick] }]*/ const crypto require(crypto); const pick require(lodash/pick);第二例中lodash/*本会命中lodash/pick但!lodash/pick将其从受限范围中排除因此require(lodash/pick)合法。这是 gitignore 风格取反在实际配置中最典型的用法。源码实现剖析要真正用好这个规则理解其底层实现会很有帮助。规则源码位于 lib/rules/no-restricted-modules.js核心逻辑可以拆解为四层。1. 配置 schema 校验meta.schema定义了两种合法配置形态anyOf一个字符串或{ name, message }对象组成的数组arrayOfStringsOrObjects其中对象要求name必填、message长度至少为 1且不允许出现额外属性additionalProperties: false、数组内不允许重复uniqueItems: true一个包含paths字符串或对象数组与patterns字符串数组属性的对象数组且不允许额外属性。因此非法配置例如缺少name、message为空字符串、混入未知字段会在配置加载阶段直接被 schema 校验拦截。2. 选项解析与无需检查短路create(context)中首先判断第一个选项是否为含paths或patterns键的对象据此分别提取restrictedPaths与restrictedPatterns。随后将所有受限路径折叠成restrictedPathMessages映射字符串值为null对象则映射到其自定义message。如果受限路径与 patterns 均为空规则直接返回空监听器——即没有限制就完全不做任何检查避免无谓的遍历开销。3. require 调用的识别与参数提取规则在CallExpression节点上监听先通过isRequireCall确认callee是名为require的标识符。随后用getFirstArgumentString提取第一个参数若参数是字符串字面量Literal且typeof node.value string取其value并trim()去除首尾空白因此require(os )在受限名单含os时仍会被命中若参数是静态模板字面量借助ast-utils.js中的isStaticTemplateLiteral取第一个 quasi 的 cooked 值并trim()即require(\fs) 同样会被检测变量、数字、含插值的模板字符串如require(\foo${bar})则返回null规则放行。这一实现解释了文档中的边界行为require(2)、require(foo)、require(\foo${bar}) 都不会触发报告因为模块名无法静态确定。4. 精确路径与 pattern 的双通道匹配拿到模块名后规则执行两路判断精确路径通道若名字存在于restrictedPathMessages调用reportPath报告并根据是否存在自定义消息选择customMessage或defaultMessage消息模板pattern 通道若restrictedPatterns非空用ignore库ignore({ allowRelativePaths: true }).add(restrictedPatterns)执行ig.ignores(name)匹配命中则报告patternMessage模板。这里的两处细节值得注意。其一规则使用了ignore库而非手写正则因此patterns完整继承 gitignore 语法*、**、!取反等且allowRelativePaths: true使得../foo这类相对路径也能参与 pattern 匹配。其二精确路径与 pattern 各自独立报告因此同一次require理论上可能产生两条错误一条来自paths、一条来自patterns而自定义消息只可能在精确路径通道中出现。消息模板规则定义了三条消息模板见meta.messagesdefaultMessage{{name}} module is restricted from being used.customMessage{{name}} module is restricted from being used. {{customMessage}}patternMessage{{name}} module is restricted from being used by a pattern.三者分别对应精确命中、带自定义消息的精确命中、以及 pattern 命中读者可根据报错文案中的后缀区分命中来源。测试验证行为边界一览规则行为由 tests/lib/rules/no-restricted-modules.js 中的 313 行用例完整覆盖从测试可以直观确认前文提到的所有边界合法代码require(fs)配options: [crypto]、require(2)、require(foo)、require(fs )未受限时带空格也合法、require(\fs)配crypto、require(foo/bar)配paths: [foo, bar]、pattern 未命中patterns: [foo/c*]不匹配foo/bar、!排除生效patterns: [foo/*, !foo/bar]、相对/绝对路径未被错误命中如require(../foo)配options: [../notFoo]非法代码require(fs)配[fs]报defaultMessagerequire(os )配[fs, crypto , stream, os]命中os再次印证参数会被 trimrequire(foo/bar)配paths: [foo/bar]报精确命中配patterns: [foo/*]报patternMessagerequire(\crypt\o)配[crypto]在静态模板字面量转义后仍能命中自定义消息对象直接对象或嵌套于paths均报customMessagerequire(../foo)、require(/foo)在paths与patterns 两种形态下分别命中对应消息模板。这些用例同时验证了错误定位line/column/endColumn指向require(...)调用本身方便开发者定位问题代码行。注意事项与版本演进仅覆盖 CommonJS本规则只检测require调用不处理 ES Module 的import语句。若项目使用 ESM需要借助其他机制如no-restricted-syntax配合 import 选择器实现类似限制。规则状态从源码meta.deprecated可以看到该规则自 ESLint v7.0.0 起被标记为弃用deprecatedSince: 7.0.0计划可用至 v11.0.0原因是Node.js 相关规则已移出 ESLint 核心availableUntil: 11.0.0其职责由社区维护的eslint-plugin-n插件中的no-restricted-require规则继续承担。新项目建议直接评估该插件仍在维护旧版 ESLint 的项目可继续使用本规则其行为在弃用窗口内保持不变。自定义消息的边界自定义消息仅适用于精确paths/字符串形式不适用于patterns若模式匹配出错只能依赖patternMessage的通用文案。小结no-restricted-modules通过精确路径 gitignore 风格 patterns 自定义消息三层能力为 Node.js/CommonJS 项目提供了一套声明式的模块使用白/黑名单治理方案。其配置简洁、匹配行为可预测特别适合文件系统访问管控、高危模块收敛与内部依赖边界治理等场景。配合 tests/lib/rules/no-restricted-modules.js 中的用例你可以快速验证任意组合配置的实际效果。【免费下载链接】eslintFind and fix problems in your JavaScript code.项目地址: https://gitcode.com/GitHub_Trending/es/eslint创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表