
eslint-plugin-unicorn 的 no-exports-in-scripts 规则禁止在脚本文件中使用 export【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn本篇文章围绕 eslint-plugin-unicorn 的no-exports-in-scripts规则展开讲解它如何识别以 shebang#!开头的可执行脚本、为何要禁止脚本中出现 ESM 导出语句以及它与普通模块、CommonJS 脚本之间的边界。读完本文你将掌握该规则的判定原理、完整适用场景、配置方式与测试用例细节能够直接在项目中启用并正确规避误报。规则概述脚本与模块的边界no-exports-in-scripts是一条风格建议类suggestion规则其核心主张是脚本文件应当被直接执行而不是被当作模块导入。在 Node.js 生态中一个以 shebang 开头的文件如#!/usr/bin/env node通常意味着它是一个 CLI 工具或可执行入口。如果在这样的文件里再出现export语句就会同时混入脚本边界与模块边界两种语义读者难以判断这个文件到底是用来直接运行的还是设计为供其他模块导入的。这正是规则文档docs/rules/no-exports-in-scripts.md所强调的核心动机。规则源码 rules/no-exports-in-scripts.js 中规则的meta.docs.description为Disallow exports in scripts.meta.type为suggestion且未提供任何可配置选项schema: []——这意味着该规则开箱即用、无需调参。判定原理只看第一行是否为 shebang该规则的实现非常精简核心判定逻辑只有一步检查文件的第一行是否以#!开头。const create context { const {sourceCode} context; if (!sourceCode.lines[0].startsWith(#!)) { return; } context.on([ExportNamedDeclaration, ExportDefaultDeclaration, ExportAllDeclaration], node ({ node, messageId: MESSAGE_ID, })); };对应源码位置rules/no-exports-in-scripts.js。关键点如下通过sourceCode.lines[0].startsWith(#!)判断文件是否为脚本。只有第一行恰好以#!开头才触发检查这是全部判定依据没有任何其他启发式条件。一旦确认是脚本规则会监听三种导出节点类型ExportNamedDeclarationexport const foo 1;、export {foo};、export {foo} from ./foo.js;、export type Foo string;TypeScript 中导出类型同样走此节点ExportDefaultDeclarationexport default foo;ExportAllDeclarationexport * from ./foo.js;、export * as foo from ./foo.js;。命中后报告统一的消息Do not use exports in scripts.消息 ID 为no-exports-in-scripts见 rules/no-exports-in-scripts.js。由于规则挂载的meta.languages为[js/js]它默认只作用于 JavaScript 文件TypeScript 场景需要通过languageOptions指定 TypeScript 解析器测试用例中即为如此处理见下文。示例失败与通过的代码规则文档给出了三组最直观的示例本文将其完整保留并补充说明。带 shebang 的脚本中出现导出 —— 失败#!/usr/bin/env node export const foo 1;第一行以#!开头文件被判定为脚本随后出现的export const foo 1;触发报告。带 shebang 的脚本、无导出 —— 通过#!/usr/bin/env node const foo 1; console.log(foo);脚本只包含普通声明与副作用调用符合脚本只执行、不导出的预期。普通模块中的导出 —— 通过export const foo 1;文件第一行不是#!规则直接返回不产生任何报告。边界情况哪些写法会被放行、哪些会被拦截测试文件 test/no-exports-in-scripts.js 通过 AVA 的test.snapshot()对大量边界场景做了验证快照结果保存在 test/snapshots/no-exports-in-scripts.js.md。这些用例恰好能帮你理解规则的精确边界避免在真实项目中产生意外误报。不会被拦截valid的场景无 shebang 的任何导出export const foo 1;、export default foo;、export * from ./foo.js;、export {};以及先声明后导出的const foo 1; export {foo};TypeScript 中无 shebang 的类型导出export type Foo string;、export interface Foo {}带 shebang 但完全不导出#!/usr/bin/env node下仅使用import与console.log带 shebang 但使用 CommonJS 导出#!/usr/bin/env node下的module.exports foo;—— 规则只针对 ESM 的export关键字CommonJS 的module.exports不在检查范围内这也与脚本可直接执行的定位一致shebang 位于注释中// #!/usr/bin/env node export const foo 1;第一行是注释而非真正的 shebang规则不触发shebang 只是字符串内容console.log(#!/usr/bin/env node); export const foo 1;第一行是普通代码#!出现在字符串字面量内部不影响判定。从源码角度看这些边界全部由sourceCode.lines[0].startsWith(#!)这一条判定自然覆盖只有物理第一行、真实存在的 shebang才会进入导出检查。会被拦截invalid的场景以下所有写法都会报告Do not use exports in scripts.#!/usr/bin/env nodeexport const foo 1;#!/usr/bin/env nodeexport default foo;#!/usr/bin/env nodeexport * from ./foo.js;#!/usr/bin/env nodeexport * as foo from ./foo.js;#!/usr/bin/env nodeconst foo 1; export {foo};#!/usr/bin/env nodeexport {foo} from ./foo.js;#!/usr/bin/env nodeexport {};即使空的导出对象也会被拦截#!/usr/bin/env node 多个导出语句每条导出分别报告一次快照invalid(8)显示一个文件内两处导出会产生 Error 1/2 与 Error 2/2TypeScript 场景#!/usr/bin/env nodeexport type Foo string;、#!/usr/bin/env nodeexport interface Foo {}需在测试中通过languageOptions: {parser: parsers.typescript}启用 TS 解析器见 test/no-exports-in-scripts.js快照文件 test/snapshots/no-exports-in-scripts.js.md 中可以看到每条错误报告的输出格式报告位置精确指向 export 语句本身消息为Do not use exports in scripts.。配置方式与推荐预设该规则已在 eslint-plugin-unicorn 的推荐配置中启用。在 readme.md 的规则列表中该规则对应行为规则描述recommendedunopinionatedno-exports-in-scriptsDisallow exports in scripts.✅☑️启用recommended✅的配置集合中该规则直接生效启用unopinionated☑️的配置集合中该规则同样开启注规则源码 rules/no-exports-in-scripts.js 中meta.docs.recommended标注为unopinionated两者并不冲突unopinionated是无争议、可放心启用的定位。如果希望手动启用可在 ESLint 配置中写入unicorn/no-exports-in-scripts: error,或按项目需求设为warn。由于meta.schema为空数组该规则不接受任何选项无需也无法传参。一个值得注意的细节是仓库自身的 dogfooding 配置 eslint.dogfooding.config.js 中把unicorn/no-exports-in-scripts: off显式关闭这说明对于允许脚本附带导出的项目完全可以通过该选项按需放行规则本身是可选加入的。实践建议CLI 入口文件凡是带 shebang 的 bin 脚本保持零导出的纯净形态若确有复用需求将可复用逻辑抽取到独立模块文件不带 shebang再从脚本中import使用。不要用注释绕过规则虽然// #!或字符串中的#!不会触发检查但这属于规则识别的边界而非推荐写法真正的 shebang 必须位于物理第一行才能被操作系统/Node.js 识别。CommonJS 脚本不受影响如果你用module.exports组织脚本规则不会干预它与 ESMexport关键字互不干扰。TypeScript 脚本同样适用在配置了 TS 解析器时export type、export interface这类仅类型导出同样会被拦截符合脚本不做任何对外导出的统一约定。小结no-exports-in-scripts用一条极简的判定首行是否为#!守护脚本与模块分离的代码组织原则脚本只管执行模块才负责导出。它的边界清晰、零配置、无参数配合 rules/no-exports-in-scripts.js 的实现与 test/no-exports-in-scripts.js 的完整用例可以放心在 recommended 配置中直接启用。【免费下载链接】eslint-plugin-unicornMore than 300 powerful ESLint rules项目地址: https://gitcode.com/GitHub_Trending/es/eslint-plugin-unicorn创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考