Help us understand the problem. What is going on with this article?

PrettierとLinterを併用する

More than 1 year has passed since last update.

ALE_stylelint-fix.gif
js-standard-style

TL;DR

Prettier触ってみたかったので、boilerplateっぽいのを作った

  • JSはESLint。CSSはStylelintを使います。
  • FormatterとしてPrettierを使用。これはJSのみ。
  • git commit時に自動整形されるようにしておく。

PrettierそのものはCSSにも対応しているが、Stylelintと併用しようとすると、まだ足りない感じなので様子見。けっきょくPrettierしてるのはJSだけなので、なんだか片手落ちな感が否めない。追って対応していきたいところ。いちおレガシーCSSに導入するときとか事前にPrettier通しておくと、多少は楽だった。

コーディングルールに関しては一例として、今回は無難なルールをベースに設定しています。

導入数でいえばGitHubやAirBnBコーディングルールが多数派だが、Linter導入の目的としてはstandardの方が合っているだろうと思う。

メリット

  • 記法が統一されるとレビューで見やすくなる
  • 細かいコードの書き方で揉めるのを防ぐ
  • 並び順とか手動でやらせると非現実的な指定を、自動で行える

Q. PrettierとLinterの--fixオプションは何が違うの?

A. Prettierはコードの整形はするが、警告を出してくれない。
コードの整形そのものは、LinterよりPrettierのほうが巧くやってくれる(1行80文字とか)。とはいえ、あまり細かな指定はできない。なんなら.editorconfigのほうが多いかもくらいなので。

Linterが出してくれる警告には意味があるので消したくないが、エラーがindentで埋まるのは好ましくないので使い分ける。Linterには「記法の統一」と「品質の担保」という2つの側面があって、前者を機械的に処理することによって、本質的なレビューに専心できる。

参考: Prettier vs. Linters

デメリット

  • エディタ連携すると好みのスタイルで書けない
  • Pre-commit設定するとコミット時に多少もたつく

手元では好きなスタイルで書かせておいて、push時にインデントとか整形するってのが、一番Prettierを活かしてるスタイルな気がする。eslint-plugin-standardを抜けばできそうに思うが、どうせmergeすれば変わってるので良いかなとシンプルに--fixで纏めることにした。

Install

$ yarn add -D prettier
$ yarn add -D eslint eslint-plugin-prettier eslint-config-prettier
$ yarn add -D eslint-config-standard eslint-plugin-standard eslint-plugin-promise eslint-plugin-import eslint-plugin-node
$ yarn add -D stylelint stylelint-order stylelint-config-standard

Usage

$ eslint --fix src/**/*.js
$ stylelint  --fix src/**/*.css

ESLintがPrettierを実行するように設定しているのでシンプル。エラーもPrettierの出力を前提にチェックしている。sylelintはそのままで、Prettierなし。

Pre-commit Hook

全員にエディタプラグイン入れさせるのは現実的でないため、
git commitすると自動でLinter/formatterが走るように設定しておく。

$ yarn add -D lint-staged husky
package.json
  ...
  "scripts": {
    "precommit": "lint-staged"
  },
  "lint-staged": {
    "src/**/*.{js,json}": [
        "eslint --fix", "git add"
    ],
    "src/**/*.{css,scss}": [
        "stylelint --fix", "git add"
    ]
  },
  ...

参考: Pre-commit Hook

Note: ESLintと併用する場合

PrettierとESLintと併用する場合、2つの方法がある

  1. eslint-plugin-prettier
    • ESLintのworkflowで処理する
    • Prettierの出力が維持される
    • .eslintrcにprettierが明記されるので判りやすい
    • eslint-config-prettier を使えば、ESLintのPrettierと重複してるルールを無効化してくれる
    • eslint --fix だけで、PrettierとESLintの自動修正を同時に行ってくれる
    • Integrating with ESLint
  2. prettier-eslint
    • Prettierしてからeslint --fixに渡す
    • Prettierのオプションは.prettierrcで管理する
    • prettier-eslint --writeeslint --fixもしてる

ESLintがPrettierを実行するか、PrettierがESLintに渡すか。
ほとんど変わらないが、後者だと--fixなしでチェックだけしたいってのができない。あと、prettier-eslint の作者はもう使ってないとのことなので、現実的にはeslint-plugin-prettier一択。

Note: CSSの場合

stylelint --fixを用いて整形まで行う。

stylelint-orderを入れれば、プロパティのソートが可能になる。postcss-orderの内部で使われていて、今回の場合はstylelint-idiomatic-orderに含まれている。

少し前ならstylefmtて良いツールがあって、Prettierのissueからも誘導されてたけど、stylelintが--fixに対応したので開発が止まってる。prettier使うか、stylelint --fixしろって感じらしい。

Note: prettier-stylelint(できなかったメモ)

$ yarn add -D stylelint prettier-stylelint
$ yarn add -D stylelint-config-standard stylelint-config-idiomatic-order
$ yarn add -D stylefmt
$ prettier-stylelint --write src/test.css

prettier-eslintから着想を得たらしい、prettier-stylelintがあるが、2018-03-30時点ではCLIでは整形されるものの、エラー終了しているのでVimプラグインでは変化しなかった。おそらく以下のエラーを吐いているから。

`{ "parser": "postcss" }` is deprecated. Prettier now treats it as `{ "parser": "css" }`.

Vim Setup

公式でいくつかのエディタに対応している旨が紹介されている。
Editor Integration

以下はVimの場合。

ALE

非同期でチェックが走るので、Syntasticなんかより軽い。設定項目が少なく、標準で多くの言語とツールに対応している。AirLineに対応している点もポイント高い。

dein.toml
[[plugins]]
repo = 'w0rp/ale'
hook_add = '''
    let g:ale_fixers = {
    \    'javascript': ['prettier-eslint'],
    \    'css': ['stylelint'],
    \    'scss': ['stylelint'],
    \}

    " if you want to fix files automatically on save.
    let g:ale_fix_on_save = 1
'''

Neoformat

シンプルで良さそうだったが、標準でstylelint --fixに対応しておらず、標準出力の受け渡しまわりが巧くできなかった。ひとまず例として紹介しておく。

dein.toml
[[plugins]]
repo = 'sbdchd/neoformat.git'
hook_add = '''
    "let g:neoformat_verbose = 1 " only affects the verbosity of Neoformat

    " Enable tab to spaces conversion
    let g:neoformat_basic_format_retab = 1

    " Enable trimmming of trailing whitespace
    let g:neoformat_basic_format_trim = 1

    " js
    let g:neoformat_javascript_prettiereslint = {
        \ 'exe': './node_modules/.bin/prettier-eslint',
        \ 'args': ['--stdin'],
        \ 'stdin': 1,
        \ }
    let g:neoformat_enabled_javascript = ['prettiereslint']

    " css
    let g:neoformat_css_stylelint = {
        \ 'exe': './node_modules/.bin/stylelint',
        \ 'args': ['--stdin', '--fix'],
        \ 'stdin': 1,
        \ }
    let g:neoformat_enabled_css = ['stylelint']

    augroup fmt
        autocmd!
        autocmd BufWritePre *.js Neoformat
        autocmd BufWritePre *.css Neoformat
        autocmd BufWritePre *.scss Neoformat
    augroup END

参考

sigwyg
theport
ポート株式会社 PORT INC.は、「世界中に、アタリマエとシアワセを。」をミッションに、新しい時代の1ページを創る会社です。【PORTもくもく会】https://freestyle-mokumoku.connpass.com/
https://www.theport.jp/
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
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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
ユーザーは見つかりませんでした