テレビ向けにSPAアプリケーションを作るときにデバッグで困った話

通常webサイトのデバッグはブラウザのDevToolsを使い、iOSやAndroidであれば、ChromeやSafariでリモートデバッグを行います。
しかしテレビのブラウザだとDevToolsはもちろん、リモートデバッグのような機能は用意されていないのです。

Microsoft謹製のVorlon.JSなどもありますが、
とりあえずconsole.logが見れればいいので、自分でシンプルなものを作ることにしました。

nodejsには--inspectというオプションをつけて実行するとChromeのDevToolsでnodejsのデバッグができる機能があります。

これを利用して--inspectをつけてwebsocketサーバーを立ち上げ、デバッグしたいwebサイトでwebsocketクライアントのjsを追加し、
consoleオブジェクトのメソッドをコールしたときにwebsocketサーバーに内容を送るようにします。

npmパッケージとして作るのでコマンドとして実行するファイルの先頭に以下の記述を追加し実行権限を与えます。
ここで--inspectをつけるのがポイントです。

#!/usr/bin/env node --inspect  

webサーバーはexpresswebsocketにはsocket.ioを使います。
node 10系だとinspector.consoleメソッドで簡単にリモートのコンソールにメッセージを送ることができるので、
これを使ってリモートのinspectorコンソールにメッセージを送ります。

const express = require('express');  
const inspectpr = require('inspector');  
const app = express();  
・  
・  
・  
const http = require('http').Server(app);  
const io = require('socket.io')(http);  

io.on('connection', socket => {  
  socket.on('console', event => {  
    const {method, data} = event;  
    inspector.console[method](...data);  
  });  
});  

クライアント側ではconsoleオブジェクトのメソッドを別のオブジェクトに退避し、上書きをします。

const socket = io('localhost:8888');  
const consoleMethods = ['debug', 'error', 'info', 'log', 'warn', 'dir', 'table'];  
window.orgConsole = {};  

socket.on('connect', () => {  
  for (const method of consoleMethods) {  
    window.orgConsole[method] = console[method];  
    console[method] = (...data) => {  
      window.orgConsole[method].call(console, ...data);  
      socket.emit('console', {method, data});  
    }  
  }  
});  

これにより、consoleオブジェクトを使ったログ出力がwebsocketを通じてリモートのinspectorコンソールに出力されます。

出来上がったものがこちらになります。
console-log-proxy - npm

また、ChromeをInspectorクライアントとして使う場合、NIMというExtensionを使うとサーバーを起動したときに自動でコンソールが立ち上がるような設定もできるので便利です。

参考