angular fullstackでgulp serveすると、ファイル監視が働いて、ソース編集をトリガーに色々とやってくれるんですが、nfsをマウントしたフォルダ内のファイルを、サーバ側で変更した時にうまいこと捕捉できないようです。

構成は

・Mac(nfsサーバ  + ソースファイル )

・Vagrant + ubuntu/xenial64

config.vm.synced_folder “src/”, home_dir + “/src”, type: “nfs”

でmacとubuntuでファイルを共有します。

ソースの編集はmac上のエディタ(sublime)で、gulp serveはubuntu上で実行します。

gulp serveではgulp-watchというプラグインでファイル監視をしており、さらに内部的にはchokidarなるライブラリを使っているようです。

さらにさらに、chokidarはMac上で実行された場合はfsevents、それ以外はnodejsのfs.watch系の機能を使うようです。

んで、fs.watchにはこんな悲しい記述が。。。

If the underlying functionality is not available for some reason, then fs.watch will not be able to function. For example, watching files or directories can be unreliable, and in some cases impossible, on network file systems (NFS, SMB, etc), or host file systems when using virtualization software such as Vagrant, Docker, etc.

You can still use fs.watchFile, which uses stat polling, but it is slower and less reliable.

要は、ポーリングしろということですな。

chokidarは usePolling:true でポーリングモードになるようです。

gulp-watchに渡すオプションはそのままchokidarに渡るようなので、usePolling:trueを使うようにgulpfile.babel.jsの’watch’タスクを書き換えます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
gulp.task('watch', () => {
    var testFiles = _.union(paths.client.test, paths.server.test.unit, paths.server.test.integration);

    plugins.livereload.listen();
    var wc_opt={usePolling:true};   //追加!
    plugins.watch(paths.client.styles, wc_opt , () => {  //['inject:scss'] //wc_optwを第二引数に
        gulp.src(paths.client.mainStyle)
            .pipe(plugins.plumber())
            .pipe(styles())
            .pipe(gulp.dest('.tmp/app'))
            .pipe(plugins.livereload());
    });

    plugins.watch(paths.client.views, wc_opt) //wc_optwを第二引数に
        .pipe(plugins.plumber())
        .pipe(plugins.livereload());

    plugins.watch(paths.client.scripts, wc_opt) //['inject:js'] //wc_optwを第二引数に
        .pipe(plugins.plumber())
        .pipe(transpileClient())
        .pipe(gulp.dest('.tmp'))
        .pipe(plugins.livereload());

    plugins.watch(_.union(paths.server.scripts, testFiles), wc_opt) //wc_optwを第二引数に
        .pipe(plugins.plumber())
        .pipe(lintServerScripts())
        .pipe(plugins.livereload());

    gulp.watch('bower.json', ['wiredep:client']);
});

一応動いております。

CPU負荷もそれほどでもないし、開発時にしか使わないんで、これでおkとしよう。

あんま関係ないけどlivereloadがうまく動かん。Browsersyncに差し替えるかも。