Blog

<Gulp + ESLint + Babel> ちょっと手を加えたJSファイルを作る

※「IEサポート終了」「ブラウザのESM対応」など、時代の変化に合わせて再構築しました。

コーダーのためのWeb制作環境 〜万能な静的ファイル群を作ろう〜

普段、JavaScriptはwebpackで最適化し、バンドルしてWEBサイトに読み込ませています。
基本はGulpでSCSSをコンパイルしたりホットリロードの設定をしたりしていますが、JSはGulpでwebpackを動かすという方法にしています。

ですが、お客さんによっては、「JavaScriptは最適化しない状態で納品してください」という方もいらっしゃいます。
直クライアントではなく、間に代理店が入る場合、パートナーとして一部を請け負ってる場合、クライアント社内にWEBチームがある場合に、この方が良いということがあります。

そういう時に、書いたままのJSファイルをそのまま渡すのは何か気が引ける…し、IE11対応だと動かない可能性がある。
編集できる状態で、ちっちゃいエラーもなく、トランスパイルされたファイルを渡さなければ…

そんなわけで、GulpでそのようなJSファイルを作ることにしました。

ESLintとBabel

この二つのみ、適用することにします。

ESLintは、JavaScriptのコードの構文を検証するためのツールです。
Gulp用に、gulp-eslintというパッケージがあるので、それを使います。

Babelは、新しい書き方のコードを、レガシーブラウザでも動くコードに変換してくれるツールです。
これによって、アロー関数やconstやletが使えるようになります。言わずもがなIE11対策です。(あと1年くらいかしら…)
Gulp用にgulp-babelというパッケージがあるので、それを使います。

インストール

npm i gulp-eslint
npm i babel-eslint
npm i gulp-babel

babel-eslintは、ESLint自体でまだサポートされていない実験的な機能を使用してるコードも適用可能になります。ES6用に入れてます。

Babel7の場合は下記二つも必要です。

npm i @babel/core
npm i @babel/preset-env

gulpfile.jsの設定

const gulpEslint = require('gulp-eslint');
const gulpBabel = require('gulp-babel');

//バンドルも最適化もしたくない、eslintとbabelだけ
const eslint = (done) => {
  gulp
    .src(baseDir + '/js/main.js')
    .pipe(gulpEslint({ useEslintrc: true, fix: true })) // .eslintrc を参照、自動修正オン
    .pipe(gulpEslint.format())
    // .pipe(gulpEslint.failAfterError())
    .pipe(gulpBabel({
      "presets": ["@babel/preset-env"]
    }))
    .pipe(gulp.dest(dist + "/js"))
  done();
};
const watch = () => {
  gulp.watch(baseDir + '/js/**/*.js', gulp.series('eslint', 'reload'));
};

gulp.task('eslint', eslint);

exports.default = gulp.parallel('watch', 'browser-sync');

gulpEslint.formatは、結果をコンソールに出力します。
gulpEslint.failAfterErrorは、すべてのタスクが完了したあとに処理を止めてエラーを出力します。最初はありにしてたのですが、いろいろやっていくうちに、なくてもいいか…と思ったのでコメントにしてます。

.eslintrc.jsonの設定

gulpfile.jsの「useEslintrc: true」で、.eslintrc を参照するようにしているので、
ルートディレクトリに.eslintrcを作って、そこにルールを書き込みます。

{
    "extends": [
        "eslint:recommended"
    ],
    "plugins": [],
    "parser": "babel-eslint",
    "env": {
        "browser": true,
        "es6": true
    },
    "globals": {
        "$": false
    },
    "rules": {
        "quotes": ["error","single"]
    }
}

eslint:recommended

ESLintのルールはたくさんあるので、一つ一つ書いていくと大変ですが、
extendsでeslint:recommendedにすれば、ESlintのおすすめをまとめて設定できます。

ルールはこちら
List of available rules - ESLint - Pluggable JavaScript linter

このページの左列にチェックマークのあるものが、recommendedでチェックされているもののようです。
recommendedを設定した上で、rules:{}に追加ルールを書くこともできます。

ルールにそって自動で直してほしいので、gulpfile.jsの方で「fix: true」を加えています。
何を自動で直してくれるのかというと、上記の公式ルールにあるレンチマークのついたものです。

globals

globalsには「$:false」と設定しています。
これは、このJSファイルの外でjQueryを定義していることをESLintに教えています。
jQueryを使って書いているコードはこれがないと「'$' is not defined」というエラーがたくさん出ます。
ちなみに、"env"のなかに「"jquery": true」をいれることでもエラー回避できます。

rules

基本はおすすめの設定ですが、一個だけ「シングルクオートに統一」を入れました。(リンターの動きを確認するためと言ってもいい…)

env

envキーで、どの環境を有効にしたいかを指定します。
「"browser": true」は、ブラウザのグローバル変数を有効にします。これがないと、「window」「location」「console」などがis not definedになってしまいます。

「"es6": true」は、モジュールを除くすべてのECMAScript 6機能を有効にします。これがないと、「Promise」がis not definedになります。
ちなみにPromiseはどちらにせよIE11で使えないので、リンターを突破したとて、使う場合はpolyfillを検討する必要があります。

自動修正とコード整形について

gulpfile.jsにfix:trueを追加し、ESLintの範囲内のもので自動修正可能なものは自動で直すようにしました。

.pipe(gulpEslint({ useEslintrc: true, fix: true })) // .eslintrc を参照、自動修正オン

コード整形は、私の場合はBabelが最終的にフォーマットしてくれます。(インデントや文末のセミコロン抜け、空行の調整など)
ですが、そうでなくてもフォーマットに関しては元ファイルの方でVSCodeの規定フォーマッタを使って自動フォーマットさせ、特にGulpに任せないという方向でいこうと思います。
Prettierを併用する方法もありそうですが、あまりいろいろやると衝突したときにまた原因追求しないといけないので、今回はなしとしました。

gulp-babelがやってくれてるフォーマッタには一体何が使われているのだろう…と思いましたが、そこまで調べきれませんでした。
コメントの空行を無くしてくれたり、これがないとやってくれないことをやってくれているので、気になるところではあるのですが…

コメントが勝手に違うところについてしまう問題

そのgulp-babelの挙動で、コメントが一部移動してしまうケースがありました。

move(hash) {
  let target = hoge;
  // 移動先を数値で取得
  if (target.length) {
    let position = ほげ〜

の様な時、この「// 移動先を数値で取得」というコメントは、その下のif文にかかっているコメントなのですが、
これが

value: function move(hash) {
  var target = hoge; // 移動先を数値で取得

  if (target.length) {
    var position = ほげ〜

となってしまいます。
var target のコメントみたいになっている…。

このような箇所がたくさんあるんですが、.eslintrc.jsonをいろいろ触ってみても、なおりません。
ESLintのlines-around-commentがコメント周りの空行をなんとかするものみたいだけど、さっぱり効かない。gulp-babelの設定かなにかで上書きされてるんでしょうか?(不明)

なので、こういうコメントはそもそもブロックコメントを利用することにしました。自分のそもそもの書き方を直そう。

行コメントではなく、ブロック単位で日本語コメントを入れたい場合は、ちゃんとブロックコメント(/* 〜 */)を利用するというマイルールを作ることにしました。

まとめ

この他に、WEB制作を始めてから今まで追加修正を重ねてきたMyJSをいろいろ書き直すという作業もやりました。
もうちょっと統一感のあるコードがかけたらよいなあと思うので、これから細かいところも考えていこうかなと思いました。
それにしても、納品形態に合わせていろんなことができる、Gulpは便利です。

おすすめの記事 recommend blog

新着 new blog

github