expressを使ってウェブアプリを開発中、views/以下のファイルを変更したときに、自動でブラウザをリロードしたいと考えた。

同じnode.js製のbrowser-sync(bs)ならできるだろうと考えて調べると、gulpを使う方法と、connect-browser-sync(cbs)というライブラリを使う方法の2つを見つけた。

それでgulpは必要ないということで、cbsを採用。

browser-syncでブラウザ自動更新 - ushumpei’s blog

このサイトを参考にして実装を始める。
簡単そうだと思いきや、めちゃくちゃハマった。3時間くらいハマった。

どうしてもbsが動いてくれない。

この方法じゃだめなのかとgulpを使って実装してみるもだめ。

どうすりゃええんじゃーということで調べてみると、stackoverflow兄貴の記事を発見

node.js - Express and BrowserSync without gulp? - Stack Overflow

とりあえず最小構成でbsとexpressを同時に動かすサンプルがあったので動かしてみると、やっぱり動かない。

GitHub - damienromito/express-sync: How to use an express server with browser-sync (without gulp)

ソースを見てみるとlistenポートを9000に変更してあったので、ufwをつかってサーバーの9000をallowにしてみる。

すると、localhost:3000 でbsのディレクトリ管理画面が開いた。

ここで、ファイヤーウォールに問題があることが発覚。

このときexpressは9000番で動作しており、bsは3000番ポートで起動していたということだろう。

その上でbsのコアサーバーのポートは何番なんだろうと調べてみると、デフォルトで3001番ポートだということが判明。

Browsersync options

3001番ポートを改めて開放してやると、expressとcbsが同時に動き始めた。

localhost:3000に接続してviews/*を編集するとちゃんとブラウザがリロードしてくれた。

おそらく、cbsはこんな構造をしているんだろうなと。

Browser syncの仕組み予想

ということで、cbsやbsが動かないとお困りの方はファイヤウォールの設定を見直しになられることをおすすめします。

nodemonと一緒に動かす場合

最後に、nodemonも一緒に動かしてあげると全部自動で更新してくれるので便利です。

まずはnodemonをインストール

npm install nodemon --save-dev

package.jsonのstartのスクリプトを下記のように書き換えます。


//package.json
start: "./node_modules/.bin/nodemon ./bin/www"

これで

npm start

をかけると、nodemon + express + browser-syncの環境が立ち上がりました。




node.jsを新しいプロジェクトに採用するにあたって、おさらい的な意味で入門書を読みかえしている。

とても良い本なので、nodejsをこれから始めようと思っている皆さんにもおすすめしたい。

この本の中のsocket.ioに関する項目について、実装してみたところ不具合が発生したので、自分の覚書として記しておきたい。

実行環境は以下の通り
sakuraVPS CentOS Linux release 7.5.1804 (Core)
nodejsのバージョンは v10.0.0
npmからインストールしたsocket.ioのバージョンはv1.7.4
クライアント側のsocket.ioはcdnよりv2.2.0

サーバー側


//io_server.js

var http = require('http');
var fs = require('fs');
var Io = require('socket.io');

var server = http.createServer(function(req,res){
  var source = fs.createReadStream('index.html');
  res.writeHead(200);
  source.pipe(res);
})

io = Io(server);
let counter=0;

io.sockets.on('connection',function(socket){
  io.emit('change',{
    count:counter+1
  });

  socket.on('join',function(){
    counter++;
    socket.broadcast.emit('change',{
      count: counter
    });
  });
  
  socket.on('disconnect',function(){
    counter--;
    socket.broadcast.emit('change',{
      count:counter
    });
  });

});

server.listen(3000);

クライアント側


<!-- index.html -->

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>chatroom</title>
</head>
<body>
<h1>現在の人数</h1>
<h2 id="counter">0人</h2>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script>

<script>
//var socket = io.connect("localhost:3000");
var socket = io.connect();

socket.on('change',function(o){
  document.getElementById("counter").innerHTML = o.count+ "人";
});

socket.on('connect',function(){
  socket.emit('join');
});

</script>
</html>

書籍では、index.htmlの16行目は
var socket = io.connect("localhost:3000");
とあるが、これだと動作しなかった。
結果、その下の行の
var socket = io.connect();
で動作することを確認したので記しておく。

ブラウザのコンソールで発生するエラーをもとにググってたどり着いたのが以下のページ

javascript - SocketIO ERR_CONNECTION_REFUSED - Stack Overflow

このページを見ることで解決できたのだけれど、socket.ioを0.9から1.3.xにアップグレードしたあとio.connectには引数を使うとエラーが起こるようになったらしい。

socket.io公式のチュートリアルにおいても同じ内容で表記してある。

ブラウザのタブを開く数(閲覧者の数)に応じて、ブラウザ内の人数の値が変化する。

スクリーンショット 2018 12 06 11 20 51




あるディレクトリの中のディレクトリ群を、全て個別のzipアーカイブにしたいと思った。

そこで

for i in `ls`; do zip -r $i.zip $i; done;

というコードを書いて実行したところ、すべてのディレクトリの中に「.zip」というファイルが出来上がってしまった。

いやいや、もう一つ上のディレクトリに、個別のディレクトリと個別のディレクトリのzipアーカイブが並んでほしかったのだけど。

何がおかしいのだろうと思って

for i in `ls` ; echo $i.zip

を実行したところ


dir1/.zip
dir2/.zip

という結果が出てきた。

つまり、ディレクトリをあらわす記号"/"の後に.zipがついていたわけです。
なるほど、自分のzshはディレクトリの名前をタイプするだけでそのディレクトリの中に入るような仕様にカスタムしているので、

cd dir1

をしていることと同様になり、その後.zipを作っているということになっていたわけです。

ということでディレクトリの末尾のスラッシュを消す方法を探したところ、以下のコマンドで達成できました。

for i in `ls` ; echo ${i%/}.zip

${i%/} %/を変数に対して付加してあげると、末尾のスラッシュを取り除いてくれるようです。

これは例えばスラッシュでなくても、i%#とすれば末尾のシャープを取り除いてくれるようですね。

結果、以下のコードを実行することで思っていたことが出来ました。

for i in `ls` ; do zip -r ${i%/}.zip $i; done;

勉強になりました。