ゆとり日記

心にゆとりを持って生きたいプログラマーの雑記です。気が向いたら書きます。

遅延読み込みの落とし穴を色々踏んだ話

フロントエンドカンファレンス福岡のCFPに残念ながら漏れてしまったので、発表しようと思っていた話を簡単にブログに纏めました。

と思っていたら前夜祭で話せることになったので、ここに書いた話をベースに話す予定です。

fec-fukuoka.connpass.com

概要

  • 「ユーザの体感速度を上げるために遅延読み込みを実装したが、実はユーザー体験を損なっていた。」
  • 「一見早くなったように見えて安心していたら、SEOにネガティブな要因を引き起こしていた。」

試行錯誤して実装した遅延読み込みが実はクローラーやユーザに優しくなかった。簡潔に言うとそんな話です。

今回は僕が実際にやってしまった体験談を踏まえつつ、反省点や対策を述べていきたいと思います。

前置き

自分が普段開発しているサービスがSingle Page Application(SPA)ではないので、SPAに関わる話はほとんど出てきません。また、クローラーに関する話には不確実な部分があります。100%失敗するパターンから50%失敗するパターンまで持ってこれた、くらいの話だと思って読んでください。

なお、遅延読み込みの実装にはIntersection Observerを用いており、ここでいう遅延読み込みでは画像だけに留まらず、他の要素を動的に生成しています。

遅延読み込みがユーザ体験を悪くするケース

よかれと思ってやったことがユーザ体験にネガティブな影響を与えることがあるという話です。

実際に実装が反映されていたページの一例がこちらです。初期表示時のカードUIパーツの表示数を少なくし、初期表示を少しでも早めるのが目的でした。

1ページに表示されるパーツ数は20個ですが、ブラウザのファーストビューに収まるのはPCでも2個だったので、初期表示には2個だけ表示する。減らした分(残りの18個)をページ表示後にAPIから取得し、JavaScriptでHTMLを生成して差し込む。このようなフローを踏んでいました。

という流れを踏んでいました。

やらかしたこと

ページ内要素を遅延読み込みしたことで、ブラウザバックで戻ってきた時にページの表示位置がズレるというケースです。

  • 上で例に挙げたページから、次のページに遷移する。
  • 遷移先からブラウザバックで戻る。
  • 戻った先のページで要素の遅延読み込みが始まる。
  • 読みこみが終わると、ページの構造が変化するのでスクロール位置がズレてしまう。

こういった事が起きていました。

このケースへの対策案

対策としては2つ考えられました。

1つめはブラウザバック時は遅延読み込みをしないこと。以前SPAを開発していた時はこのアプローチで対策を打ちましたが、今回はあSPAではないので同じ対策が使えず、別の対策を考えることにしました。

そこで考えた2つめは遅延読み込みを行う箇所にダミーのカードUIを配置しておき、スクロール位置のズレを防ぐというものです。

  • ダミーのカードUIを予め配置しておく。
  • 遅延読み込みが完了したら、ダミー要素の後ろに本来表示したい要素を差し込む。
  • ダミーUIを消す。

という流れです。このアプローチは概ね上手くいったのですが、この対策も完璧ではありませんでした。APIのレスポンスを見るまでは表示できる要素の個数が分からないので、予め配置しておくダミー要素の個数を必要に応じて変えることが出来ないのです。

また、DOMの構造を変えるタイミングが増えるので、ブラウザのリフローを誘発してしまう側面もあります。

SEOにネガティブな要因を引き起こすケース

遅延読み込みしたHTML要素がクローラーに認識されてなかった、という話です。体験談を交えつつ説明していきたいと思います。

やらかしたこと

遅延読み込みに時間がかかりすぎると、要素の表示が完了する前にクローラーが帰ってしまい、ページが正常にインデックスされない場合があります。ある程度の時間は待ってくれるようですが、待ってくれる時間がどの程度なのかは明言されていません。そのため、実際にやってみないと上手くいくかどうかは判断出来ないのです。

今回、僕がプロダクトで試した際も上手くいっているページといっていないページが存在していました。

ちなみに、実装した処理が正しく機能するかどうかは事前にpupperterでテストが可能です。 参照リンク: https://developers.google.com/search/docs/guides/lazy-loading

これが理由で遅延読み込みはひとまず止める方針に倒しました。

反省と振り返り

今回はプロダクト全体に実装してしまったのですが、今思うとチャレンジし過ぎだったなと思っています。テスト実装を試すページを絞っておけば、悪影響を最小限に留めておけました。

一部のページに絞って実装を試していたので、影響を大きくすることを抑えられたのは不幸中の幸いでした。元に戻すことを想定して戻しやすい実装にしていたことも手伝って、止める時に素早く戻せたのも良かったです。

まとめ

ページの一部分を遅延読み込みするというだけの話ではありますが、考慮しなければいけないことが案外多いことがわかりました。良かれと思ってやった事が良い結果に結びつくとは限らないという教訓ですね。今後も素早く実装して素早く検証するサイクルを繰り返し、問題解決につなげたいと思います。

僕と同じ轍を踏む人が出ないことを祈ります。

社内ISUCONで得たもの

会社でやった社内ISUCONに参加して、得るものをが色々あったので書きます。

社内でやったISUCONの内容について

以下のような変則的ルールでやりました。

  • 問題は[ISUCON8を使用。(前日まではISUCON9を使用する予定でしたが、当日に変更)
  • 問題自体を事前に見て準備するのOK。
  • 予選突破者のブログを見て真似したりするのはNG。
  • エンジニア8人が3つのグループに分かれて競う。
    • 社内に2人しかいないフロントエンドエンジニアは同じチームにならないようにするなど、得意分野が同じ人間が集中しないようにはなっていた。
  • 使える時間は4時間。
  • コードをAlibaba Cloudに置き、終了時点のスコアで勝敗を決める。
  • その他レギュレーションはISUCON公式に準拠。

ISUCONが開催された理由

「社内エンジニアのトラブルシューティング力を磨く」

主な目的はこれだと思っています。普段触らない領域(僕にとっては「デプロイの仕組み」や「ミドルウェアの使いどころ」など)を触るという目的も勿論あると思いますが。 開催を決めたCTOの考えと僕の解釈が混じっていますが、概ね合っているはず。

その背景を説明します。

弊社にはエンジニアが8人いて、以下のような内訳になっています。

  • CTO : インフラに強い
  • プロダクトオーナー : インフラに強い
  • サーバーサイド方面に強い人 : 4人
  • フロントエンド方面に強い人 : 2人(僕はここ)

プロダクトオーナーが開発以外の業務で多忙だったり、CTOのトラブルシューティング力が高いことも手伝い、障害の対応がCTO任せになっているという現状があります。任せきりになってしまった結果、他の人間のトラブルシューティング力が上がらない。でも、障害本番にいきなり投入するのもリスクが高いです。

また、アプリケーションエラーの解消(エラーの通知はSlackに通知するようにしています)も特定の人だけがやる状況が続いてもいました。

そこでISUCONでトラブルシューティングの経験を積んで、普段のトラブルシューティングに活かすとっかかりを掴もうという話になりました。

ISUCONをやった感想

4時間色々ともがきましたが、自分の無力さを味わう苦い思い出になりました(このブログもハイネケンを飲みながら書いています

  • 環境構築からつまづく。
  • 同僚にdockerで動く環境を作ってもらうも、ベンチマークが上手く動かない。
  • 監視ツールの使い方が分からなくて困惑する。
  • チーム内の作業分担が上手く出来なくて、バタつく隙間時間が生まれる。
  • ボトルネックのあたりを付けるのが大きく遅れた。DBとPHPのどっちに注力するかを決めるべきだった。
  • コード上のボトルネックを見つけるも、対応策を考えるのに時間がかかってしまった。

傍から見たら何をやっているのかって感じかもしれませんが、こういう状況でした。

ISUCONから得たもの

  • 時間の使い方をより意識する必要があった。
    • 4時間しかないので、やることを絞らないと何も出来ずに終わる。
  • Goのビルドツールだったり、H2O だったりと自分が知らなかったものを知れた。
  • ansibleのようなデプロイツールにはもっと慣れた方が良い。
  • 時にはダイナミックなアプローチが必要だと感じた。
    • ボトルネックになっているクエリがあるなら、テーブルの構成から見直して改善するようなアプローチは想像出来ていなかった。
  • 疑似体験とはいえ、時間制限を設けてISUCONの問題に取り組めたのは良い経験になった。
    • 実際にやるまでは、ISUCONがどういうものなのかを肌で感じられていなかった。
  • 問題の実装を読んでいくのは勉強になる。
    • ほぼ実戦と言えるアプリケーションコードを読める機会は多くないので尚の事。

まとめ

色々書きましたが、来年のISUCONに挑戦する熱意が湧くくらいには刺激的な経験ができてよかったです。 自分の力不足を思い知らされたので、そこは地道にやっていこうと思います。

株式会社オミカレに入社しました!

所謂、退職エントリーであり、入社エントリーです。最終出社日から一ヶ月位経ってしまって今更感がありますが一応。

  • From: 株式会社リブセンス
  • To: 株式会社オミカレ

11月末で有給消化が終わり、今月からは株式会社オミカレで働いていて、主軸サービスであるオミカレの開発を担当しています。フロントエンドに軸足を置いたWebアプリケーションエンジニアとして、事業に貢献していくつもりです。

転職した理由

社長は信頼出来る人物で、CTOは最高で、一緒に働くメンバーは熱い思いを持っている。要するに人間的な部分に惹かれた事が大きかったです。

更に言うと、僕自身が社会的に意味のあるサービスを創っていきたいと思っていて、オミカレがその拘りにマッチしているのも理由の一つと言えます。

前職を辞めた理由

現職からオファーを受けたのは夏頃でしたが、その時はオファーを一度断っていました。当時、仕事へのモチベーションが落ちてはいましたが、前職でやれる事はまだあると自分では思っていましたし、尊敬できる人達も多かったです。その状況で悩んだ結果、当時はオファーを断っています。

ですが、その後もモチベーションが落ち込む出来事が幾つかあり、再オファーを承諾することに決めて今に至ります。

モチベーションが落ちる出来事は色々ありましたが、ここで書きません。僕が物事の一面しか見れていなかっただけで事実は違ったかもしれないですし、僕自身が感じたことは主観で捉えた話でしかありません。そういった話をオープンな場に書くのはフェアではないと感じるので書かないことにしました。前職の会社を嫌いになったわけではないですし。

まとめ

入社して早くも二週間が経ちますが、環境にもようやく慣れてきました。入社直後に張り切りすぎると体調を崩すことを前職で学んだので、この二週間は体調に目を光らせつつ、PHPの学び直しをしたり、dockerに慣れたりしてきました。今週からは徐々にペースを上げていこうと思います。

ちなみにエンジニアは足りてないっぽいし、デザイナーに至っては足りてないどころか一人もいないので、オミカレに興味のある人はDMなりメンションなりで気軽に声をかけてください!!よろしくお願いします。

アイコンフォントの運用をどうするか考える

gulp-iconfontでアイコンフォントを生成して運用していく生活が辛くなったので、素のSVGを使っていくのが現実的なのかを調べてみた。

辛くなったのはアイコンフォントのCSS調整するのが億劫になったのと、SVG種類が増えるたびにアイコンフォントを更新するのが面倒になったことの2つの理由がある。

使用できる参照方法

そもそも、SVGをHTML上で扱うには4つの手段がある。

  • SVG要素をHTML上にインラインで配置。
  • object要素で参照。
  • img要素で参照。
  • CSSのbackground-imageで参照。

普通に配置したいだけであればどれを選んでも問題ない。しかし、CSSSVGを装飾したい場合は話が変わってくる。

CSSで装飾したい場合

結論から言うと「SVG要素をHTML上にインラインで配置」しかない。

img要素やbackground-imageで参照したリソースに対して指定できるのはwidthやheightに限られるので、参照したSVGの色の変更することは出来ない。

一方、object要素はiframe要素と同様に外部リソースを参照するための要素であるため、CSSの参照は出来ない。(冷静に考えると、参照できたらセキュリティの抜け穴になりかねないので出来てはいけない)

SVG要素をインラインで配置する際の課題

インラインで都度記述するのが単純に面倒。アイコンフォントであれば、i要素やspan要素にクラスを設定するだけで使用できることを考えると、一層面倒に感じる。

というわけで、丸一日考えた現時点では以下の結論に至っている。

  • 装飾の必要がない場合はimg要素やbackground-imageで参照。
  • 装飾の必要がある場合はインラインで配置。

アイコンフォントに強いこだわりが無かったり、そもそも素のHTMLを書いたりしていない場合は素直にFontAwesomeとか使った方が圧倒的に楽です。そちらをオススメします。

英語力をつけるための習慣をつける

これまで雰囲気で英語を使ってきて、語彙力が全然足りてないなと日々思っていた。 また、技術的なトピックには日常的に英語で触れているものの、普段から触れている文章のジャンルが偏りすぎるのも良くないと感じてもいた。

ということで、この本の原書を読み始めました。

https://www.amazon.co.jp/Intellectual-Devotional-Complete-Education-Confidently/dp/1594865132/ref=sr_1_1?ie=UTF8&qid=1535375952&sr=8-1&keywords=intellectual+devotional

日本語訳されたものも出版されていて、本屋に行くと平積みされています。

1日1ページ、読むだけで身につく世界の教養365 | 文響社 Bunkyosha

どんな本?

日替わりで内容が変わる7つのジャンルのコラムが1年分載っていて、曜日ごとのジャンル振り分けはこんな感じになっています。

  • 月曜日:歴史
  • 火曜日:文学
  • 水曜日:芸術
  • 木曜日:科学
  • 金曜日:音楽
  • 土曜日:哲学
  • 日曜日:宗教

各分野ごとに違う人が書いているので、言い回しや文章にも各々の癖が見て取れて面白いです。 原書の初版発行が2006年で本自体は少々古いですが、この12年の間に根底を覆されている話はあまりないと思うので、話の鮮度はそこまで気にせずに読めています。

何をやっているのか

  1. 文章をノートに書き写す。
  2. 自分で全部翻訳をする。
  3. 全文を声に出して読む。

これを毎日継続します。文章の分量は多くないはずですが、1日分の量を済ませるために今は2時間くらいかかっています。

聞き慣れない単語や知らない文法が多く出てきて調べるのに時間がかかったり、自分の訳が文章的におかしかったりするのを見直したりしている間に結構な時間が経過しているようです。

あと、造詣がない分野の日はきついです(僕は海外文学をあまり読んだことが無いので、文学の日は基本的にハードモードです)。

やってみている感触

毎日継続するのはなかなかきついんですが、継続の甲斐あって英文に対する抵抗感(「読むのめんどくさいな・・」というような気持ち)は少しずつ薄れている実感があります。

また、知らない分野のことを知れるのは単純に面白いので、これを楽しみに続けられてます。

継続にあたって意識していること

  • 「体調が悪くて、今日の分が出来なかった。」
  • 「急に呑みに行くことになって、今日の分が出来なかった。」

こういう展開はたまにあります。たまにあるんですが・・その日に勉強出来なかった事で自分を必要以上に責めないようにしてます。自分に厳しくし過ぎて消耗してしまっては本末転倒です。

そういう日が週に4、5日あるようでは、さすがに生活を見直さなければならないと思います。ですが、週に1日程度であればそこまで気にしない事にして、別の方法で勉強することで穴埋めをする方針にしています。

別の勉強とは

  • TEDで面白そうな動画を見る。
  • 自分が好きな海外ドラマを英語で見る。

机に向かう元気が無い時は上記の方法を選んでいます。

TEDの動画であれば長くて15分くらいなので、そこまでのエネルギーはかけずに見ることが出来ます。

海外ドラマはこれを1話から見ています。

www.suits-tv.jp

登場人物がエリート揃いの設定なので、スラングが飛び交ってばかりの会話になることもないです。法廷ドラマなので、銃撃戦で人が死ぬこともなく精神衛生上優しいということもあり、他人にオススメしやすいです。

まとめ

自分なりの勉強法を纏めてみました。「これが最強の勉強法」だと言うわけではなく、あくまで自分に合っていそうな勉強方法を模索した結果を書いてみた次第です。

「英語の勉強、続かねえ〜〜/(^o^)\」という方のとっかかりになれば幸いです〜。

西日本応援プロジェクト 真夏の大LT大会!に行ってきました

techplay.jp

最近外部のイベントにあまり行っていなかったし、西日本の様子をニュースで見る度にしんみりしてて「寄付くらいしてみるか」という気持ちにもなっていたりしたので、パパッと申し込んで行ってきました。

行ってきた感想

1000円寄付した程度で聞いていいのか不安になるほどの豪華な内容で、「最高」以外の言葉がないイベントでした。チャリティコンサートに行ってきたのと同じくらいの楽しさがあったと感じています。頭の中でぐるぐる回っている感想を書き出すと、以下のようになりました。

  • メガネ型のウェアラブルバイス全盲のユーザに目の前の様子を音声で教えてる動画を見て、凄くドキドキした。

  • 自分の身内が西日本にいるわけではないんだけど、被災地の動画を見てると言葉が何も出てこなくなった。

    • IT DARTTwitterでボランティアの募集状況とかを周知してるのは全然知らなかったので、広く知られて欲しいと思う。
  • 自分の昔のブログやHPを今見たら、確実に悶絶死すると思った(遠い目)。「当時はこれがカッコいいと思ってた」みたいのは誰しもが通る道ですよね。

  • 緊急地震速報Chrome拡張の存在を初めて知った。

    • 身近な友人が被災していた出来事だったはずなのに、7年前の地震の記憶が自分の中で風化しつつあるのを実感した。
  • VP of Engineeringを受け持つくらいの人は色んな経験をしていた。

    • キャリア相談をしてくれて、1相談ごとに1000円を寄付するという謎企画があるそう。
  • カンファレンスの開催はお金がかかる。正直予想以上だった。1万円とかで参加できるなら安いもんだと感じてしまった。

  • Railsを支えている@kamipoさんの偉大さを知る。

  • 有益(今日から使えるとは言っていない)なPHP情報は個人的に一番ツボだった。

  • 出版業界の大変さを知る。実はWEB+DBに寄稿するのは個人的な夢なので、いつか書いてみたい。

  • ネットワークがダイヤルアップからADSLに変わる辺りでこの世界に首を突っ込み始めたので、昔話は完全に俺得状態で面白かった。

酪農の話が個人的に凄く気になっていたのですが、尿意に負けて聞けなかったのが残念・・(´・ω・`)。

資料のURLや当日の様子はTwitterハッシュタグを遡ればOKだと思います。

#midsummer_lt - Twitter Search

まとめ

肩肘張らずに楽しく寄付が出来るのは凄く素敵な事だと思うので、主催してくれた方々に感謝です!ありがとうございました!