静的解析ツールのESlintを導入します。Prettierは今の所、なくても良いかな!?
Nuxt2でも導入していたのをVue3にも対応させるイメージです。
前回:Nuxt BridgeをNuxt3に移行。上に戻るボタンに対応

ESlintを導入

複数のサイトを参考にさせて頂きましたが、これだけで十分そう。

% yarn add -D eslint @nuxtjs/eslint-config-typescript \
  typescript eslint-plugin-nuxt@latest

package.json

-    "lint:js": "eslint --ext \".js,.vue\" --ignore-path .gitignore .",
-    "lint": "yarn lint:js",
+    "lint": "eslint --ext \".js,.ts,.vue\" --ignore-path .gitignore .",
+    "lint:fix": "yarn lint --fix",
+    "eslint": "eslint",
+    "eslint:fix": "eslint --fix"

  "devDependencies": {
    "@nuxtjs/eslint-config-typescript": "^12.1.0",
    "eslint": "^8.48.0",
    "eslint-plugin-nuxt": "^4.0.0",
    "typescript": "^5.2.2",

tsが対象になっていなかったので追加と、yarn lintだとファイル指定ができない(パスが必須で”.”を入れている)ので、別途、yarn eslintを作りました。

.eslintrc.js

ちなみに.eslintrc.tsだと、設定ファイルがないと言われる。

ESLint couldn't find a configuration file. To set up a configuration file
 for this project, please run:
    npm init @eslint/config
module.exports = {
  root: true,
  env: {
    browser: true,
+    es2021: true,
    node: true
  },
  extends: [
    '@nuxtjs/eslint-config-typescript',
    'plugin:nuxt/recommended',
+    'plugin:vue/vue3-recommended'
  ],
  plugins: [
  ],
  // add your custom rules here
  rules: {
+    'prefer-promise-reject-errors': 'off',
    'vue/max-attributes-per-line': 'off',
    'vue/singleline-html-element-content-newline': 'off',
-    'prefer-promise-reject-errors': 'off',
+    'vue/multi-word-component-names': 'off',
+    'vue/no-reserved-component-names': 'off',
+    'vue/no-multiple-template-root': 'off',
+    '@typescript-eslint/no-var-requires': 'off'
  }
}

Vue3からtemplate直下に複数ルート入れられるようになったので、vue/no-multiple-template-rootを追加しました。

pages/index.vue
  1:1  error  Component name "index" should always be multi-word  vue/multi-word-component-names

-> これは変えられないので、offに変更しました。

pages/users/sign_in.vue
  82:5  error  Name "Form" is reserved in HTML  vue/no-reserved-component-names

-> vee-validateの <Form はそのまま使いたいので、offに変更しました。

nuxt.config.ts
  5:16  error  Require statement not part of import statement  @typescript-eslint/no-var-requires

-> 動的にファイルを切り替えているので、offに変更しました。

const environment = process.env.NODE_ENV || 'development'
const config = require(`./config/${environment}.ts`)

コードを修正(lint修正)

自動修正

% yarn lint --fix

手動修正

The “xxx” event has been triggered but not declared on `emits` option

emitが不要になったケース

components/Message.vue
  3:66  warning  The "update:alert" event has been triggered but not declared on `emits` option   vue/require-explicit-emits
  4:66  warning  The "update:notice" event has been triggered but not declared on `emits` option  vue/require-explicit-emits

-> v-alertの閉じるボタンの仕様が変わっているので修正しました。
 closable追加して、emitで値を消さなくても良くなった。

呼び出し元

-      <Message :alert.sync="alert" :notice.sync="notice" />
+-      <Message v-model:alert="alert" v-model:notice="notice" />
+      <AppMessage :alert="alert" :notice="notice" />

- import Message from '~/components/Message.vue'
+ import AppMessage from '~/components/app/Message.vue'

  components: {
-    Message,
+    AppMessage,

components/Message.vue -> components/app/Message.vue
※共通のはappとかに入れると解りやすくなりそうなので変更します。
 同様に共通のDestroyInfo.vue/Loading.vue/Processing.vue等のパスも変更。

-  <div v-if="alert || notice">
-    <v-alert v-if="alert" type="error" dismissible @input="$emit('update:alert', null)">{{ alert }}</v-alert>
-    <v-alert v-if="notice" type="info" dismissible @input="$emit('update:notice', null)">{{ notice }}</v-alert>
+  <div v-if="alert != null || notice != null">
+    <v-alert v-if="alert != null" type="error" closable>{{ alert }}</v-alert>
+    <v-alert v-if="notice != null" type="info" closable>{{ notice }}</v-alert>

引き続きemitが必要なケース

components/ListSetting.vue
  123:18  warning  The "update:hiddenItems" event has been triggered but not declared on `emits` option  vue/require-explicit-emits

emitsオプションで宣言すればOK!

+  emits: ['update:hiddenItems'],

      this.$emit('update:hiddenItems', hiddenItems)

`<template v-for>` key should be placed on the `<template>` tag

components/ListDownload.vue
  122:27  error  `<template v-for>` key should be placed on the `<template>` tag  vue/no-v-for-template-key-on-child

keyをemplateの中に移動すればOK!

-                      <template v-for="(item, index) in items">
+                      <template v-for="(item, index) in items" :key="item.value">
                        <v-switch
                          :id="`download_output_item_${item.value.replace('.', '_')}`"
-                          :key="item.value"

コードを修正(template直下に複数ルート)

アラートは出ませんが、2行減らせて、インデントも1つ減らせるので、全体的に修正しておきます。
但し、divがなくなると、デザインが崩れる事があるのでご注意を。

※VSCodeにVeturを入れている場合、修正するとvue/no-multiple-template-rootのアラートが表示されます。
.eslintrc.jsの設定が効かない。Veturを無効にして、Volarを入れればOK!

例: pages/infomations/index.vue

<template>
-  <div>

-  </div>
</template>

例: components/app/Message.vue

<template>
-   <div v-if="alert != null || notice != null">

-  </div>
</template>

無駄にdivが出ないようにしていただけなので、削除しました。

例: components/infomations/Lists.vue

- <template>
-   <div v-if="infomations != null && infomations.length > 0">
+ <template v-if="infomations != null && infomations.length > 0">
<template>
+  <template v-if="infomations != null && infomations.length > 0">

-  </div>
+  </template>
</template>

最初のtemplateにもv-if入れられるようです。
無視されるだけなので、divをtemplateに変える事にしました。

不要ファイルを削除

不要なファイルが見えてきたので、削除しておきます。

削除対象

assets/README.md
assets/variables.scss
components/README.md
layouts/README.md
middleware/README.md
pages/README.md
plugins/README.md
store/index.js
store/README.md
store/
.babelrc
.editorconfig
.babel.config.js
jest.config.js
jest.setup.js
jsconfig.json

空ファイルを追加

assets/.keep
middleware/.keep

ヘッダのタイトルが表示されないのと、エラーページがデフォルトのままになってしまったので、そちらの修正を行います。
Nuxt BridgeをNuxt3に移行。ヘッダタイトルとエラーページを修正

今回のコミット内容

origin#507 ESlintを導入、lint修正
origin#507 不要ファイルを削除
origin#507 ESlintのvue/no-multiple-template-rootをoffに変更+対象コード修正

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です