wheatandcatの開発ブログ

React Nativeで開発しているペペロミア & memoirの技術系記事を投稿してます

ts-unused-exportsを使用して不要なexportを検知する

exportしているが使用していない場合は、削除したいなーと思ったので実装してみた

Pull Request

github.com

実装

検知には ts-unused-exports を使用

github.com

以下のコマンドで追加

$ yarn add -D ts-unused-exports

以下のコマンドで実行できます

$ yarn ts-unused-exports ./tsconfig.json ./src/App.tsx

1 module with unused exports
/github.com/wheatandcat/memoir/src/App.tsx: Props
error Command failed with exit code 1.

上記のようにプロジェクト内で参照されていないexportを検知できます。

これを使用してCIで参照されていないexportがある場合にエラーになるように実装しました。

まず、スクリプトを作成

scripts/ts-unused-exports/index.js

const analyzeTsConfig = require('ts-unused-exports').default;
const config = require('./config.json');
const rootPath = require('path').resolve();

const result = analyzeTsConfig('./tsconfig.json');

var red = '\u001b[31m';
var green = '\u001b[32m';
var white = '\u001b[37m';
var yellow = '\u001b[33m';

const keys = Object.keys(result);
const ignoreFiles = config.ignoreFiles;
const baseUrl = config.baseUrl;

let items = [];

for (let i = 0; i < keys.length; i++) {
  const key = keys[i];

  if (!key.startsWith(`${rootPath}/${baseUrl}`)) {
    continue;
  }

  const ignore = ignoreFiles.find((v) => {
    const path = key.replace(`${rootPath}/`, '');
    const regexp = new RegExp(v + '(.*?)', 'g');

    return regexp.test(path);
  });

  if (ignore) {
    continue;
  }

  const item = result[key];
  const exportName = item.map((v) => v.exportName).join(', ');

  items.push({
    path: key,
    text: white + key.replace(`${rootPath}/`, '') + ': ' + yellow + exportName,
  });
}

if (items.length === 0) {
  console.log(green + '0 modules with unused exports');
} else {
  console.log(red + `${items.length} modules with unused exports`);

  for (let i = 0; i < items.length; i++) {
    const item = items[i];

    console.log(item.text);
  }

  process.exit(1);
}

configファイルは、以下に切り出し

scripts/ts-unused-exports/config.json

{
  "baseUrl": "src",
  "ignoreFiles": ["__mockData__", "hooks/tmp/*", "storyBookUtils/*"]
}

package.jsonのscriptsに追加

package.json

{
  "scripts": {
    "unused-exports": "node ./scripts/ts-unused-exports"

最後にGitHub Actionsを追加

.github/workflows/unused-exports.yml

name: unused-exports
on: [push]

jobs:
  unused-exports:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Cache node_modules
        uses: actions/cache@preview
        with:
          path: ~/.cache/yarn
          key: ${{ runner.os }}-memoir-${{ hashFiles(format('{0}{1}', github.workspace, '/yarn.lock')) }}
          restore-keys:
            ${{ runner.os }}-memoir-
      - name: Install node_modules
        if: steps.cache.outputs.cache-hit != 'true'
        run: yarn install
      - name: codegen
        run: yarn codegen
      - name: unused-exports
        run: yarn unused-exports

これで実装完了です。 Pushしてエラーだと以下みたいな感じになります。

◆ Pull Request スクリーンショット 2021-07-17 11 36 36

◆ GitHub Actionsの表示 スクリーンショット 2021-07-17 11 36 53