Help us understand the problem. What is going on with this article?

必要な要素が出来た時点で処理を実行したい(DOMContentLoadedまで待てない)

More than 3 years have passed since last update.

とあるサイトを高速化したいという依頼を受けた。

構造

そのサイトは静的ページなんだけど、記事本文部分が以下の様なHTML構造になっていて、

<div>冒頭ぶった切り</div>
<div class="MoreBtn hide">続きを読むボタン</div>
<div class="MoreBody hide">記事の後半全文</div>

Javascript で DOMContentLoaded のタイミングでクエリをチェックして mode=all が付いてるかどうかを見て hide クラスの除去を行っていた。

readmore.js(明用簡略ソースです)
$(function(){
  if(/mode=all/.test(location.search)) {
    $(".MoreBtn").removeClass("hide");
  } else {
    $(".MoreBody").removeClass("hide");
  }
});

一応これで表示非表示の制御自体は期待通りの動作は実現できていました。

問題点

  • このページにはサイドバーやサードパーティ製の広告タグがわんさか入っていました。
  • そのため DOMContentLoaded が発火するのが非常に遅い 時がありました。
  • するとヘタしたら続きを読むボタンや本文表示自体が冒頭文章が表示された後1分ぐらいしてからボタンや本文が唐突に現れるといった具合です。
  • 広告タグや readmore.js を埋める場所を動かすのも難しい事情があるようです。
  • 色々突っ込みどころはありますが現状は大きく変えずに小手先の修正で改善したいというのが要件です。

解決策

実はDOM内に記事部分が出現するタイミング自体は結構早いです。
問題の元凶は DOMContentLoaded が発火するのが非常に遅い事で、またそれを早くするのも難しそうというという事です。
なので DOMConentLoaded を待たずに .MoreBtn.MoreBody の要素が出現したタイミングで JS 処理を実行すればいいんじゃね?
ってことでそれを発火するタイミングを早くする為に readmore.js を以下のような書き換えてみました。

!function(){
  // selectors で指定された要素の出現、またはDOMContentLoadedの早い方のタイミングで handler を実行する、
  function waitElementOrReady(selectors, handler) {
    var loop = setInterval(function(){
      if(selectors.every(function(v){return document.querySelector(v)})) {
        onReady();
      }
    }, 500);
    document.addEventListener('DOMContentLoaded', onReady);
    function onReady() {
      clearInterval(loop);
      handler();
    }
  }

  // $(...) の代わりに waitElementOrReady 関数経由で発火タイミングを指定する。
  waitElementOrReady([".MoreBtn", ".MoreBody"], function(){
    if(/mode=all/.test(location.search)) {
      $(".MoreBtn").removeClass("hide");
    } else {
      $(".MoreBody").removeClass("hide");
    }
  });

}();

こんな感じの改造で、コンテンツ全体の読み込みが終わらなくても続きボタンや続きの本文が即座に表示できるようになりました。
案外簡単に出来てよかった。めでたしめでたし。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした