https://github.com/sverweij/dependency-cruiser

 pnpm i
 
 pnpm add -D dependency-cruiser
 
 npx depcruise --init
# インタラクティブに質問に答えてそのプロジェクトにあった設定ファイルを作成する
 npx depcruise . --include-only "^app" --output-type dot | dot -T svg > dependency-graph.svg      
zsh: command not found: dot
node:events:497
      throw er; // Unhandled 'error' event
      ^
 
Error: write EPIPE
    at afterWriteDispatched (node:internal/stream_base_commons:160:15)
    at writeGeneric (node:internal/stream_base_commons:151:3)
    at Socket._writeGeneric (node:net:952:11)
    at Socket._write (node:net:964:8)
    at writeOrBuffer (node:internal/streams/writable:564:12)
    at _write (node:internal/streams/writable:493:10)
    at Writable.write (node:internal/streams/writable:502:10)
    at writeToStdOut (file:///Users/XXX/project/github.com/vercel/nextjs-postgres-nextauth-tailwindcss-template/node_modules/.pnpm/[email protected]/node_modules/dependency-cruiser/src/cli/utl/io.mjs:36:20)
    at write (file:///Users/XXX/project/github.com/vercel/nextjs-postgres-nextauth-tailwindcss-template/node_modules/.pnpm/[email protected]/node_modules/dependency-cruiser/src/cli/utl/io.mjs:49:5)
    at runCruise (file:///Users/XXX/project/github.com/vercel/nextjs-postgres-nextauth-tailwindcss-template/node_modules/.pnpm/[email protected]/node_modules/dependency-cruiser/src/cli/index.mjs:132:3)
Emitted 'error' event on Socket instance at:
    at emitErrorNT (node:internal/streams/destroy:169:8)
    at emitErrorCloseNT (node:internal/streams/destroy:128:3)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
  errno: -32,
  code: 'EPIPE',
  syscall: 'write'
}
 
Node.js v21.7.1
  • なるほど dot に npx つけたらいけるかな
 npx depcruise . --include-only "^app" --output-type dot | npx dot -T svg > dependency-graph.svg
node:internal/modules/cjs/loader:1145
  throw err;
  ^
 
Error: Cannot find module 'commander'
Require stack:
- /Users/XXX/.npm/_npx/d524878513a669be/node_modules/dot/bin/dot-packer
    at Module._resolveFilename (node:internal/modules/cjs/loader:1142:15)
    at Module._load (node:internal/modules/cjs/loader:983:27)
    at Module.require (node:internal/modules/cjs/loader:1230:19)
    at require (node:internal/modules/helpers:179:18)
    at Object.<anonymous> (/Users/XXX/.npm/_npx/d524878513a669be/node_modules/dot/bin/dot-packer:4:15)
    at Module._compile (node:internal/modules/cjs/loader:1368:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1426:10)
    at Module.load (node:internal/modules/cjs/loader:1205:32)
    at Module._load (node:internal/modules/cjs/loader:1021:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:142:12) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/Users/XXX/.npm/_npx/d524878513a669be/node_modules/dot/bin/dot-packer'
  ]
}
 
Node.js v21.7.1
  • ふぁえ?
  • 一回 pnpm-lock.yaml消してみる
    • だめだった。
  • 調べたら graphviz を入れる必要があるっぽい
 brew install graphviz
 
 npx depcruise . --include-only "^app" --output-type dot | dot -T svg > dependency-graph.svg
  • お、いけた!
  • app ディレクトリに絞るとあまり情報がないのでプロジェクトのルートを含めてすべての依存関係を png で出力してみる
 npx depcruise . --output-type dot | dot -T png -o dependency-graph.png

本題

// dependency-cruiser.js
 
module.exports = {
	//...
	options: {
		//...
		collapse: "^((app|components|lib)/[^/]+)", // ルート直下のディレクトリをグループ化
	},	
}
 npx depcruise . --include-only "^app|^components|^lib" --output-type dot | dot -T png -o dependency-graph.png

  • 2階層下まで出力したい場合は
    • collapse: "^((app|components|lib)/[^/]+/[^/]+)",