Better-express-error
express開発時にエラーが発生した場合、通常はエラーページに直接表示されるか、プロダクション環境では404ページや500ページにリダイレクトされます。
これは特に言及するほど価値がないかもしれませんが、実際にこのようなページを見たとき、うれしく思いますか?
Ruby On Railsの開発者であれば、better_errorsやRailsのエラートレースページをデバッグに使用したことがあるかもしれません。
しかし、expressではまだbetter errorのような機能を持つパッケージを見つけることができず、いつもこのような見づらいエラーメッセージを見るしかありません。
そこで、自分でこの問題を解決するためのシンプルなミドルウェアを作成しました。実際には、これはbetter_errorsのexpressでの実装です。
エラーメッセージの分析
TypeError: range out of bound. Please check http://kjj6198.github.io for more information.
at app.get (/Users/kalan/code/express-error/server/app.js:17:9)
at Layer.handle [as handle_request] (/Users/kalan/code/express-error/node_modules/express/lib/router/layer.js:95:5)
at next (/Users/kalan/code/express-error/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/Users/kalan/code/express-error/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/Users/kalan/code/express-error/node_modules/express/lib/router/layer.js:95:5)
at /Users/kalan/code/express-error/node_modules/express/lib/router/index.js:281:22
at Function.process_params (/Users/kalan/code/express-error/node_modules/express/lib/router/index.js:335:12)
at next (/Users/kalan/code/express-error/node_modules/express/lib/router/index.js:275:10)
at jsonParser (/Users/kalan/code/express-error/node_modules/body-parser/lib/types/json.js:109:7)
at Layer.handle [as handle_request] (/Users/kalan/code/express-error/node_modules/express/lib/router/layer.js:95:5)
注意深く観察すると、エラーメッセージの形式は非常に整然としていることがわかります。まず、最初の行にはエラー名とメッセージが表示されます。これが通常、最も重要な情報です。2行目以降はスタックトレースの呼び出しです。at ...は特定の関数の呼び出しであり、括弧内にはファイル名、行番号、列の情報が表示されます。
エラーメッセージを詳細に分析した後、純粋なテキストをより有用な情報に変換することができます。したがって、split('\n')
を使用して文字列を分割し、正規表現を使用して文字列に基づいてファイル名と行番号の情報に分割することができます。
エラーの表示
最初の行のエラーメッセージは通常、最も重要な情報です。なぜなら、エラーが発生したコードがそこにあるからです。したがって、最初の行のエラーメッセージを目立つ場所に配置し、ハイライトします。
2行目以降のエラーメッセージは、ファイル名、行番号、呼び出された関数を色とサイズで表示します。
先程の一連の黒いテキストよりも、このようにシンプルに整理することで、開発者は何が起こっているのかを一目で把握できます。
ファイルの表示
ただし、エラーメッセージを表示するだけでなく、対応するファイルの内容や関連するコンテキストも表示したいと考えています。したがって、右側の領域を使用して、エラーメッセージに含まれるファイル名と行番号に基づいて対応するファイルの内容を表示します。
Node.jsでは、fs.readFileSync
を使用するだけで十分です。
function(filename, line, row) {
const content = fs.readFileSync(filename);
content.toString()
.split('\n')
.slice(line - 5, line + 5)
.map(content => `<span>${content}</span>`)
.join('\n');
}
ここでは、非常にシンプルな方法で、前後5行を表示しています。よりスマートな方法としては、ASTのようなテクニックを使用して、対応する関数のコンテンツのみを表示することができます。しかし、今は前後5行のコードを直接表示するだけで十分です。
調整と修正を行うと、おおよそ以下のようになります:
シンプルなハイライトにより、開発者はエラーが発生した場所をすぐに確認できます。
REPL
エラーを表示するだけでなく、このページで簡単なコードを入力し、問題点を確認した後、実際のコードを修正することができるようにしたいと考えています。
Node.jsでは、VMモジュールを使用して、指定されたコードをV8の仮想マシンコンテキストで実行することができます。このモジュールを使用すると、REPLのような機能を実現できます!
const debugContext = vm.createContext({
request: req,
response: res,
util: require("util"),
Buffer: require("buffer").Buffer,
stream: require("stream"),
console: {
log: util.format,
},
clear: "",
})
公開したい変数をコンテキストに渡し、フロントエンドのコードをPOSTで読み取ることで、簡単にデバッグの効果を得ることができます。
(これにはさらなる調整が必要です)
すべてを統合!
すべてを統合すると、おおよそこのようなページになります。
純粋なテキストよりも、ページのスタイルを調整し、REPLの機能を実装するために少し手間がかかりましたが、デバッグのフローがよりスムーズになりました。
結論
詳細な実装は、このリポジトリにあります。近いうちに実装をミドルウェア形式に変更して、より使いやすくする予定です。また、レイアウトやコードのハイライトの部分を改善し、フローと画面全体をよりスムーズにするために取り組んでいきます。ただし、それがいつになるかはわかりません(笑)
さまざまな提案があれば、Issueを提出してください。