ARTICLE DETAIL

资讯详情

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

dependency-cruiser 实战 FAQ 全解析:从疑难排错到功能拓展

dependency-cruiser 实战 FAQ 全解析:从疑难排错到功能拓展 开发工具静态分析代码质量【免费下载链接】dependency-cruiserValidate and visualize dependencies. Your rules. JavaScript, TypeScript, CoffeeScript. ES6, CommonJS, AMD.项目地址https://gitcode.com/gh_mirrors/de/dependency-cruiser点击查看免费下载导读本文以 dependency-cruiser 官方 FAQ 文档为骨架系统梳理这款依赖分析工具在使用中最常遇到的疑难问题为什么 TypeScript / Vue / Svelte 的依赖消失不见、巨型依赖图如何瘦身、性能如何优化、monorepo 与 Yarn PnP 如何适配以及如何通过插件机制扩展输出格式。读完本文你将掌握--info、--ts-pre-compilation-deps、collapsePattern、reporterOptions.dot.filters等关键开关的底层原理与实操姿势并理解 dependency-cruiser自带解析器、外借编译器的架构设计。文中所有结论均有当前仓库源码与文档佐证可直接对照 doc/faq.md、doc/cli.md 与 doc/options-reference.md 进一步深挖。一、故障排查Troubleshooting1.1 TypeScript / CoffeeScript / LiveScript / Vue 依赖不显示怎么办标准答案把编译器安装到与 dependency-cruiser 相同的位置反之亦然。dependency-cruiser 自身不内置这些语言的转译器而是直接复用运行环境中已有的编译器。你可以用以下命令确认编译器是否对 dependency-cruiser 可见dependency-cruiser --info如果转译器确实缺失按你的安装方式对症下药本地开发依赖安装推荐把所需转译器装进项目本地npm i -D typescript之类即可全局安装将所需转译器一并全局安装npx 方式通过-p参数把编译器临时带进来。例如想查看某个 TypeScript 文件的所有进出依赖npx -p typescript4.3.5 -p dependency-cruiserlatest dependency-cruiser src -T text --focus src/main/index.ts源码佐证从 src/extract/transpile/index.mjs 可以看到EXTENSION2WRAPPER映射表.ts、.tsx、.d.ts、.cts、.mts等扩展名分别绑定到typeScriptWrap含 esm/tsx 变体.vue绑定到vueWrap.svelte绑定到svelteWrap.coffee、.litcoffee、.csx、.cjsx绑定到 CoffeeScript 包装器。而 transpile 默认导出 的逻辑是先通过getWrapper找到对应扩展的包装器再调用wrapper.isAvailable()探测转译器是否可用不可用时直接原样返回源码——这正是依赖丢失现象的实现层根源。若配置了babelConfig则 JS/TS 系列扩展会优先走babelWrap见 getWrapper。1.2 期望中的某些 TypeScript 依赖不出现预编译依赖答案在配置文件的options段加入tsPreCompilationDeps: true或在命令行加--ts-pre-compilation-deps。默认情况下 dependency-cruiser只统计编译后仍然存在的依赖。以下两类依赖编译后不存在默认被忽略尚未使用的 import死代码仅导入类型type-only import的依赖。若你想让这些依赖进入统计二选一在.dependency-cruiser.json/.dependency-cruiser.js的options中设置tsPreCompilationDeps: true命令行传--ts-pre-compilation-deps详细文档见 doc/cli.md#--ts-pre-compilation-deps-TypeScript-only。源码佐证在 src/extract/tsc/extract.mjs 中shouldUse的判定条件是(tsPreCompilationDeps || parser tsc) isAvailable() isTypeScriptCompatible(pFileName)也就是说开启该选项后直接走 TypeScript AST 分析而非先转译成 JavaScript。这一行为在 src/main/options/defaults.mjs 中默认为false。1.3 三斜线指令/// triple slash directives仍然不显示答案升级到 9.0.0 及以上版本。自 9.0.0 起三斜线指令无需额外配置即可被识别。历史背景在旧版本中需要把tsdtriple slash directive模块系统加入配置的moduleSystems数组或在命令行传--module-systems cjs,ejs,tsd。源码佐证如今 tsc 提取器通过pAST.referencedFiles、pAST.typeReferenceDirectives、pAST.amdDependencies直接提取三斜线引用并标记moduleSystem: tsd与dependencyTypes: [triple-slash-directive, ...]见 src/extract/tsc/extract-typescript-deps.mjs。因此只需保证moduleSystems默认数组[es6, cjs, tsd, amd]见 src/main/options/defaults.mjs中保留tsd即可无需手动配置。1.4 只检测到第一层依赖TypeScript怎么回事答案最可能的原因是 dependency-cruiser 找不到 TypeScript 编译器安装位置不一致解法见 1.1。背景剖析上面的依赖图出自类似命令dependency-cruiser src/index.ts -T dot | dot -T svg deps.svg。由于src/index.ts是显式参数dependency-cruiser 一定会扫描它但当 TypeScript 编译器不可用时它会回退到 JavaScript 解析器。TypeScript 语法与 JavaScript 高度相似所以直接依赖仍能全部找出可一旦进入解析阶段例如解析configuration它只会检查自己能处理的扩展名.js、.json等不含.ts于是这些模块被标记为unresolvable——这正是图中红线红字的原因。当 TypeScript 编译器就位后同样的命令能找出多得多的依赖如上图所示。1.5 依赖图过于庞大、连线难以追踪怎么办答案通常你并不需要一次性看到全部模块。面对 5000 个模块、20000 条依赖的 monorepo 图信息量反而趋近于零。dependency-cruiser 提供了多种降噪策略策略一按包拆分——为 monorepo 中每个packages单独出图但这并不能解决所有可读性问题。策略二高层依赖图archi reporter。把依赖聚合到更高抽象层只关心主组件之间的连接dependency-cruiser --config .dependency-cruiser.js --output-type archi -- src | dot -T svg high-level-dependency-graph.svg默认情况下archi聚合到packagesmonorepo、src、lib等常见路径的下一层。可用collapsePattern调整聚合粒度以适应自己的目录结构。策略三文件夹级依赖图ddot reporter。鸟瞰视角按文件夹聚合依赖dependency-cruiser --config .dependency-cruiser.js --output-type ddot -- src | dot -T svg folder-level-dependency-graph.svg策略四过滤。--include-only、exclude、--do-not-follow、--focus以及极端情况下的--max-depth及它们在配置文件中的对应项都能有效削减 dot 输出中的模块与依赖数量。例如只聚焦src内部、排除测试与 mock 文件dependency-cruiser src --include-only ^src/ --exclude mocks\\.ts$|\\.spec\\.ts$ --output-type dot | dot -T svg dependency-graph.svg策略五加分项report 级过滤。当你出图所需的细节度低于校验所需的细节度时可以给图单独套一层过滤校验仍用完整数据。两种做法为出图单独建一份配置与校验配置分离在总配置的 reporter 级添加过滤。详见 report level filtering其中还介绍了用depcruise-fmt免费获得性能提升。示例只在 dot 图中展示src树下的模块{ options: { // 全局过滤遇到 node_modules 记录之但不再深入 doNotFollow: node_modules, reporterOptions: { dot: { // 仅针对 dot图形reporter 的过滤只显示 src 树中的模块 filters: { includeOnly: { path: ^src } } } } } }可用的 reporter 级过滤器包括includeOnly、exclude与focus。源码佐证dot 系 reporter 的入口在 src/report/dot/index.mjsreport函数接收{ theme, collapsePattern, filters, showMetrics }当filters存在时先对modules做applyFilters再渲染pryCollapsePatternFromResults会优先取 reporter options 中的collapsePattern否则使用getCollapseFallbackPattern给出的默认值^(node_modules|packages|src|lib|app|test|spec)/[^/]见 src/report/dot/index.mjs。archicdot与ddot均经由 src/report/dot/dot-custom.mjs 复用同一套实现。策略六让 dot 渲染正交边orthogonal edges而非样条曲线。部分场景下直角连线比曲线更易读。做法之一是给 dot 传-Gsplinesorthodependency-cruiser src --config .dependency-cruiser-graph.js --output-type dot | dot -Gsplinesortho -T svg dependency-graph-with-orthogonal-edges.svg或者固化到配置文件的 dot reporter options 中module.exports { // ... 你的规则与/或它继承的配置 ... options: { // ... 你的其他选项 ... reporterOptions: { dot: { theme: { graph: { splines: ortho, }, }, }, }, }, };这不是 dot 输出的默认值因为 GraphViz 并不总能渲染正交边图效果因人而异YMMV。1.6 TypeScript 动态导入显示为 ✖答案你用的版本低于 4.17.0。自 4.17.0 起TypeScript 与 JavaScript 的动态导入均受支持✖应成为历史。历史背景4.17.0 之前dependency-cruiser 默认以ES2015作为编译目标推断 TS 源码形态这与动态导入不兼容。如果你已有能让编译器接受动态导入的tsconfig.json可通过--ts-config参数喂给 dependency-cruiser只要导入的是静态字符串而非变量/表达式动态导入即可被解析。1.7 纯 ESM 项目报错 Must use import to load ES Module答案把.dependency-cruiser.js重命名为.dependency-cruiser.cjs。自 10.1.0 起--init生成器会自动为你完成这一重命名。1.8 全局安装、npx 还是本地开发依赖答案推荐以本地开发依赖安装。这样 dependency-cruiser 会自动使用与你项目相同版本的编译器工具链结果最可靠。1.9 无法解析外部包的某个类型type怎么办答案在.dependency-cruiser.js的options.enhancedResolveOptions中加入mainFields告诉解析器额外查找外部包 package.json 中的types字段{ // rules: [], options: { enhancedResolveOptions: { mainFields: [main, types, typings] } // other options ... } }背景剖析dependency-cruiser 使用enhanced-resolve的默认行为——按 Node.js 规范只查找 package.json 的main与exports字段外加index.js、.mjs、.cjs等文件。mainFields属性会 1:1 透传给enhanced-resolve使其同时检查其他字段。从 src/main/options/normalize.mjs 可以看到collapsePattern等 reporter 选项的归一化入口mainFields同样作为enhancedResolveOptions的一部分被透传。二、功能特性Features2.1 如何启用 TypeScript / CoffeeScript / LiveScript答案无需启用。只要环境中有对应编译器它们天然开箱即用out of the box。2.2 使用 jsx / tsx / csx / cjsxReact 生态怎么配答案jsx 及其 TS / CoffeeScript 变体同样开箱即用但 jsx 有一个小坑。小坑是什么在极少数情况下dependency-cruiser 可能发现某个 jsx 文件依赖了它实际上并不依赖的东西。背景剖析底层目前使用acornacorn-jsx曾经是官方 jsx 转译器至今仍被其他工具使用。jsx 的某些写法它并不支持好在多数情况下它会回退到acorn-loose宽松解析器仍能挑出正确的依赖。唯一的例外是当你在特定口味的 jsx 片段里使用了import、export或require字样时。以下 jsx 默认解析器会解析失败import React from react; export class ReplicateIssueComponent extends React.Component { renderSomethingElse () { return ( The word import here results is picked up as an import statement./ ); }; render () ( {this.renderSomethingElse()} Here import is confused with an import statement as well. / ); }原 issue 评论中提供了若干规避方案audunsol给出未来版本计划内置处理这些场景的能力无需 workaround。2.3 支持 Vue 吗答案支持。对.vue单文件组件dependency-cruiser 使用vue-template-compilerVue2或vue/compiler-sfcVue3若你用 Vue2 开发vue-template-compiler通常已在项目依赖中只需把 dependency-cruiser 装在相同位置vue/compiler-sfc自 Vue 3.2.13 起默认内置更早的 Vue3 可能需要手动添加。2.4 支持 Svelte 吗答案支持。对.svelte单文件组件使用svelte4.x 版本它通常已在你的 Svelte 项目依赖中。由于 Svelte 的工作机制所有.svelte文件都会依赖svelte/internal若噪音太大可在配置文件或命令行中配置忽略它。2.5 dependency-cruiser 会为这些语言安装转译器吗答案不会。对 LiveScript、TypeScript、CoffeeScript、Svelte 与 Vue SFC它直接使用你项目里已有的转译器全局安装则用全局的。相比把转译器打包为自身依赖这有几个好处npm idependency-cruiser 更快用不到的转译器不会落到磁盘上dependency-cruiser 会用你项目实际使用的转译器版本可能出于合理原因并非最新版。2.6 支持 webpack 配置alias、modules吗答案支持。通过 CLI 的--webpack-config或配置文件options段的webpackConfig见 rules-reference喂入 webpack 配置dependency-cruiser 在巡航依赖时会采纳其中的resolve部分包括你配置的alias。目前支持的 webpack 配置文件格式为合理子集仅限 Node.js 可解析的 JavaScript含 ESMwebpack 4 及以上兼容更早版本可能可用但不保证导出内容为对象字面量或函数webpack 4 风格最多两个参数或上述的数组取第一个元素其他格式TypeScript、yaml、LiveScript 等在存在把 Node 打补丁到能理解它的函数时也可用——如果你用这类格式写 webpack 配置这个函数大概率已就位。源码佐证webpack 配置的解析逻辑位于 src/config-utl/extract-webpack-resolve-config.mjs其中对非原生格式TypeScript、yaml 等会提示借助对 CommonJS 打补丁的模块来完成加载。2.7 能调优让 dependency-cruiser 跑得更快吗答案大概率可以。以--init生成的.dependency-cruiser.js默认配置为例它优先正确性而非速度。影响性能的因素大致按影响从大到小排序moduleSystems把模块系统收敛到你真正在用的如今大概率只剩es6最多加cjs会显著提速tsPreCompilationDeps置为true后TypeScript 源码直接分析 AST不再先转译成 JavaScript因此更快enhancedResolveOptions.extensions只保留你实际使用的扩展名如.ts会加快解析。默认初始化为当前环境所有解析器支持的扩展仅 tsc/swc 时约是.js, .cjs, .mjs, .ts, .d.ts, .jsx, .tsx。即便不能删除扩展名按出现频率从高到低排序也有帮助——enhanced-resolve会按此顺序查找文件命中即停doNotFollow旧版本初始化了一堆dependencyTypes更快且同样准确甚至兼容yarn PnP的做法是只设path通常是node_modulesparser: swc若你的代码库能被swc成功编译把解析器切到swc能提速但幅度未必像期望的那么大默认规则里的正则自带的某些规则包含对你的代码库不完全适用的正则比如你还留有.coffee文件吗清理后虽不显著但积少成多enhancedResolveOptions.cachedInputFileSystem.cacheDuration少数场景下调整缓存时长可换取性能以内存为代价见 options-reference。源码佐证默认moduleSystems为[es6, cjs, tsd, amd]、tsPreCompilationDeps为false、exoticRequireStrings为空数组等均见 src/main/options/defaults.mjs。2.8 检测动态导入dynamic imports吗答案检测TypeScript 与 JavaScript 都支持——但仅限静态字符串参数或不含占位符的模板表达式。这已覆盖大多数异步模块加载如 webpack 代码分割场景。2.9 处理变量或表达式形式的 require / import 吗答案不处理。require(someVariable)、import(someOtherVariable).then(...)、require(funkyBoolean ? lodash : underscore)这类写法无法静态确定依赖指向。dependency-cruiser 目前专注于把静态分析这一件事做好。2.10 支持 webpack inline loaders 吗答案支持自 9.17.0 起开箱即用无需额外配置。2.11 支持 require.js 插件语法!符号吗答案支持自 9.17.0 起开箱即用无需额外配置。2.12 兼容 monorepo 吗答案完全兼容。对每个被巡航的模块dependency-cruiser 会寻找最近的package.json来判断某个包是否被声明为依赖。2.13 兼容 Yarn PlugnPlay 吗答案兼容。自 9.21.3 起自动生效无需配置。历史沿革更早版本4.14.0 起需要在配置的externalModuleResolutionStrategy键中写入yarn-pnp--init会自动处理现已不再需要自 13.0.0 起不再支持 yarn 1.x 的 pnp——yarn 团队已多年仅对该版本做生命周期与安全维护并鼓励迁移到 yarn 3旧版 pnp 也阻碍了 dependency-cruiser 跟进 Node.js / JavaScript 生态。2.14 检测到循环依赖后如何看到具体环路答案升级到 5.2.0 及以上。从该版本起err、err-long、err-html与teamcityreporter 都会输出循环路径dot与ddot更早就支持了。2.15 用了window.require或 require 包装器如何让这类依赖被计入答案自 5.4.0 起可在配置中加入exoticRequireStrings键列出包装器或 require 的重定义exoticRequireStrings: [window.require, need, tryRequire];源码佐证exoticRequireStrings被 tsc、swc、acorn 三套提取器共同消费见 src/extract/tsc/extract.mjs、src/extract/swc/extract.mjs 与 src/extract/acorn/extract.mjs默认值为空数组src/main/options/defaults.mjs。2.16 用 jsdoc / tsdoc 注释声明依赖如何让 dependency-cruiser 识别答案自 16.7.0 起可在配置中加入//... detectJSDocImports: true; // implies parser: tsc // ...由于只有tsc解析器支持该特性需要安装typescriptdependency-cruiser 会自动使用它。详见 detectJSDocImports in the options reference。2.17.dependency-cruiser.js能获得代码补全吗答案能。在支持这些能力的编辑器中给module.exports加类型注释即可获得补全与建议/** type {import(dependency-cruiser).IConfiguration} */ export default { // ... your rules options };新版本--init生成器会自动为你加上这行注释。自 18.2.0 起dependency-cruiser 还识别用 TypeScript 编写的配置文件——前提是运行它的 Node.js 环境直接支持这些文件。--init生成的配置模板即内置了/** type {import(dependency-cruiser).IConfiguration} */注释与基础规则示例可参考 src/cli/init-config/config-template.mjs。2.18 支持比模块更细的粒度类、函数、变量吗答案不支持未来也大概率不会。dependency-cruiser 专注把模块间依赖这一件事做好类/函数/方法及其依赖的静态分析固然有趣但那会让它变成另一个工具且实现与维护成本高昂。三、扩展 dependency-cruiserExpanding3.1 如何新增一种输出格式答案两条路——作为插件或直接内置进 dependency-cruiser。方式一作为插件创建一个导出函数签名如下的模块(pCruiseResult: ICruiseResult): IReporterOutput;把该模块作为输出类型传入例如命令行dependency-cruiser src --output-type plugin:my-awesome-plugindependency-cruiser 需要能找到my-awesome-plugin本地模块通常要给出完整路径dependency-cruiser src --output-type plugin:$(pwd)/path/to/my-awesome-plugin执行插件前dependency-cruiser 会校验函数签名是否正确、能否处理最小输入。官方提供了基础示例 configs/plugins/stats-reporter-plugin.mjs。源码佐证插件校验逻辑在 src/report/plugins.mjs 的isValidPlugin用{ modules: [], summary: {...} }的最小 cruise result 调用插件函数检查返回对象同时具有output属性和数值型exitCode。加载流程见getExternalPluginReportersrc/report/plugins.mjs匹配^plugin:(?pluginName.)$后动态import目标模块并取default导出非法时抛出 Could not find reporter plugin ... (or it isnt valid)。stats-reporter-plugin.mjs的默认导出正是返回{ output: JSON.stringify(stats, null, 2), exitCode: 0 }的结构configs/plugins/stats-reporter-plugin.mjs可作最小参考实现。方式二直接内置对于应随 dependency-cruiser 发行的 reporter按以下步骤在src/report下新增一个导出默认函数的模块该函数接收 dependency-cruiser 输出对象schema 见 src/schema/cruise-result.schema.json返回包含outputCLI 要输出的内容与exitCode报告完成后 CLI 的退出码的对象在 src/report/index.mjs 的TYPE2MODULE映射表中新增键值与模块相对路径现有键包括anon、archi、dot、ddot、fdot、err、err-long、err-html、json、html、csv、mermaid、markdown、teamcity、text、metrics、baseline、d2、azure-devops、null等在doc/cli.md的--output-type一节补充描述新输出类型的段落在test/report添加单元测试证明新 reporter 的行为符合预期。源码佐证getReporter会优先处理plugin:前缀走getExternalPluginReporter否则从TYPE2MODULE查表动态导入未命中时回退到identityreportersrc/report/index.mjsgetAvailableReporters则直接返回映射表的所有键src/report/index.mjs。3.2 如何支持心仪的 alt-js 语言答案提出请求或提交 PR。dependency-cruiser 已支持 TypeScript、CoffeeScript 与 LiveScript若还有别的能转译到 JavaScript 的语言想要支持可以联系作者。添加 alt-js 语言的 PR 配方在package.json把该语言及其支持的版本范围加入supportedTranspilers对象把该语言的转译器加入devDependencies写测试证明新增功能可用时需要在src/extract/transpile新增yourLanguageWrap.js调用转译器把该语言转换成 JavaScript最好 ES6 或更高低版本也应可用参考 src/extract/transpile/typescript-wrap.mjs 的写法在 src/extract/transpile/index.mjs 的EXTENSION2WRAPPER映射表中为该语言的每个适用扩展名添加./yourLanguageWrap条目在test/extract/transpile为yourLanguageWrap添加单元测试。四、路线图与联系方式4.1 Road map官方路线图在项目主页的 Projects 看板中维护包含计划中的功能与改进方向。4.2 Contact遇到问题或建议欢迎创建 issue也欢迎提交 pull request——如果改动较复杂建议先创建 issue 或在 Mastodon 上联系作者大约每日查看一次。总结通读这份 FAQ 可以发现 dependency-cruiser 的设计哲学一以贯之自带解析器、外借编译器——它不捆绑转译器而是复用你项目环境中的 TypeScript、CoffeeScript、Vue、Svelte 工具链参见 src/extract/transpile/index.mjs 的isAvailable()探测机制从而既轻量又与你项目真实编译环境保持版本一致。图的可读性、性能、monorepo / Yarn PnP 适配、插件扩展等问题的答案最终都落在options与reporterOptions这两个配置核心上。上手时建议本地安装、--init生成配置、用--info排查编译器可见性再按本节 FAQ 逐步打磨出既准确又高效的依赖巡航流水线。赞分享开发工具静态分析代码质量【免费下载链接】dependency-cruiserValidate and visualize dependencies. Your rules. JavaScript, TypeScript, CoffeeScript. ES6, CommonJS, AMD.项目地址https://gitcode.com/gh_mirrors/de/dependency-cruiser点击查看免费下载相关推荐Starship FAQ 实战全解从安装配置到跨 Shell 集成与疑难排查Starship FAQ 实战全解从安装配置到跨 Shell 集成与疑难排查 Starship 是一个用 Rust 编写、跨 Shellbash、zsh、fCLI开发工具Flecs FAQ 实战指南ECS 核心概念、性能疑难与常见错误排查Flecs FAQ 实战指南ECS 核心概念、性能疑难与常见错误排查 本篇指南以 Flecs 官方 FAQ 为主体系统解答使用 FlecsC/C 的快游戏开发Starship FAQ 全解析跨 Shell 提示字元引擎的配置、除错与疑难排解实战指南Starship FAQ 全解析跨 Shell 提示字元引擎的配置、除错与疑难排解实战指南 本篇技术指南以 Starship 官方繁体中文 FAQ 文档 dCLI开发工具上一篇网盘直链下载助手使用教程8 大网盘免费解析真实下载链接告别干等一小时下一篇网盘下载慢怎么办3步装好网盘直链下载助手八大平台免费提速创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表