Motomichi Works Blog

モトミチワークスブログです。その日学習したことについて書いている日記みたいなものです。

webpackでビルドする前にeslintで.vueと.jsの構文チェックをする | webpack4.x+babel7+vue.js 2.x 環境構築 2019年3月版 ステップ0004

参考にさせて頂いたページ

webpack.config.jsについて

eslintについて

eslint-loaderのoptionsについて

色々

以前書いた記事

グローバルにインストール

npm install -g eslint

プロジェクトにインストール

まず以下の4つのモジュールをインストールします。

npm install --save-dev eslint eslint-loader babel-eslint eslint-config-vue eslint-plugin-vue

eslint-config-standard - npm」を入れます。依存するモジュールが4つあるのでまとめてインストールします。

npm install --save-dev eslint-config-standard eslint-plugin-import eslint-plugin-node eslint-plugin-promise eslint-plugin-standard

ここまでやった段階でのpackage.json

{
  "name": "webpack_4_vue_introduction",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "watch": "webpack -d --watch",
    "test": "jest"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/cli": "^7.4.3",
    "@babel/core": "^7.4.3",
    "@babel/preset-env": "^7.4.3",
    "@vue/test-utils": "^1.0.0-beta.29",
    "babel-core": "^7.0.0-bridge.0",
    "babel-eslint": "^10.0.1",
    "babel-jest": "^24.7.1",
    "babel-loader": "^8.0.5",
    "css-loader": "^2.1.1",
    "eslint": "^5.16.0",
    "eslint-config-standard": "^12.0.0",
    "eslint-config-vue": "^2.0.2",
    "eslint-loader": "^2.1.2",
    "eslint-plugin-import": "^2.17.1",
    "eslint-plugin-node": "^8.0.1",
    "eslint-plugin-promise": "^4.1.1",
    "eslint-plugin-standard": "^4.0.0",
    "eslint-plugin-vue": "^5.2.2",
    "jest": "^24.7.1",
    "jest-serializer-vue": "^2.0.2",
    "node-sass": "^4.11.0",
    "sass-loader": "^7.1.0",
    "style-loader": "^0.23.1",
    "vue-jest": "^3.0.4",
    "vue-loader": "^15.7.0",
    "vue-template-compiler": "^2.6.10",
    "webpack": "^4.30.0",
    "webpack-cli": "^3.3.0"
  },
  "dependencies": {
    "vue": "^2.6.10",
    "vuex": "^3.1.0"
  }
}

webpack.config.jsの編集

rulesに以下のeslint-loaderをrulesの.vueと.jsの二か所に追記します。

          {
            loader: 'eslint-loader',
          },

ここまでやった段階でのwebpack.config.js

以下のようになりました。

const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin');

module.exports = {
  // entry point
  entry: {
    'javascripts/first_page': './src/javascripts/entry_points/first_page.js',
  },
  // 出力するパスは絶対パスで書きます
  output: {
    path: `${__dirname}/webroot/packed`,
    filename: (arg) => {
      return '[name].bundle.js'
    },
  },
  // webpack4はlordersではなくなりました
  module: {
    rules: [
      // 拡張子.vueのファイルに対する設定
      {
        test: /\.vue$/,
        use: [
          {
            loader: "vue-loader",
            options: {
              loaders: {
                js: 'babel-loader',
              },
            },
          },
          {
            loader: 'eslint-loader',
          },
        ]
      },
      // 拡張子.jsのファイルに対する設定
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
          },
          {
            loader: 'eslint-loader',
          },
        ]
      },
      // 拡張子.scssのファイルに対する設定(.vueの中にscssを書きたい場合もここに設定します。)
      {
        test: /\.scss$/,
        use: [
          {
            loader: 'style-loader',
          },
          {
            loader: 'css-loader',
          },
          {
            loader: 'sass-loader',
          },
        ]
      },
    ]
  },
  // デフォルトの設定値だけでは足りないことについて解決します
  resolve: {
    // モジュールを読み込むときに検索するディレクトリの設定
    modules: [path.join(__dirname, 'src'), 'node_modules'],
    // importするときに省略できる拡張子の設定
    extensions: ['.js', '.vue'],
    alias: {
      // importのファイルパスを相対パスで書かないようにsrcのrootを設定
      '@': path.join(__dirname, 'src'),
      // 例えばmain.js内で `import Vue from 'vue';` と記述したときの`vue`が表すファイルパスを指定
      'vue$': 'vue/dist/vue.esm.js'
    },
  },
  // プラグインを列挙
  plugins: [
    new VueLoaderPlugin()
  ],
}

.eslintrc.jsを空ファイルで作成

.eslintrcは以前は拡張子がありませんでしたが、今は拡張子を付けることが推奨されています。

.eslintrcは色々な拡張子で作成できます。

jsonの例をよく見かける気がしますが、jsonは記述ルールが厳しいので、.jsにしようと思います。

windowsの場合

copy nul .eslintrc.js

macの場合

touch .eslintrc.js

.eslintrc.jsの記述内容

以下の通り記述します。

module.exports = {
  "extends": [
    // eslint-plugin-vue(.vueファイルのtemplateとscriptのlint)をextend
    "plugin:vue/recommended",
    // eslint-config-standardをextend
    "standard",
  ],
  "parserOptions": {
    // ecmaVersionを指定
    "ecmaVersion": 6,
    // type="module"をサポート
    "sourceType": "module",
    // parserを指定
    "parser": "babel-eslint",
  },
  "env": {
    // browserが持っているオブジェクトをサポート
    "browser": true,
    // ES2015以降に追加された組み込みオブジェクトをサポート
    "es6": true
  },
  "globals": {},
  "rules": {
    "semi": ["error", "always"],
    "comma-dangle": ["error", "always-multiline"],
  }
}

一度ビルドしてみる

webpack -d

以下のような感じでとても多くの構文エラーが出ました。

何行目の何文字目がエラーなのか書いてあります。

   1:22  error    Extra semicolon                                                               semi
   6:1   error    Import in body of module; reorder to top                                      import/first
   6:70  error    Extra semicolon                                                               semi
   8:33  error    Extra semicolon                                                               semi
  10:1   error    Do not use 'new' for side effects                                             no-new
  14:3   warning  The "components" property should be above the "template" property on line 13  vue/order-in-components
  15:3   error    Extra semicolon                                                               semi
  16:1   error    Too many blank lines at the end of file. Max of 0 allowed                     no-multiple-empty-lines

構文を修正する

以下はルールの一例です。コツコツ修正するか、後述するautofixのoptionを追加してから再度ビルドします。

  • 'mapGetters' is defined but never used: 変数を定義しているが使われていない
  • 'mapActions' is defined but never used: 変数を定義しているが使われていない
  • Extra semicolon: 余計なセミコロンがある
  • The "components" property should be above the "template" property on line 13: 記述する順番が規約に沿ってない
  • Expected 1 line break after opening tag ('<button>'), but no line breaks found: 改行してない
  • Missing trailing comma: カンマが無い
  • Missing space before function parentheses: (の前に半角スペースが無い
  • Expected a space before '/>', but not found: /の前に半角スペースが無い
  • Property name "app" is not PascalCase: 一文字目は大文字にする
  • Do not use 'new' for side effects: newする場合は変数に入れる

自動修正の設定をする

webpack.config.jsに以下のようにoptionsを設定することで、ビルドの度に自動修正することができるので、自動修正したい場合は設定します。

webpack.config.jsを二か所修正しておきます。

          {
            loader: 'eslint-loader',
            options: {
              fix: true,
            },
          },

ここまでやった段階でのwebpack.config.js

以下のようになりました。

const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin');

module.exports = {
  // entry point
  entry: {
    'javascripts/first_page': './src/javascripts/entry_points/first_page.js',
  },
  // 出力するパスは絶対パスで書きます
  output: {
    path: `${__dirname}/webroot/packed`,
    filename: (arg) => {
      return '[name].bundle.js'
    },
  },
  // webpack4はlordersではなくなりました
  module: {
    rules: [
      // 拡張子.vueのファイルに対する設定
      {
        test: /\.vue$/,
        use: [
          {
            loader: "vue-loader",
            options: {
              loaders: {
                js: 'babel-loader',
              },
            },
          },
          {
            loader: 'eslint-loader',
            options: {
              fix: true,
            },
          },
        ]
      },
      // 拡張子.jsのファイルに対する設定
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'babel-loader',
          },
          {
            loader: 'eslint-loader',
            options: {
              fix: true,
            },
          },
        ]
      },
      // 拡張子.scssのファイルに対する設定(.vueの中にscssを書きたい場合もここに設定します。)
      {
        test: /\.scss$/,
        use: [
          {
            loader: 'style-loader',
          },
          {
            loader: 'css-loader',
          },
          {
            loader: 'sass-loader',
          },
        ]
      },
    ]
  },
  // デフォルトの設定値だけでは足りないことについて解決します
  resolve: {
    // モジュールを読み込むときに検索するディレクトリの設定
    modules: [path.join(__dirname, 'src'), 'node_modules'],
    // importするときに省略できる拡張子の設定
    extensions: ['.js', '.vue'],
    alias: {
      // importのファイルパスを相対パスで書かないようにsrcのrootを設定
      '@': path.join(__dirname, 'src'),
      // 例えばmain.js内で `import Vue from 'vue';` と記述したときの`vue`が表すファイルパスを指定
      'vue$': 'vue/dist/vue.esm.js'
    },
  },
  // プラグインを列挙
  plugins: [
    new VueLoaderPlugin()
  ],
}

もう一度ビルドする

自動修正の設定をした場合、今回の構文エラーのほとんどはこれで直ります。

webpack -d

Do not use 'new' for side effects を無視する

.eslintrc.jsを編集します。

以下のようにrulesに追記しました。

  "rules": {
    〜略〜
    "no-new": "off",
  }

出力されるWarningメッセージについて

ESLint v5.0.0 変更点まとめ - Qiita

eslint実行時に以下のWarningメッセージが出力されています。
これはeslint5から表示されるようになったようです。
parserOptions.ecmaFeatures.experimentalObjectRestSpreadが非推奨でparserOptions.ecmaVersionを使用してくださいということらしいですが解決の仕方がわからず一旦このまま使っています。

(node:16602) [ESLINT_LEGACY_OBJECT_REST_SPREAD] DeprecationWarning: The 'parserOptions.ecmaFeatures.experimentalObjectRestSpread' option is deprecated. Use 'parserOptions.ecmaVersion' instead. (found in "vue")

またそのうちわかったら。

おわりに