Rails6系+Vue3系で"Hello, Vue3!"

###はじめに
当方初記事となりますが、今回は私が一週間くらいハマりにハマってしまったRail6でのVueの導入、そしてブラウザに"Hello,Vue3!"を表示するところまでの手順を記したいと思います。

Rails6+Vue3に関する記事はQiitaをはじめとする各Q＆Aサイトで多くの方が取り扱っていらっしゃいますが、私はどうにも要領が悪いのか、うまくいきませんでした。なぜかって？こっちが聞きたいです。

Vue.jsを初めて触るという方は、先にVue.js公式にてVue.jsについて確認しておくことを推奨致します。
https://v3.ja.vuejs.org/

##本記事のゴール
表題の通り、ブラウザ上で"Hello, Vue3!"です。
![スクリーンショット 2022-02-16 21.52.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2494809/913305ad-7b41-f899-441a-7a8381307435.png)
ね、簡単そうでしょ？

##環境(コマンド:バージョン）
・MacOS:11.5.2
・ruby -v:3.0.2
・Rails -: 6.1.4.6
・yarn -v:1.22.17
・node -v:17.5.0
・webpacker:5.0
・vue -v (vueのバージョン確認はコマンドライン上で、
```
$npm list vue
```
と入力すると返してくれます。といっても読者の方はまだVueをインストールしていないと思うので確認する必要もないと思いますが。）
※2022年2月現在の環境です。Rails7が既にリリースされていますが、当記事では取扱い致しません。

###ターミナル上でアプリケーション作成
まずはrails newで適当にアプリケーションを作成し、rails　serverでrailsのWelcomeページが出てくるか確認してください。

```
$rails new HogeApp
$rails s
```
###Vue3用のパッケージをインストール

```
$yarn add vue@next
$yarn add --dev -vue-loader@next @vue/compiler-sfc
```
ちなみにyarn addの@以降はバージョンを指定することができます。
nextとすることで現在の最新バージョンをインストールしてくれます。

###webpackを設定

config/webpack/environment.js内、Vueファイルに対してvue-loaderを使用するように設定します。

ついでに、Tree Shakingを有効化します。
ここに関しては私自身理解が乏しい部分がありますが、ここの設定をしておかないとVuedevtoolsがブラウザで現れなくなったり、
コンソールの中で「__VUE_OPTIONS_API__を定義しろ」と怒られてしまいます。

```config/webpack/environment.js
const { environment } = require('@rails/webpacker')
const { VueLoaderPlugin } = require('vue-loader')

environment.plugins.prepend(
     'VueLoaderPlugin',
     new VueLoaderPlugin()
)

environment.loaders.prepend('vue',{
     test: /\.vue$/,
     use: [{
         loader: 'vue-loader'
     }]
})

const { DefinePlugin } = require('webpack')
environment.plugins.prepend(
    'Define',
    new DefinePlugin({
        __VUE_OPTIONS_API__: true,
        __VUE_PROD_DEVTOOLS__: true
    })
)

module.exports = environment
```

###webpacker.ymlのextensionにvueを追加
```config/webpacker.yml
//...
extension:
  - .vue
//...
```

###"Hello, Vue3!"を表示するページの作成

```
$rails g controller hoge index
```

viewを修正

```app/views/hoge/index.html
<h1>Hoge#index</h1>
<p>Find me in app/views/Hoge/index.html.erb</p>
<%= javascript_pack_tag 'hello_vue.js' %>　
<div id="vue-app"></div>
```

※javascript_pack_tagメソッドは、パックファイルを参照するスクリプトタグを作成するために使用されます。
ここでは'hello_vue.js'というjsファイルを参照しています。
divのid要素ではvue-appを指定していますが、これは後述のhello_vue.js内にてマウントするための記述になります。

app.vueを作成

```app/javascript/app.vue
<template>
    <p>
        {{ message }}
    </p>
</template>

<script>
export default {
    data() {
        return {
            message: "Hello,Vue3"
        }
    }
}
</script>

<style scoped>
p {
    font-size: 2em;
    text-align: center;
}
</style>
```

scriptタグで囲っている箇所にご注目ください。
export defaultとありますが、これは読んで字のごとく、「デフォルト（初めから）exportしているよ」という意味です。
「そんなこと言われてもわからんわ！」と思ったそこの君。一種のおまじないだと思ってもらって構わない。
兎にも角にも、message: "Hello, Vue3！"となっている箇所が同ファイル上部分にあるtemplateタグで囲われているpタグ内に反映されるというわけです。
このapp.vue内に書いたコードはhello_vue.jsで参照、マウントされます。

```app/javascript/packs/hello_vue.js
import { createApp } from "vue";
import App from "../app.vue";

document.addEventListener("DOMContentLoaded", () => {
    const app = createApp(App);
    app.mount("#vue-app")
});
```
上の方、先ほどmessaggeを記述したapp.vueを参照しているのがわかるかと思います。
加えて、イベントリスナーの中でindex.html.erb内に記述したid要素vue-appをマウントしています。

これでブラウザ上に"Hello,Vue3!"が表示されるかと思います。

#最後に
Vueは他のフレームワークと比べて簡単だと言われがちですが、私は普通に難しいと思いました。
間違えている箇所あればご指摘くださると幸いです。喜んで訂正いたします。