質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.06%

CSSをjsで遅延読み込みさせたい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,379

yokoyamax

score 16

タイトルの通り、外部ドメインのCSS(Font Awesomeなど)をjsで遅延読み込みさせたいと考えております。
目的としては、ページスピード(スコア)の向上です。

実現したいこと

  • 現状、head内で読み込んでいるCSSを削除
  • </body>直前にjsを設置し、そこでheadで読み込んでいたCSSを読み込む

困っていること

下記ページを参考に素人ながらjsを書いてみましたが、うまく読み込めておりません。
※読み込めていないというのは、jsで遅延読み込みさせた場合にCSSのレンダリングがされないとう意味です。
通常通りhead内のlinkタグではCSSのレンダリングができております。

https://developers.google.com/speed/docs/insights/OptimizeCSSDelivery
https://www.notitle-weblog.com/entry/2016/11/10/184826
  

現状のコード

<script async>
  var fontawesome45 = "https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css";
  var fontawesome47 = "https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css";
  var fontawesome50 = "https://use.fontawesome.com/releases/v5.3.1/css/all.css";
  var fontawesome_animation = "https://cdnjs.cloudflare.com/ajax/libs/font-awesome-animation/0.1.0/font-awesome-animation.min.css";
  var jquery = "https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css";
  function cb(href) {
    var link = document.createElement('link'); link.rel = 'stylesheet';
    link.href = href;
    document.head.appendChild(link);
  };
  var raf = requestAnimationFrame || mozRequestAnimationFrame ||
      webkitRequestAnimationFrame || msRequestAnimationFrame;
  if (raf) {
    raf(function (){
      cb(fontawesome45);cb(fontawesome47);cb(fontawesome50);cb(fontawesome_animation);cb(jquery);
    });
  } else {
    window.addEventListener('load', function(){
      cb(fontawesome45);cb(fontawesome47);cb(fontawesome50);cb(fontawesome_animation);cb(jquery);
    });
  }
</script>

  
全体html

<!DOCTYPE html>
<html>
<head>
<link rel="preload" href="css/hoge.css" type="text/css" as="style" onload="this.onload=null;this.rel='stylesheet'">

<script type="text/javascript" async>
  /*! loadCSS. [c]2017 Filament Group, Inc. MIT License */ ! function(t) {
    "use strict";
    t.loadCSS || (t.loadCSS = function() {});
    var e = loadCSS.relpreload = {};
    if (e.support = function() {
        var e;
        try {
          e = t.document.createElement("link").relList.supports("preload")
        } catch (a) {
          e = !1
        }
        return function() {
          return e
        }
      }(), e.bindMediaToggle = function(t) {
        function e() {
          t.addEventListener ? t.removeEventListener("load", e) : t.attachEvent && t.detachEvent("onload", e), t.setAttribute("onload", null), t.media = a
        }
        var a = t.media || "all";
        t.addEventListener ? t.addEventListener("load", e) : t.attachEvent && t.attachEvent("onload", e), setTimeout(function() {
          t.rel = "stylesheet", t.media = "only x"
        }), setTimeout(e, 3e3)
      }, e.poly = function() {
        if (!e.support())
          for (var a = t.document.getElementsByTagName("link"), n = 0; n < a.length; n++) {
            var o = a[n];
            "preload" !== o.rel || "style" !== o.getAttribute("as") || o.getAttribute("data-loadcss") || (o.setAttribute("data-loadcss", !0), e.bindMediaToggle(o))
          }
      }, !e.support()) {
      e.poly();
      var a = t.setInterval(e.poly, 500);
      t.addEventListener ? t.addEventListener("load", function() {
        e.poly(), t.clearInterval(a)
      }) : t.attachEvent && t.attachEvent("onload", function() {
        e.poly(), t.clearInterval(a)
      })
    }
    "undefined" != typeof exports ? exports.loadCSS = loadCSS : t.loadCSS = loadCSS
  }("undefined" != typeof global ? global : this);
</script>
</head>

<body>
  テキストテキストテキストテキスト
  <script>
    ここに上部のjs
  </script>
</body>
</html>


  
自分が書いたjsが間違っているのか、それとも他のjsとの兼ね合いなのか、
何が原因で上手くいかないのかをご教授頂けますと幸いです。

よろしくお願い致します。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • miyabi_takatsuk

    2019/01/10 12:39

    うまく読み込めていない、というのは、CSSが読み込まれず、CSSルール通りのレンダリングがされない、ということでよろしいですか?Chromeの要素検証などで、linkタグ自体が意図した通り挿入されているかどうかも確認し、質問に記載したほうが、問題解決につながるかと思います。

    キャンセル

  • yokoyamax

    2019/01/10 13:27

    >うまく読み込めていない、というのは、CSSが読み込まれず、CSSルール通りのレンダリングがされない、ということでよろしいですか?
    →そのとおりでございます。

    linkタグ単体では通常どおり問題なく読み込まれレンダリングされております。

    キャンセル

回答 1

checkベストアンサー

+3

cssが一つならこんな感じ?

<head>
<link rel='stylesheet' type='text/css' href='hoge.css'></link>
<script>
window.addEventListener('DOMContentLoaded', function(e){
  if(org=document.querySelector('head link[href]')){
    cln=org.cloneNode(true);
    document.querySelector('head').removeChild(org);
  }
  setTimeout(function(){
    document.querySelector('head').appendChild(cln);
  },3000);
});
</script>
</head>
<body>
test
</body>

複数を想定

<head>
<link rel='stylesheet' type='text/css' href='hoge1.css'></link>
<link rel='stylesheet' type='text/css' href='hoge2.css'></link>
<link rel='stylesheet' type='text/css' href='hoge3.css'></link>
<script>
window.addEventListener('DOMContentLoaded', function(e){
  if(i=document.querySelectorAll('head link[href]')){
     var cln=[].map.call(i,function(x){
       var y=x.cloneNode(true);
       document.querySelector('head').removeChild(x);
       return y;
     });
    setTimeout(function(){
      cln.forEach(function(x){
        document.querySelector('head').appendChild(x);
      });
    },3000);
  };
});
</script>
</head>
<body>
test
</body>

解説付き

window.addEventListener('DOMContentLoaded', function(e){
/*
 * windowがロードされて画面がレンダリングされる前の処理
 */
  if(i=document.querySelectorAll('head link[href]')){

/* ここからクローン・削除処理 */

 /*
 * i=document.querySelectorAll('head link[href]')
 * head内にhref属性を持つlinkがあることを確認し
 * あればiに代入、一つもなければif節から抜ける
 */
    var cln=[].map.call(i,function(x){
/*
 * iはHTMLCollectionなのでループするメソッドを持たないため
 * Arrayが持つmapコマンドを借りる
 * mapメソッドはiから受け取った要素を順番にxに渡す
 */
      var y=x.cloneNode(true);
/*
 * xはHTMLElement、それを一度yという変数にクローンしておいておく
 */
       document.querySelector('head').removeChild(x);
/*
 * headタグからxを削除する
 */
       return y;
/*
 * y(=クローンしたlink)を戻す
 */
     });
/*
 * mapでリターンすると戻り値で構成された配列ができあがる
 * したがってclnはhead内のlinkをクローンしたものをリスト化した配列
 */
/* ここまでクローン・削除処理 */

/*
 * 一連の削除が終わると追加処理まで一時的にcssが適用されていない状態になる
 */

/* ここから追加処理 */

    setTimeout(function(){
/*
 * nミリ秒後にコマンドを実行する
 */
      cln.forEach(function(x){
/*
 * cln配列から要素を1つ1つ取り出してxに渡す
 */
        document.querySelector('head').appendChild(x);
/*
 * headにxを追加していく
 */
      });
    },3000);
/*
 * setTimeoutの待ち時間を3秒とする
 */

/* ここまで追加処理 */

  }
/* if節の終わり */

});

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/01/10 15:16

    はい、そのとおりでございます。
    ざっくりと構いませんのでお願いしてもよろしいでしょうか?

    キャンセル

  • 2019/01/10 15:59

    解説付けておきました

    キャンセル

  • 2019/01/10 16:44

    懇切丁寧にありがとうございます。
    お陰様で実現できました。
    ほんとうにありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.06%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る