Posted at
ElmDay 25

elm-webpack-loader のエラーに色を付ける


elm-webpack-loader のエラー脱色問題

elm make コマンド一つでバンドルまでしてくれるんだから webpack とか要らないよね?と思いきや、なんやかんやで webpack が必要になってしまうと elm-webpack-loader とかを使うことになります。

しかしここで問題が。

Elm の親切なコンパイルエラーが...真っ赤!?

で、でも create-elm-app を使うとちゃんと色がほら。ん?

https://github.com/halfzebra/create-elm-app/blob/master/scripts/utils/formatElmCompilerErrors.js

なんということでしょう。自前で色をつけています。

そして残念ながら、ここの部分のコードはユーティライズされていません。


重要な部分を切り出す

というわけで、formatElmCompilerErrors.js から不要な部分を全て削ぎ落として本質的な部分だけを抜き出してみました。ざっくりこうです。

const chalk = require("chalk");

const ctx = new chalk.constructor({ enabled: true });
const error = ctx.bold.red;
const filename = ctx.cyan;

function stripRedundantInfo(error) {
console.log(error);
return (
error
// .replace(/Module build failed.*\nError.*\n/gm, "")
.replace(/Error: Compiler process exited with.*\n/gm, "")
.replace(/\[=+\]\s-\s\d\s\/\s\d[\r\n\s]?/gm, "\n")
);
}

module.exports = function formatWebpackMessages(messages) {
const errors = messages.errors;
const warnings = messages.warnings;
return errors.length > 0
? {
errors: errors
.map(x =>
x
// .replace(/(--\s[A-Z\s]+-+\s.*\.elm\r?\n)/g, filename("$1"))
.replace(/(--\s[A-Z\s]+-+\s.*\.elm\r?\n)/g, filename("\r$1"))
.replace(/(\n\s*)(\^+)/g, "$1" + error("$2"))
.replace(/(\d+)(\|>)/g, "$1" + error("$2"))
)
.map(stripRedundantInfo),
warnings: warnings
}
: messages;
};

みんな大好き(?) chalk を使っていますね。

コメントアウト部分は、筆者環境で表示が崩れていたのでそれぞれ一つ下のコードで修正しています。

次は、それを使う側のスクリプトです。

const webpack = require("webpack");

const chalk = require("chalk");
const formatElmCompilerErrors = require("./formatElmCompilerErrors");
const formatWebpackMessages = require("react-dev-utils/formatWebpackMessages");
const config = { "🎃👽🧠🧙‍♂️🧜‍♀️" }
const compiler = webpack(config);
compiler.watch(
{
aggregateTimeout: 300,
},
(err, stats) => {
const messages = formatElmCompilerErrors(
formatWebpackMessages(stats.toJson({}, true))
);
const isSuccessful = !messages.errors.length && !messages.warnings.length;
if (isSuccessful) {
console.log(chalk.green("Compiled successfully!"));
console.log();
}
if (messages.errors.length) {
console.log(chalk.red("Failed to compile.\n"));
console.log(messages.errors.join("\n\n"));
return;
}
if (messages.warnings.length) {
console.log(chalk.yellow("Compiled with warnings.\n"));
console.log(messages.warnings.join("\n\n"));
}
}
);

module.exports = config ではなく、 compiler = webpack(config) を使う必要があります。あとはなんかゴニョゴニョしているうちにできます。

とりあえず watch を使ってみましたが、 dev server とか使いたい人はさらにゴニョゴニョしてください。