箱のプログラミング日記。

渋谷の自社開発企業でRails書いてます。

Uglifier::Error: Unexpected character '`' 【Railsデプロイエラー】

f:id:y_hakoiri:20191102134313j:plain

レビュー通って意気揚々とmerge、デプロイ!!...と思ったらエラーでこけた話。

Uglifier::Error: Unexpected character '`'

jsをかなりいじったPRだったのですぐに原因が想定できたのだけど、エラー文の通り。

期待しない文字「`」が含まれてるからエラーですよとのこと。

Uglifierとは

UglifierというのはRailsに標準で含まれているJS軽量化のライブラリ。

https://github.com/lautis/uglifier

Railsではデプロイする際にassets配下のファイルを全てひとまとめにして読み込みを早くしてくれるのだけど、

そのプリコンパイルの段階でJSのコメントやら空白やら改行やらの無駄な部分をカットしてくれるライブラリらしい。

エラーの原因を修正

Uglifierは標準ではES5の文法規格までしかサポートしていないようで、

ES5ではテンプレートリテラル(`)に対応していないので今回エラーが起こっていた模様。

なのでRailsで使う際には

config/environments/production.rb

config.assets.js_compressor = :uglifier

これを

config.assets.js_compressor = Uglifier.new(harmony: true)

こうしてくださいね、と公式に書いてある。

ちなみに環境ごとにファイルがあるので、stagingとかtestとか他にもいくつかファイルがある場合はそれぞれ書き換える必要がある。

ローカルで動かしてた時にこのエラーが起こらなかったのは、development.rbには元々config.assets.js_compressor = :uglifierの記述がないからなんですね。

ググったところここの部分を書き換えではなくコメントアウトしてしまっている記事がちらほらあったけど、

そうすると肝心な軽量化をしてくれないので微妙だと思います。

ただし

多分↑の修正を行えばデプロイ自体はすんなりいくと思うのだけど、

デプロイを突破してもそもそもJSのテンプレートリテラルはIE11が対応していないらしい。。なんやねん。

ということで、uglifierの設定を書き換えるのはやめて、テンプレートリテラルを使っていた部分を文字列連結で書き換える作業を結局行いました。

Babelを使ってコンパイルする方法とかも見かけたけど、影響範囲が大きそうなのでとりあえずの応急措置...

追記:またエラー出た

デプロイしてみたらまた違うエラーが出た。

rake aborted!
Uglifier::Error: Name expected

またプリコンパイルのところでコケてる。今度は何だろうよく分からない

とりあえずエラー文でググったら「ローカルでもプリコンパイルしてログ見てみろ」って書いてあるので

bundle exec rake assets:precompile

やってみたけど、特に何も起こらずyarnファイルが出来上がった

yarn.lock

# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1

特に意味はなさそう。

、、と思ったらローカルにuglifier書いてなかったー。凡ミス。

config/environments/development.rb

config.assets.js_compressor = :uglifier

この状態でもう一度bundle exec rake assets:precompileしてみたら、今度はデプロイ時と同じエラーが起こった。けど結局よく分からず

解決:やっぱりオプションを追加してみた

ものは試しというか、やっぱりuglifierの公式に「Railsではharmony: trueオプション追加してね」って書いてあるので、やっぱここなのかなぁと思いやってみたら無事デプロイできました。

直接的な原因が分からないからちょっと気持ち悪いけど、とりあえず解決したから良いかな。。

まとめ

  • uglifierはJS軽量化のRailsデフォルトで組み込まれているパッケージ
  • だけど使うときはharmony: trueオプションを書き換える必要がありそう
  • テンプレートリテラルはIE11に対応していないので文字列を純粋に結合してくのが良さそう

参考

GitHub - lautis/uglifier: Ruby wrapper for UglifyJS JavaScript compressor.

RailsでES6の機能を使うとプリコンパイルが通らない(Uglifierがエラーを吐く)問題 - Qiita

ruby on rails - heroku Uglifier::Error: Name expected - Stack Overflow