Vue3、Rails7系を使って、何かアプリを作ってみたいなぁと思い、環境構築の段階で
学んだことを備忘録として残そうと思いました。
環境
ruby 3.1.0
Rails 7.0.4
vue@3.2.41
railsの初期化
railsの初期化(アプリ作成)
raiils new sample_app
vueの初期化
次にvueを導入していくが、いきなりつまりポイント
railsの標準に搭載されているwebpackerでvueを導入していくつもりが・・・
rails webpacker:install: vue
=> Don't know how to build task 'webpacker:install:vue'
コマンドが使えない・・・
曰く rails7系 では、vueのインストールコマンドがなくなっているっぽい。
というか、引退宣言がされており、そもそもRails7系では非推奨になっている...。
webpacker
のコマンドを確認したところ、確かにwebpacker:install:vue
は存在しない。
なんてこった・・・
rails -T | grep webpacker
Ruby on Rails 7, importmap and VueJS 3, no more webpacker を参考にさせていただいたところrails7系
では、webpacker
ではなく、importmap
という仕組みを使ってフロント側(vue
、javascript
とか)の実装を行えるそう。
公式ドキュメントにも書かれている通り、インポートマップはインポートするファイルの場所をブラウザに教えることができるそう。
ただ、ブラウザのバージョン規定によるとインポートマップに対応しているブラウザも結構多い見たいです。そこで、
rails7系では、大多数のブラウザで使用されている ES Module Shims を使用することで、ある程度のブラウザには対応できるようにしているそうです。
※ IE には救いがないようだ・・・
使い方はRails 7: importmap-rails gem README(翻訳)を参考にしながら進めていきます。
Gemfile
に以下を追記して、bundle:install
gem 'importmap-rails'
そうするとconfig/importmap.rb
やapp/javascript/application.js.
などのファイルが生成されます。
Vueのインストール方法
次にVueのインストールについてですが公式ドキュメント ES モジュール ビルドの使用を参考にしながら進めていきました。
ところで、ESモジュールってなに?
色々な記事を読むたびに出てくるESモジュールとはなんぞや。
以下の記事を参考に理解を深めていく
JavaScriptでモジュールを使う時代
ES Modulesとは
ESモジュールとは、「ES2015で策定されたJSファイルから別のJSファイルを読み込む仕組み」
ES2015
とはJavaScript
の標準仕様のことで、いわゆるバージョンのこと。
ブラウザの世界では、
JSファイル
を読み込むためにはscript
タグを利用するが、
ES Modules
が実装されている環境では、
・import
文を利用することで、外部ファイルのJSファイルを読み込むことができる。
・外部ファイルのJSファイル
ではexport宣言
されたものが他のJSファイル
から読み込まれる。
ほぇー
何気なしに使ってたimport文
について知れて感激
インストール方法
Vue.js を使う場合、CDN を利用するのが一番簡単そうです (下記)。
<script type="module">
import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
</script>
しかし、ネットに繋がっていない場合や、サーバーが落ちた時に使用できなくなるデメリットが
あるのでローカルにインストールして、そこから読み込む方法をとりました。
以下--download
コマンドでvender/javascript
ディレクトリにダウンロードします。
./bin/importmap pin "vue/dist/vue.esm-browser.js" --download
次に、先ほど生成したconfig/importmap.rb
に以下を追記
ついでにpin "application", preload: true
と
pin_all_from "app/javascript/controllers", under: "controllers"
も追加します。
pin "application", preload: true # application.js を読み込みたい
pin "vue", to: "vue--dist--vue.esm-browser.js.js" # @3.2.41
# app/javascript/controllers 配下を読み込みたい
pin_all_from "app/javascript/controllers", under: "controllers"
これで「vender
フォルダにあるvue--dist--vue.esm-browser.js.js
ファイルをvue
というパッケージ名として読み込む」という意味になり、import Vue from "vue"
として書けるようになります。
次にconfig/importmap.rb
を読み込めるように
layout
ファイルにjavascript_importmap_tags
を追記します。
<!DOCTYPE html>
<html>
<head>
<title>CodeSnippet</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
<!--以下を追加-->
<%= javascript_importmap_tags %>
<!--controllers/application 配下を読み込む-->
<%= javascript_import_module_tag 'controllers/application' %>
</head>
<body id="app">
<%= yield %>
</body>
</html>
Hello Vue を表示させてみる
routes.rb
に以下を追加
Rails.application.routes.draw do
root to: 'home#index'
end
app/controllers/home_controller.rb
に以下を追加
class HomeController < ApplicationController
def index; end
end
view/home/index.html.erb
に以下を追加
<div>
{{ text }}
</div>
app/javascript/controllers/application.js
に以下を追加
import * as Vue from "vue";
const App = Vue.createApp({
data(){
return {
text: 'Hello Vue'
}
},
})
App.mount("#app");
ではrails s
でサーバーを立ち上げてlocalhost:3000
にアクセスすると、以下の表示が見られます。DOM上に一瞬 {{ text }}
が表示された後、id="app"
にアタッチし、文字列を置き換えているのがわかります。
importmap
がhead
内に展開され、vue
がマッピングされた場所からインポートされていることが分かりました。webpacker
だとアセットコンパイルによってJS
ファイルを一つのファイルにギュッと圧縮してからブラウザに教えているところを、importmap
では、import
を使って、使用するファイルを一つずつブラウザに教えているようです。
結局 importmap で何が嬉しくなったのか
JSのビルドがなくなる
例えば、Webpackerを使用した場合、複数のJS
ファイルを1つの大きなJS
にまとめているため、複数JS
ファイルの内、1つでも変更があると、出来上がる大きなJS
も変わってきます。つまり、JSファイルをちょろっと変更しただけなのに、1から作り直すため時間が掛かってしまいました。
一方、importmapを使用した場合、JS
ファイルを個別で読み込んでいます。つまり、変更のないファイルはキャッシュを利用し、変更のあったファイルだけ読み込むので、効率的。
importmapを導入して困りそうなこと
・ブラウザのバージョンが低いと使用できない可能性がある。
・IEは100%使用できない
最後に
こうして振り返るとそんなに難しいことはやっておらず、なんなら Ruby on Rails 7, importmap and VueJS 3, no more webpacker に必要なことが全部書いてあるのも拘らず、変な回り道をして、それなりの時間がかかってしまいました。
ほんと、環境構築をサクッとこなしてしまう方々はすごいなぁと感じます。