【Angular Universal】 domino を使ってクライアントサイドのエラーを軽減する
domino とは?
サーバーサイドレンダリング( SSR ) を行う場合、当然ですがクライアントのコードをサーバーで実行する必要があります。
クライアントの処理ではサーバーサイドでは存在しない Window
や Document
といったグローバルオブジェクトを様々な場所で利用しているので、何も対策を行わないと window is not defined #830 等のエラーが発生してしまいます。
domino は、そういったオブジェクトのモックを生成してくれるライブラリです。
モックの Window
等を利用することで、クライアントサイドの処理にあまり手を加えることなく SSR を行うことが出来ます。
※ ただし、実際のプロパティとはずれている部分もあるので、domino を使ったからといってすべての処理がすんなり動くようになるわけではありません
使い方
window is not defined #830 であるように
import * as domino from 'domino';
const mockWindow = domino.createWindow(TEMPLATE);
global['window'] = mockWindow;
global['Window'] = domino.impl.Window;
global['document'] = mockWindow.document;
こんな感じで定義できます
domino を読み込む場所に注意
当初、domino はクライアントサイドでいう polyfill
のようなものだと思い、深く考えずにサーバーサイドの最初の方で読み込んでいました。
しかし、そのせいで
domino
↓
axios 依存ライブラリ
↓
axios
という順番で実行されてしまい、中途半端な Window
や Document
がグローバルに存在する環境下でサーバーサイドの処理が行われていました。
そしてたまたま、そういったオブジェクトで処理が分岐する依存ライブラリ ( axios ) にぶつかり、エラーが発生してしまいました。
よく考えれば当然ですが、domino の読み込みはなるべくレンダリング処理の直前で行うほうが良いと思います。
今回は axios でしたが、同様の処理を行っているライブラリは他にもあるのではないでしょうか…?
補足 axios のエラーについて
- http クライアントである axios に依存しているライブラリでエラーが発生
-
https://github.com/axios/axios/blob/master/lib/helpers/isURLSameOrigin.js#L41 で発生
-
domino で生成したエレメントには
pathname
が存在しないのでエラーが発生していた
-
domino で生成したエレメントには
pathname: (urlParsingNode.pathname.charAt(0) === '/') ?
utils.isStandardBrowserEnv() ?
function isStandardBrowserEnv() {
if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {
return false;
}
return (
typeof window !== 'undefined' &&
typeof document !== 'undefined'
);
}
axios ではクライアントサイドのグローバルオブジェクトを確認して、現在の環境(サーバー or クライアント)を判断し、処理を分けているようである
今回は中途半端な Window
及び Document
が存在していたため、クライアントサイドの処理が実行されエラーとなっていた
まとめ
最初にも述べましたが domino で生成できるグローバルオブジェクトは完全なものではありません。
しかし、基本的なプロパティは大体実装されているので、これを読み込むだけクライアントサイドの処理をあまり修正せずに SSR で利用することができます。
プロジェクトで使用しているライブラリによっては別途対応が必要なものもありますが、私のケースでは おおよそ流用できて便利でした ( ^ω^)
ひとり言
これからちょくちょく angular universal 系の tips を angular-universal
タグにまとめていこうかなと思います。
(´-`).。oO(ある程度溜まったらチュートリアル的な記事を作ってまとめられたら良いなぁ)
Author And Source
この問題について(【Angular Universal】 domino を使ってクライアントサイドのエラーを軽減する), 我々は、より多くの情報をここで見つけました https://qiita.com/MasanobuAkiba/items/7b0abc65631bbb999f35著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .