Мёртвые экспорты
devtoolz dead-exports находит именованные экспорты, которые нигде в проекте не импортируются.
devtoolz dead-exports [paths...] [options]Команда только читает код — ничего не удаляет и не переписывает, у неё нет --fix. Задача не в том, чтобы автоматически подчистить, а в том, чтобы показать, на что вообще стоит посмотреть, прежде чем удалять руками.
Реальный вывод — маленький пакет с точкой входа src/index.ts, ре-экспортирующей formatPrice и applyDiscount, где roundToNearestNickel объявлена рядом с formatPrice, но нигде не ре-экспортирована и не используется:
🧰 devtoolz — chores, automated
Scanned 4 files.
1 dead export found:
src/pricing.ts:5 roundToNearestNickelformatPrice не попадает в отчёт — она ре-экспортируется из публичной точки входа и, отдельно, реально используется в src/cart.ts. applyDiscount тоже не попадает — она ре-экспортируется из точки входа, и по умолчанию этого достаточно, чтобы не считаться мёртвой, даже если внутри репозитория её никто не вызывает.
Что считается «мёртвым»
Экспорт не попадает в отчёт, если выполняется любое из:
- на него есть хотя бы один
importгде-то в просканированных файлах; - он реально достижим из публичной точки входа пакета — не только объявлен прямо в файле точки входа, но и ре-экспортирован через цепочку
export { x } from './y'/export * from './y'любой глубины. Именованный ре-экспорт освобождает от подозрений только сам ре-экспортированный символ, а не весь файл, из которого он идёт — если рядом в том же файле объявлена вторая, не ре-экспортированная функция, она по-прежнему может оказаться мёртвой; - модуль импортируется целиком (
import * as ns from './x') — тогда используемым считается вообще всё, что экспортирует./x; - это тип, импортированный через
import type— тоже считается использованием.
Публичные точки входа определяются автоматически по package.json's exports/main/module/bin, плюс src/index.ts/src/index.tsx, если он существует, даже без package.json. --entry добавляет дополнительные файлы к этому списку.
Workspace
pnpm/npm/yarn-воркспейс определяется автоматически (по pnpm-workspace.yaml либо workspaces в корневом package.json) — импорт вашего экспорта из соседнего пакета того же воркспейса не читается как мёртвый, даже если внутри текущего пакета на него никто не ссылается. --no-workspace отключает это и проверяет только сам просканированный код.
Опции
--strict
Проверять и публичные точки входа тоже, не только внутренние файлы — то, что ре-экспортируется наружу, но реально никем не используется даже вне репозитория (внешние потребители неизвестны инструменту, так что это осознанный компромисс, а не гарантия). На том же примере выше:
🧰 devtoolz
Scanned 4 files.
2 dead exports found:
src/discounts.ts:1 applyDiscount
src/pricing.ts:5 roundToNearestNickel--entry <path>
Дополнительный файл публичной точки входа (можно указать несколько раз) — экспорты из него исключаются из отчёта так же, как и у автоопределённых точек входа.
--no-workspace
Не автоопределять pnpm/npm/yarn-воркспейс для резолва между пакетами.
--cwd <path>
Корень, от которого резолвятся относительные пути.
--ext <list>
Через запятую, какие расширения обрабатывать. По умолчанию: .ts,.tsx,.js,.jsx,.cjs,.mjs.
--ignore <glob>
Дополнительный паттерн игнорирования (повторяемый) поверх встроенных дефолтов. Файлы конфигурации сборки (*.config.ts/*.config.js/*.config.mjs/*.config.cjs) исключены из обхода по умолчанию всегда — их default-экспорт обычно подхватывается соответствующим инструментом по имени файла, а не через import где-то в репозитории, и иначе читался бы как мёртвый практически в каждом проекте.
--no-respect-gitignore
Не учитывать .gitignore проекта.
Пример:
devtoolz dead-exports src # обычная проверка
devtoolz dead-exports src --strict # и публичные точки входа тоже
devtoolz dead-exports src --entry src/testing.ts # ещё одна точка входа, например testing-утилиты
devtoolz dead-exports . --no-workspace # игнорировать соседние пакеты воркспейса