hacomono TECH BLOG

フィットネスクラブ・スクールなど施設・店舗のための会員管理・予約・決済システム「hacomono」 開発チームの技術ブログ

eslint, prettier の設定を複数のリポジトリで共通化してみた

hacomono フロントエンド テックリードのみゅーとん(@_mew_ton)です。

開発メンバーが増え、プロジェクトがどんどん増えてきました。

そろそろ eslint, prettier をそれぞれのプロジェクトでバラバラに管理するのに疲弊してきたので、 ここで一気に設定を揃えたいところ。

eslint, prettier のルールを一元管理する方法を紹介します。

共通化ファイルを置く場所を作る

まず、共通設定を置く場所とするリポジトリを作ります。

今回は、eslint, prettier と、今後他の設定も追加する可能性があると思ったため、 monorepo 構成で以下のようなリポジトリを作りました。

  • ./packages/eslint-config-vue3 .. eslint config (vue3プロジェクト用) の共通設定用プロジェクト
  • ./packages/prettier-config .. prettier config の共通設定用プロジェクト

monorepo の構成には、今回は lerna を使用します。

eslint の共通設定を作成

プロジェクトのルートに index.js を作成し、共通設定にしたい eslint config の項目を設定します。

/**
 * @type {import('@typescript-eslint/experimental-utils').TSESLint.Linter.Config}
 */
const config = {
  extends: [
    "plugin:vue/vue3-recommended",
    "plugin:storybook/recommended",
    "@vue/typescript/recommended",
    "prettier",
  ],
  globals: {
    es2020: true,
  },
  plugins: ["@typescript-eslint", "vue", "import"],
  parser: "vue-eslint-parser",
  parserOptions: {
    parser: "@typescript-eslint/parser",
    sourceType: "module",
    project: ["tsconfig.json"],
  },
  rules: {
        /**
        * 内容は省略
        */
  },
};

module.exports = config;

また、同プロジェクトの package.json を以下のように設定しておきます。

  • 利用したい eslint plugin をすべて dependencies に追加する
  • 利用側で想定される eslint, prettier のバージョンを peerDependencies に設定する
  • main には上記で作成した js のファイル名を設定する
  • publish 先を今回は GitHub Packages にしたいため、 registry の URL を設定
{
  "name": "@mewton/eslint-config-sample",
  "version": "0.0.12",
  "main": "index.js",
  "dependencies": {
    "@typescript-eslint/eslint-plugin": "^5.40.1",
    "@vue/eslint-config-typescript": "^11.0.2",
    "eslint-config-prettier": "^8.5.0",
    "eslint-plugin-import": "^2.26.0",
    "eslint-plugin-storybook": "^0.6.6",
    "eslint-plugin-vue": "^8.7.1"
  },
  "peerDependencies": {
    "eslint": ">=8.26.0",
    "prettier": ">=2.7.1"
  },
  "publishConfig": {
    "registry": "https://npm.pkg.github.com/mewton"
  }
}

.prettierrc.js を共通化

同様に prettier 側のプロジェクトも設定します。

プロジェクトのルートに共通設定とする prettier config を index.js として作成します。

依存するプラグインを package.json の dependencies に設定しておきます。

/**
 * @type {import('prettier').Config}
 */
 const config = {
  plugins: [require('prettier-plugin-tailwindcss')],
  semi: false,
  arrowParens: 'always',
  singleQuote: true,
  trailingComma: 'none',
  htmlWhitespaceSensitivity: 'ignore',
  bracketSameLine: true,
  singleAttributePerLine: true,
  overrides: [
    {
      files: '*.ts',
      options: {
        printWidth: 100
      }
    },
    {
      files: '*.vue',
      options: {
        printWidth: 150
      }
    }
  ]
}
module.exports = config
{
  "name": "@mewton/prettier-config-sample",
  "version": "0.0.12",
  "main": "index.js",
  "dependencies": {
    "prettier-plugin-tailwindcss": "^0.1.13"
  },
  "peerDependencies": {
    "prettier": ">=2.7.1"
  },
  "publishConfig": {
    "registry": "https://npm.pkg.github.com/mewton"
  }
}

publish する

プロジェクトのルートディレクトリで、以下のコマンドを実行すると GitHub Packages として

@mewton/eslint-config-sample @mewton/prettier-config-sample がリリースされます。

lerna publish --yes --cd-version='patch' --no-verify-access

利用側の設定

publish されたパッケージをインポートするために、以下のコマンドを実行します。

yarn add -D @mewton/eslint-config-sample @mewton/prettier-config-sample eslint prettier

eslint, prettier の本体と、それぞれの共通化された設定値をインポートします。

次に、 .eslintrc.js .prettierrc.js を以下のように記述します。

// .eslintrc.js
module.exports = {
  root: true,
  extends: ['@mewton/sample'] 
    // @mewton/eslint-config-sample がロードされる
    // `eslint-config-` の部分が省略されるので注意
}
// .prettierrc.js
module.exports = require('@mewton/prettier-config-sample')

これで準備完了です。

通常通り eslint, prettier を実行すると、共通の設定が効いていることがわかると思います。

まとめ

これで、eslint, prettier の一元管理ができるようになりました。

プロジェクトごとにメンテする必要はなくなり、 全プロジェクトで共通のコードのきれいさを担保できるようになります。

また、 TypeScript の tsconfig 等、他にも共通化可能な設定もあるようなので、 いろいろ今後も増やしていく予定でいます。