Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
25
Help us understand the problem. What is going on with this article?
@qiiteinai

LaravelにESLintとPrettierを導入する時にやったことの全て

More than 1 year has passed since last update.

はじめに

この記事ではLaravel5.8ESLintPrettierを導入します。

LaravelのMVCモデルでは、Viewの部分は *.blade.phpファイルによって書くことが一般的です。
しかし最近では、JavaScriptの描画技術の幅やページの描画スピードの速さなどを理由として、bladeは完全に捨ててVue.jsにフロントエンドの全てを任せる構成をとるプロジェクトが多いと感じています。

今回、ESLintを導入する対象となったLaravel5.8のプロジェクトは僕がPMをしているプロジェクトです。

このプロジェクトでも、Laravelのbladeはほとんど使用しておらず、画面描画は resourses/js/に置かれているVue.jsによって行っています。

今回の記事の対象者は、LaravelでVue.jsを使っているor使いたい方全てです。

なぜESLintとPrettierを使うべきなのか

「なぜESLintPrettierを併用して使うべきなのか」ということについては、Laravelに限らず、広く議論されていることですので、ここでは触れません。
この議論の結論を言えば、「ESLintだけ導入」あるいは「Prettierだけ導入」というのは諸事情があって微妙だからどちらも使おうね、ということです。

以下ではESLintPrettierを導入するにあたり、僕が感じている利点について触れておきます。

集団開発でコードフォーマットが統一されていないのはかなりしんどい

「何を綺麗と感じるか」は人それぞれです。
しかし、一方で個々の感性が異なるために、しばしば地獄をみることになります。

  • 「あれ?末尾のセミコロンは前全部消したはずなのにまたAさんが足し直してる、、、」
  • 「キャメル?パスカル?命名規則が混在している、、、」
  • 「シングルクォーテーションとダブルクォーテーションが混在している、、、」

これを十人十色などと言ってはいけません。阿鼻叫喚です。
コードのフォーマットや変数の命名規則が理由で議論が始まったりプルリクエストが通らないとしたら、せっかくLaravelを使っているのにあなたの開発スピードは早いとは言えなくなりませんか?

  • フォーマットや変数の命名規則は開発者間で統一する
  • 開発者ごとのフォーマット調整による余計な差分はなくし、コードレビューの可読性をあげる

この重要性を理解しましょう。コードレビューは常にロジックにのみ集中するべきです。

1人で開発するからといってフォーマットが煩雑なのは許されない

僕の価値観では、コードというものは「誰が見ても美しくあるべき」です。あなたがフォーマッターを使わずに書いたコードは、他人が見ても必ず美しいと思えるでしょうか。また、開発者が感じる「美しさ」は誰が保証してくれるのでしょうか?

「ソースコードは1人で扱うから」とは言っても、いつかもう1人のメンバーが加わる場合もあります。
そう言った際に無駄なコストを払わないように、1人だとしてもフォーマットには基準を設けて整形しておくのがマナーだと僕は考えています。

ESlintPrettierは非常に優秀なフォーマッターなので、「ESLintとPrettierが共通のルールによって整形してくれたのだから信じよう」と開発者は思うのです。

いつESLintとPrettierを導入するのか

上記で「ESLintPrettierを導入しなさい」と布教したのですが、僕も最近になってようやくこれらのフォーマッターを導入したのです。

実は、ESLintPrettierを導入するまでにGitHubでのcommitは500を超えており、そこそこの規模のプロジェクトになっていました。ですから、かなりの数の *.js *.vueファイルが存在していました。

導入パターン

ESLintを全てのファイルにかける(=現存する*.jsファイルや*.vueファイルを一気に整形する)場合、非常にコンフリクトが発生しやすくなります。

対象の全てのファイルの全体に対して改行ポイントやスペース、コンマや命名規則、変数宣言や比較演算子などありとあらゆるコードを修正することを想像すれば「コンフリクトが発生しやすい」というのは火を見るより明らかです。そして、そのコンフリクトは激しくなりがちであることも理解できるでしょう。

ESLintを導入するタイミングはおおよそ次のパターンに分類できます。

  1. 今からLaravelをセットアップするあなた
    →後悔はさせないので、いますぐ導入しましょう。最もEasyです。このタイミングで気づいたあなたは偉い!

  2. すでにそこそこの規模になっているあなた
    →プロジェクト全体で大きな変更がないタイミングを伺いましょう。そこそこの努力と忍耐が必要です。

  3. かなりの規模になっていて集団開発が盛んになっているあなた
    →この時点で何かしらのフォーマッターを入れていないのはまずい状況ですが、導入のタイミングも難しいです。大量のコンフリクトを覚悟して慎重にタイミングを見計らいます。開発者全体で打ち合わせなどをする必要があるかもしれません。

僕は2番に該当していたつもりですが、それでも一気にESLintを全てのファイルにかけて本当に血の海を見ました。全ファイルが血を流して倒れました。

それでもなんとかコンフリクトが少なくなるようなタイミングを見計って行えば、ギリギリ耐えます。
あなたのフォーマッターへの想いだけを信じてください。

ESLintとPrettierを導入する

やっと本題です。しかしやることはそんなに多くありません。

今回は、プロジェクトの途中からESLintPrettierを導入します。(上記での2or3番を想定しています。1番でももちろん全く問題なし!)
ここから先はLaravelがどうこうというより、ESLintPrettier自体をよく理解していることが重要です。

パッケージをインストールする

今回必要なパッケージは以下になります。たくさんあります。
以下のパッケージは開発時にしか必要ありませんので --save-devオプションをつけてインストールしてあげます。

$ npm install babel-eslint eslint eslint-config-prettier eslint-config-standard eslint-friendly-formatter eslint-loader eslint-plugin-html eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-node eslint-plugin-prettier eslint-plugin-promise eslint-plugin-standard eslint-plugin-vue laravel-mix-eslint --save-dev

ESLintの設定ファイルを作成する

続いて、.eslintrc.jsファイルを新しく作成します。
このファイルではESLintとPrettierの整形ルールを定めます

$ cd yourLaravelProject
$ vim .eslintrc.js
.eslintrc.js
module.exports = {
  root: true,
  parserOptions: {
    parser: 'babel-eslint',
  },
  env: {
    browser: true,
  },
  extends: [
    'standard',
    'plugin:vue/recommended',
    'plugin:prettier/recommended',
    'prettier/vue',
  ],
  plugins: [
    'vue',
    'prettier', // prettierをESLintと併用します
  ],
  rules: {
    // ESLintが使用する整形ルールのうち、自分がoffにしたいルールなどを指定する
    'vue/no-v-html': 'off', // v-htmlの使用について
    'vue/prop-name-casing': 'off', // Propsの変数の命名規則について
    'no-console': 'off', // console.log()の使用について
    'no-unused-vars': 'off', // 使われていない変数について
    'camelcase': 'off', // camelcaseについて

    // この先はPrettierのルール
    "prettier/prettier": [ 
      "error",
      {
        printWidth: 120,
        tabWidth: 2,
        useTabs: false,
        singleQuote: true,
        trailingComma: 'all',
        bracketSpacing: true,
        arrowParens: 'avoid',
        semi: false,
      },
    ]
  }
}

この設定ファイルは結構厳しめにルールを設けているつもりです。
そもそもせっかくコードフォーマッターを導入するのにルールを緩くしておく必要はないからです。

しかし、もしプロジェクトの途中での導入に際してあまりルールを厳しく入れたくないという場合は、extends:[]の部分を見直すと良いと思います。

このあたりは下記サイトが参考になりました。
(参考)Vue.jsスタイルガイドとeslint-plugin-vue検証ルールのマッピング

またPrettierのルールもあなたの好みです。
Prettierのルールは公式ドキュメントを参考に変更すると良さそうです。
(参考)Options - Prettier

ファイル変更時にESLintを使用する

webpackが上記の整形ルールを使用してファイル変更をwatchしてくれるようにwebpack.mix.jsを編集します。

webpack.mix.js
const mix = require('laravel-mix')

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel application. By default, we are compiling the Sass
 | file for the application as well as bundling up all the JS files.
 |
 */

// ESLintに関する設定(この部分を丸ごと追記するイメージです)
if (!mix.inProduction()) { // 本番環境ではESLintは使用しない
  mix.webpackConfig({
    module: {
      rules: [
        {
          enforce: 'pre',
          exclude: /node_modules/,
          loader: 'eslint-loader',
          test: /\.(js|vue)?$/,
        },
      ],
    },
  })
}

// watchするファイルやポート番号などに関する設定(今回の内容とは関係ありません)
mix
  .js('resources/js/app.js', 'public/js')
  .sass('resources/sass/app.scss', 'public/css')
  .browserSync({ // browserSyncの設定
    files: ['resources/js/**/*', 'resources/sass/**/*', 'resources/views/**/*', 'public/css/**/*'],
    port: 3000,
    ui: {
      port: 3001,
    },
    proxy: 'localhost:8000', //php artisan serveで立ち上げた8000番をProxyする
  })

// 本番環境ではバージョン付けによるキャッシュ対策を施す(今回の内容とは関係ありません)
if (mix.inProduction()) {
  mix.version()
}

これで基本的なセットアップは全て終了です。

$ npm run watch

を唱えることによっていつも通り開発を開始しましょう。コンソールでESLintとPrettierが大量のエラーを吐いてくれるはずです。

実際に動作を確認する

あなたのコンソールを見てください。
例えば次のようになっている場合、

/Users/yourName/Laravel/resources/js/pages/A/B.js
350:1  error  Delete `····`
       prettier/prettier

これはPrettierが怒っている様子です。

このエラーが指し示すところは、
/js/pages/A/にあるファイルB.jsの350行目の1列目から無駄な空白があるから消せ」
ということです。

これらのエラーは地道に解消しても良いですが、あなたの見ているエラーの量を見てください。地獄ですよね。

でも安心してください、自動でこれらのエラーをほとんど解消してくれるESLintのコマンドがあります。

エラーを吐いているファイル名とそのディレクトリを確認して、コンソールで

// ESLintとPrettierの両方を実行する
$ eslint resources/js/pages/*/*.js --fix

を実行しましょう。
ファイル名はresources/js/pages/*/*.jsのようにワイルドカードを使用して指定できます。
これによってresources/js/pages/*/*.js に該当するファイルのエラーが自動で解消されていきます。

eslint ファイル名 --fixコマンドによってESLintとPrettierの両方が実行されることに注意してください
これはすでに上記で導入した eslint-config-prettierの恩恵を受けています。
ESLintとPrettierの併用に関する詳しい説明は以下の記事などがわかりやすいと思います。
(参考)ESLint - Prettier連携のやり方と仕組み

これでLaravelの*.jsファイルや*.vueファイルに対してESlintとPrettierを導入することができました。

どのようなエラーを吐いているかはあなたのプロジェクト次第です。

コンソールでのエラーを見ながら .eslintrc.jsファイルで整形方法を調整しましょう。特定の整形ルールをoffにすることもできますから、あなたの開発チームメンバーにとって最良の設定を記述し、幸せな開発サイクルを目指しましょう。

最後に

この設定を行ったことで、あなたのLaravelの*.jsファイルや*.vueファイルは全ての開発者間でフォーマットが統一されました。

今後の展望としては
1. git commitのときにESLintを自動で強制する
2. *.phpファイルに対しても何かしらのLintを施す

本記事ではこれらの設定はオーバーワークになりますので、別記事で紹介しようと思います。

長くなりましたが、ありがとうございました。

25
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
qiiteinai
資格Times (https://shikakutimes.jp) という資格情報メディアでCTOを務めています。 ご興味がある方はメールアドレス宛にご連絡ください! 得意な領域や言語 Laravel | Nuxt.js | AWS

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
25
Help us understand the problem. What is going on with this article?