はじめに
RailsにいよいよVuetifyを組み込み始めたが、ページ遷移をするとvuetifyのボタンが消えてしまう。ページ更新をするとボタンが表示される。そのような不具合に見舞われた。いったいなにが原因なのか。一週間ほど悩んだのちにようやくわかった。
turbolinkの問題だった。ちょっとずつ書いていく。
hello_vue.jsをのぞく
vue導入時にapp/javascript/packs/hello_vue.js
が作成された。さきの記事ではこいつを編集して、いいようにしていたが、まだここには続きがあった。
// If the project is using turbolinks, install 'vue-turbolinks':
//
// yarn add vue-turbolinks
//
// Then uncomment the code block below:
そういうわけで、
$ yarn add vue-turbolinks
を実行したのち、hello_vue.js
を以下のように変更した。
import TurbolinksAdapter from 'vue-turbolinks' //turbolinkをつかっていたので追加
import Vue from 'vue'
import Vuetify from "vuetify"; // vuetify導入のため追加
import "vuetify/dist/vuetify.min.css"; // vuetify導入のため追加
import App from '../app.vue'
Vue.use(Vuetify); // vuetify導入のため追加
const vuetify = new Vuetify(); // vuetify導入のため追加
Vue.use(TurbolinksAdapter)
document.addEventListener('turbolinks:load', () => {
const app = new Vue({
vuetify, // vuetify導入のため追加
el: '#hello',
data: {
message: "Can you say hello?"
},
components: { App }
})
})
なんとかなった。
turbolinkとはなにか
今回私を悩ませたturbolinkだが、Railsのgemfileにはちゃんと記述があった。
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
ページ遷移の速度が向上するらしい。もうちょっとread.meを読んでみよう。
https://github.com/turbolinks/turbolinks
Turbolinks intercepts all clicks on
<a href>
links to the same domain. When you click an eligible link, Turbolinks prevents the browser from following it. Instead, Turbolinks changes the browser’s URL using the History API, requests the new page using XMLHttpRequest, and then renders the HTML response.
そういうことらしい。turbolinksはaタグのリンクをクリックすると、その遷移をブロックするらしい。そして、その代わりにHistory APIを利用してHTMLレスポンスを返す。History APIを使ってやるほうがはやくなるらしいね。
しかし、それがなぜvuetifyに悪影響を及ぼしているのかがわからなかった。
こんなときは答えのほうからみていくと話が早い。解決策としてvueが提示しているvue-turbolinks
を覗こう。
vue-turbolinksとは
vue-turbolinks is a package to allow you to easily add Vue.js components to your Turbolinks & Hotwire powered apps.
簡単に加えられるぜ!ということらしい。(Hotwireってなんだろ。まぁいいか)
index.js
をみると思いの外シンプルだった。
//略
const Mixin = {
beforeMount: function() {
// If this is the root component, we want to cache the original element contents to replace later
// We don't care about sub-components, just the root
if (this === this.$root && this.$el) {
handleVueDestruction(this);
// cache original element
this.$cachedHTML = this.$el.outerHTML;
// register root hook to restore original element on destroy
this.$once('hook:destroyed', function() {
this.$el.outerHTML = this.$cachedHTML
});
}
}
};
//略
vueがmountする前にこれらのfunctionを実行していた。キャッシュされたHTMLの内容を、現在のHTMLに置き換えていた。それだけだった。
なんとなくわかった。torbolinksはキャッシュからリンクをひっぱってくるが、本来のvueはそれをしていなかったのだ。だからvue-turbolinkを使って、キャッシュのところにHTMLを入れ込んでいたのだ。
おわりに
vueはたのしい。vuetifyはたのしい。
これからも、勉強しながら詰まったところを書いていこう。