VagrantのUbuntu環境で、Play Frameworkを使ったアプリの開発をしたいと思い試しています。
Playはソースコードが更新されると、自動的にコンパイルが走ってくれるauto-reloadingという機能が便利です。この機能をVagrantで試していて気がついたのですが、どうやら共有フォルダにあるソースコードは更新されてても、自動でコンパイルがかからないようです。controllersもviewsもどちらも変更してみましたが、やはりだめです。
そんなことはないんじゃないか?と思い、共有フォルダではないフォルダで試してみたら、ちゃんとreloadされていたので、原因は共有フォルダにあることが分かりました。
PlayKeys.playWatchServiceを試す → ダメ
いろいろググっていたら「Play 2.3.2 auto reload is not working on shared folder · Issue #3246 · playframework/playframework」というissueを見つけました。
PlayはOSレベルの機能でファイルの変更を検知しているとのことで、NFSなどはOSが対応していないので検知できないそうです。ここで提案されていた解決策は、次のコードをbuild.sbt
に書くことです。
PlayKeys.playWatchService := play.sbtplugin.run.PlayWatchService.sbt(pollInterval.value)
これを追加すると500msの間隔で、ファイルをポーリングして検知できるようになるそうです。
これをbuild.sbtの最後にコピペして、念のためactivatorを終了して起動しなおし、activatorのコンソールでrun
を実行しました。が、やはり更新を検出できないようです。
NFSにしてみる
さきほどのissueにリンクしているissue「Play 2.3.x not detecting changes to static resources in shared folder · Issue #4208 · playframework/playframework」に気づきました。こちらの課題を報告している方が、Vagrantの共有フォルダの設定がNFSで解決したそうなので、NFSにしてみます。
Vagrantfileに次を追記して
config.vm.synced_folder ".", "/vagrant", type: "nfs"
Vagrantを起動しなおします。
vagrant reload
ちなみに、Vagrantfile全体としてはこんなふうになっています。
# -*- mode: ruby -*-
# vi: set ft=ruby :
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "shouldbee/ubuntu-14.04-with-docker"
config.vm.box_version = "0.5"
config.vm.synced_folder ".", "/vagrant", type: "nfs"
host = RbConfig::CONFIG['host_os']
case host
when /darwin/ # mac
cpus = `sysctl -n hw.ncpu`.to_i
when /linux/
cpus = `nproc`.to_i
else
cpus = 2
end
config.vm.provider "vmware_fusion" do |v|
v.vmx["memsize"] = "512"
v.vmx["numvcpus"] = cpus
end
end
起動したら、activatorを実行して、
vagrant ssh
./activator
run
ソースコードを変更してみます。が、だめでした。
Vagrantの共有フォルダの設定を変更してみます。
config.vm.synced_folder ".", "/vagrant", type: "nfs", mount_options: ["lookupcache=none"]
Vagrantを再起動して、試します。
vagrant reload
vagrant ssh
./activator
run
やはり、ソースコードを更新しても検知されませんでした。
~run
→ 遅い
今度はPlayのauto-reloadingを使うのは諦めて、~run
してみることにしました。そうしたところ、コンパイルは自動的に行われるようになりましたが、Playで起動しているサーバには反映されないようで、一旦Ctrl+D
を押してはじめてサーバが再起動して反映されるようでした。これでも、使えないことはないですが、Ctrl+D
を押さないと行けないのと、起動の処理自体に5〜10秒かかるが繰り返しになってくるとストレスになりそうです。
情報求む
うまい解決策があれば教えてもられると嬉しいです
[2015-05-25]追記
rsyncを試してみた
Vagrantのrsyncファイル共有機能を使って、Playのプロジェクトを同期するのを試してみました。Vagrantfileには同期したいプロジェクトの指定します。
config.vm.synced_folder ".", "/new-ui", type: "rsync",
rsync__exclude: [
"/.idea/",
"/.idea_modules/",
"/project/project/",
"/project/target/",
"/target/",
]
これを設定したら、vagrant reload
で再起動します。その後、同期が常に行われるように、もうひとつターミナルを開いてvagrant rsync-auto
を実行しておきます。
rsyncなら普通のファイルシステムにソースコードを配置できるので、予想通りPlayのauto-reloadingが動きました。が、VMの性能の壁があり、僕の環境では、ホストマシンのMacでは1秒程度でリロードが終わるのに対して、rsync先のゲストマシンでは20〜30秒程度かかってしまうようです。