🐞

[Vue warn]: The setup binding property "*" is already declared.の解決方法

2022/08/03に公開

vue2 + composition-apiを利用して新規プロジェクトを作っていた際に、
突然consoleにこのようなエラーが出るようになりました。

見たことがないエラーで、数時間調べてようやく原因が判明したので、
解決方法をご紹介しようと思います。

対象

  • 2022年7月1日以降にvue-cliから新規プロジェクトを作成した方

解決方法

問題の原因は、2022年7月1日にvue2系最後のマイナーバージョンとして公式リリースされた、
vue2.7(Naruto)における仕様変更です。

今回のエラーに関わる仕様変更は2点です。

  • composition-apiが標準装備となった
  • <script setup>が使えるようになった。

1) vueバージョン確認

まずはプロジェクトに実際にインストールされているバージョンを確認しましょう。
yarn-lockかpackage-lock.jsonを開きバージョン内容を見ます。

「vue@」などで検索すると出てくると思います。

ここで、実際にインストールされているvueのバージョンを見ることが出来ます。

これでvueのバージョンが2.7.8であることが確認出来ました。

ということで、最初の解決方法はこれです。

2-1) 解決方法A(vue2.7の仕様に合わせて書き直す)

最新仕様(2.7)に合わせた書き方に変更することで解決します。

1. composition-apiをアンインストールする

composition-apiは標準装備となったので、アンインストールします。

yarn remove @vue/composition-api

2. main.tsを修正

main.tsのcomposition-api関連のコードを削除する

main.ts
import Vue from "vue"
import App from "./App.vue"
import router from "./router"
import VueCompositionApi from "@vue/composition-api" //削除する
import vuetify from "./plugins/vuetify"

Vue.use(VueCompositionApi)//削除する
Vue.config.productionTip = false

new Vue({
  router,
  vuetify,

  render: function (h) {
    return h(App)
  },
}).$mount("#app")

3. VSCodeの拡張機能を変更する

  1. vue3系のVolarをインストールして有効にします。
  2. VolarとVeturは共存できないので、後者を無効化します。

4. vueファイルのscriptを書き換える

vueファイルの<script>をこんな風に書き換えます。
(vue3触ったことある方なら分かりやすいと思います。)

  • <script lang="ts">にsetupを加える
  • defineComponent不要
  • setup(){}, return{}不要
  • components:{}も不要(importするだけでOKです)

vue2.7仕様(例)

sample.vue
<template>
 <div>
  <TheHeader />
  <p>{{state.title}}<p>
 </div>
</template>

<script setup lang="ts">
import { reactive } from "vue"
import TheHeader from "@/layouts/TheHeader.vue

const state = reactive({
  title: "",
})
</script>

(コード量が大分減りました!!)

従来(vue2.6)の書き方(例)

sample.vue
<template>
 <div>
  <TheHeader />
  <p>{{state.title}}<p>
 </div>
</template>

<script lang="ts">
import { defineComponent, reactive } from "@vue/composition-api"
import TheHeader from "@/layouts/TheHeader.vue

export default defineComponent({
components:{
  TheHeader
},
 setup(){
  const state = reactive({
    title: "",
  })
  
  return { state }
 }
})
</script>

以上の方法でエラーを回避できます。

2-2) 解決方法B(ダウングレード:vue2.6を使い続ける)

実装済みファイルが多く変更が大変な場合はvue2.6を使い続けるのもありだと思います。

その場合は、vue2.6.14を再インストールしましょう。

インストールする際、バージョンの先頭にチルダ(~)をつけておきましょう。
チルダやキャレット(^)の詳しい説明はこの記事が読みやすかったです。

yarn add vue@~2.6.14 

このままだと、vueのバージョンとvue-template-compilerのバージョンがmiss matchと怒られるので、vue-template-compilerをvueと同じバージョンにするために再ンインストールします。
(これもチルダで行います)

yarn add vue-template-compiler@~2.6.14

これでyarn serveして、エラーなし&通常通り表示されるはずです。

ビハインド(なぜ解決までに時間がかかったか?-yarn.lockの存在)

主な要因はpackage.jsonの見方を間違えていたことでした。

package.jsonにこのように書かれていると、つい2.6.14がインストールされていると思ってしまいます。

package.json
"vue": "^2.6.14",

しかし実際にインストールされているのは2.7.8です。(yarn-lockで確認可能)

そしてv2.6とv2.7では大きな変更がありました。

セマンティックバージョニングによると、
X.Y.Zとある場合、以下のような名称がついており、

  • X: メジャーバージョン
  • Y:マイナーバージョン
  • Z:パッチバージョン

今回のように^2.6.14(キャレット)の場合は、X.Y.Zの内、Xさえ合っていればいいので、
2.7.xだろうが、2.10.xだろうがインストールされてしまうわけです。

ちなみに、~2.6.14(チルダ)の場合は、X.Y.Zの内、X.Yまであっていればいいので、
タイミングによって2.6.16とか2.6.20とかがインストールされるわけです。
(つまり2.6を保証出来ます)

今回はマイナーバージョンのアップデートですが割とインパクトのある変更だったと思います。
package.jsonが^(キャレット)になっていると、大きな変更にも遭遇する可能性があることを知れました。

チーム開発する際は、メンバーが後から参加することもあるので、
yarn-lockからインストールするようにした方がよさそうです。

こんな記事を思い出しました。
https://blog.minimalcorp.com/users/jigen/posts/6f325dc9b8a00370b6aedf47a34cb3ce

yarn-lockからインストールする方法
https://techblg.app/articles/npm-ci-in-yarn/

まとめ

今回はvue2.7リリースに伴うエラーを解消する方法をまとめました。
解決には時間がかかりましたが、知識もついたので良かったです!

エラーで困っている方のお役に立てたら幸いです。

Discussion