Background

Dead islands

Files that import each other but are never used by the real app.

Your dead code check says every file is used. It may be wrong.

I ran Graphify on a large React codebase. It builds a graph of files and imports, and you can ask an LLM questions about it.

I asked for files that nothing imports. It found them. But it also found something I didn’t ask for: dead islands.

A dead island

A dead island is a group of files that import each other, while nothing outside the group imports them. They are never used by the real app.

The smallest one is two files: a component and its test. The test imports the component, so the component looks used. Tools like Knip treat tests and stories as entry points, so they don’t report it.

useElementSize.ts is 52 lines. The only file that imports it is useElementSize.test.ts, 252 lines.

Smallest island

Test

useElementSize.test.ts

  • imports useElementSize.ts

Code

useElementSize.ts

  • useElementSize.test.ts imports useElementSize.ts

One example

6 files in 3 folders. A container, the button it renders, two test files and two test mocks. 467 lines, and only 168 of them are product code. Nothing in the app had used it for about a year.

Dead island

Test

Invoices/

InvoiceMenu.export.test.tsx

  • imports InvoiceMenu.tsx

Test

Invoices/

InvoiceMenu.test.tsx

  • imports InvoiceMenu.tsx
  • imports csvFile.mock.ts
  • imports zipFile.mock.ts

Code

Invoices/

InvoiceMenu.tsx

  • imports MenuItem.tsx

Code

shared/

MenuItem.tsx

Test mock

mocks/

csvFile.mock.ts

Test mock

mocks/

zipFile.mock.ts

  • Code
  • Tests and mocks

6 files, 467 lines, unused for about a year.

Imports 28 files from the rest of the app

0 imports back

  • InvoiceMenu.export.test.tsx imports InvoiceMenu.tsx
  • InvoiceMenu.test.tsx imports InvoiceMenu.tsx
  • InvoiceMenu.test.tsx imports csvFile.mock.ts
  • InvoiceMenu.test.tsx imports zipFile.mock.ts
  • InvoiceMenu.tsx imports MenuItem.tsx

InvoiceMenu.test.tsx and InvoiceMenu.export.test.tsx import InvoiceMenu.tsx, which renders MenuItem.tsx. The tests also import two mocks: csvFile.mock.ts and zipFile.mock.ts.

The island imports 28 files from the app. The app imports none back.

Why it matters

Software hygiene. Dead files are not free.

Every refactor, codemod, search and AI agent run reads them, and often changes them. You keep maintaining code nobody uses. Fewer files means less to read, for people and for agents.

Results

119

files

~5,700

lines

Dead code, in one repository.

Try it on your codebase

After building the import graph, ask:

  1. List dead files and dead islands.
  2. What insights do you have about the dead islands?
  3. Sort dead files by last change, oldest first. The oldest are most likely leftovers.
  4. Find the pull request that made this island dead. Gather the clues and share hypotheses about why.
  5. Which tests and mocks only cover code that nothing else imports?

Found with a file-import graph (Graphify). The idea is general, not tied to one tool.

Do you look for dead islands in your codebase?