SeverとClientでレンダリング結果が違う

International Components for Unicode

Reactをアイソモーフィックに実行しているのだけど、下記のようなエラーが出てた。

Warning: Text content did not match. Server: “1970-1-18 22:09” Client: “1970/1/18 22:09”

SeverとClientでレンダリング結果が微妙に違うとのこと。

new Intl.DateTimeFormat(locales, {
  year: "numeric",
  month: "numeric",
  day: "numeric",
  hour: "numeric",
  minute: "numeric"
});

該当のコード。

Node.js側のIntlオブジェクトが対応していないのかなと思いつつ、Node v8だし結構新しいしなーと思っていて、原因がわからず、しばらく放っておいた。

あとで国際化のサポートがビルドの設定ごとで違うらしいと気づいた。デフォルトのビルドでは--with-intl=small-icuというもので、部分的なサポートでしかない。それとは別にfull-icuという全サポートがあるらしく、これ入れたら、サーバーとクライアントでの差異はなくなった。

ちなみにICUとはInternational Components for Unicodeの略らしい。確かに全言語対応のデータ毎回入れてたら重いよね。

Node.jsのバージョンマネージャーはnvm使ってるんだけど、nvmインストールするときに下記のようなオプションつけるとfull-icuでビルドしたものをインストールできる。

nvm install -s v9.4.0 --with-intl=full-icu --download=all

でもこれだと毎バージョンごとにICUのデータ入れないといけないからめんどいよね。あとGAE Node.jsのインスタンスとかどこでNode.jsのビルドしてんだ?って感じなので、

後づけで言語データをインストールができるnpmがある。

NODE_ICU_DATA=node_modules/full-icu/

あとは環境変数NODE_ICU_DATAにfull-icuの言語データへのパスを設定するだけでよい。

国際化とかホント苦手だわと思ったけど、今回の場合、日付の/-が違うだけだったので、あんまり考えがめぐらなかったのが反省点。