Apa tujuan tag <script> melayani di dalam tag <noscript>?

139

Saya telah berada di "sumber tampilan" foya akhir-akhir ini di situs web dengan desain dan konten yang menarik. Salah satu situs web itu, Squarespace , memiliki blok <script>tag di dalam <noscript>tag, seperti:

<!-- Page is at: http://squarespace.com -->
...
...
<noscript id="inline-deps">
  <link rel="stylesheet" type="text/css" href="//cloud.typography.com/7811972/758964/css/fonts.css" />

  <script type="text/javascript" src="https://static.squarespace.com/static/ta/5134cbefe4b0c6fb04df8065/7400/assets/logomark/logomark.min.js?37"></script>
  <link rel="stylesheet" href="https://static.squarespace.com/static/ta/5134cbefe4b0c6fb04df8065/7400/assets/logomark/logomark.min.css?37" type="text/css" />
</noscript>
...
...

Itu mengejutkan saya, dan membuat saya mencari info di Google untuk melihat apakah ada semacam fungsi / tujuan tersembunyi untuk HTML yang aneh, tetapi tidak berhasil. Apakah ada semacam tujuan untuk memiliki <script>tag di dalam <noscript>elemen, atau apakah ini hanya contoh HTML yang buruk?

Agent.Logic_
sumber
18
IMHO itu tidak masuk akal dan itu hanya kesalahan.
Sebastien C.
12
Mungkin itu hanya cara aneh untuk berkomentar JS keluar.
AlexR
8
Dilihat dari fakta bahwa mereka memiliki header lengkap (termasuk <base href="">, <meta … />, <title>dan <link … />unsur-unsur) sepertinya mereka menyalahgunakan <noscript>untuk template.
Bergi
2
Pertanyaan bagus! Tapi mengerikan karena Anda sekarang telah memulai foya "view source" lain untuk saya .. Saya baru saja keluar dari kebiasaan itu!
Bobo
2
@ Bob: Tapi, melihat kode untuk memahami apa yang terjadi di dalam Matrix adalah hal yang baik! ;)
Agent.Logic_

Jawaban:

139

Saya melakukan beberapa pencarian melalui kode mereka dan menemukan potongan ini (saya sudah membersihkannya agar lebih mudah dibaca):

var DepLoader = (function () {
  function init() {
    var dependencies = document.getElementById("inline-deps");
    if (!dependencies || JS.hasClass(document.body, "deps--loaded")) {
      webfontsReady();
    } else {
      var html = dependencies.innerText || dependencies.textContent;
      JS.addClass(document.body, "deps--loaded");
      processRaw(html);
    }
  }

  function isListed(a, b) {
    for (var i = 0; i < b.length; i++) {
      if (a.indexOf(b[i]) !== -1) {
        return true;
      }
    }
    return false;
  }

  function webfontsReady() {
    JS.fireCustom("webfontsReady");
  }

  function processRaw(html) {
    var el = document.createElement("div");
    el.innerHTML = html;

    var scripts = el.querySelectorAll("script");
    var styles = el.querySelectorAll("link");
    var common, signup, dialog, systemPage, commerce;
    var others = [];
    var inline = [];
    var styleWhiteList = ["site.css", "dialog-", "signup-", "logomark"];
    var scriptBlackList = ["management-", "ckeditor-"];

    for (var i = 0; i < styles.length; i++) {
      var style = styles[i];
      if (style.href.indexOf("fonts.css") !== -1) load(style, webfontsReady);
      if (isListed(style.href, styleWhiteList)) load(style);
    }

    for (var i = 0; i < scripts.length; i++) {
      var script = scripts[i];
      var src = script.src;

      if (!src && script.getAttribute("data-sqs-type") !== "dynamic-assets-loader" && script.innerHTML.indexOf("SQUARESPACE_ROLLUPS") === -1) {
        eval(script.innerHTML);
      }
    }

    if (window.SQUARESPACE_ROLLUPS) {
      for (var key in SQUARESPACE_ROLLUPS) {
        var rollup = SQUARESPACE_ROLLUPS[key];
        var js = rollup.js;
        var css = rollup.css;

        if (key.indexOf("common") !== -1) {
          common = js;
        } else if (key.indexOf("commerce") !== -1) {
          commerce = js;
        } else if (key.indexOf("signup") !== -1) {
          signup = js;
        } else if (key.indexOf("dialog") !== -1) {
          dialog = js;
        } else if (key.indexOf("system-page") !== -1) {
          systemPage = js;
        } else if (key) {
          others = others.concat(js);
        } else {
          inline = inline.concat(js);
        }
      }
    }

    for (var i = 0; i < scripts.length; s++) {
      var script = scripts[i];
      var src = script.src;

      if (!isListed(src, scriptBlackList)) {
        if (src.indexOf("common-") !== -1) {
          common = script;
        } else if (src.indexOf("commerce-") !== -1) {
          commerce = script;
        } else if (src.indexOf("signup-") !== -1) {
          signup = script;
        } else if (src.indexOf("dialog-") !== -1) {
          dialog = script;
        } else if (src.indexOf("system-page-") !== -1) {
          systemPage = script;
        } else if (src) {
          others.push(script);
        } else {
          inline.push(script);
        }
      }
    }

    function loadOthers() {
      for (var i = 0; i < inline.length; i++) {
        if (inline[i].getAttribute("data-sqs-type") !== "dynamic-assets-loader") {
          load(inline[a]);
        }
      }

      for (var i = 0; i < others.length; i++) {
          load(others[i]);
      }

      JS.fireCustom("dependenciesLoaded");
    }

    var loadSystemPage = load.bind(this, systemPage, loadOthers, "system page");
    var loadSignup = load.bind(this, signup, loadSystemPage, "signup");
    var loadCommerce = load.bind(this, commerce, loadSignup, "commerce");
    var loadDialog = load.bind(this, dialog, loadCommerce, "dialog");
    var loadCommon = load.bind(this, common, loadDialog, "common");

    loadCommon();
  }

  function load(tag, callback, label) {
    var head = document.head;

    if (Array.isArray(tag)) tag = { nodeName: "SCRIPT", src: tag[0] };

    if (!tag) {
      if (callback) callback();
      return;
    }

    if (tag && (tag.src || tag.href)) {
      var child;
      if ("SCRIPT" === tag.nodeName) {
        child = document.createElement("script");
        child.src = tag.src;

        if (child.src.indexOf("combo") !== -1) {
          callback = function () {
            Y.Squarespace.FrontSite.Core.domReady(true)
          };
        }
      } else {
        if ("LINK" === tag.nodeName && "stylesheet" === tag.rel) {
          child = document.createElement("link");
          child.href = tag.href;
          child.rel = "stylesheet";
          child.tyle = "text/css";
        }

        if (child) {
          child.onload = callback;
          head.appendChild(child);
        }
      }
    } else {
      try {
        eval(tag.innerHTML);
      } catch (e) {}
    }
  }

  return { init: init, webfontsReady: webfontsReady };
})();

Seperti yang Anda lihat, <noscript>tag memiliki ID #inline-deps, yang direferensikan dalam kode (baris 3) untuk memuat dependensi secara tidak sinkron dan sesuai permintaan.

Mereka mungkin menggunakan <noscript>elemen karena memungkinkan mereka untuk secara langsung mengakses elemen DOM, daripada harus menempatkannya dalam string atau komentar (yang saya anggap sangat buruk, karena komentar tidak dimaksudkan untuk informasi aktual) dan kemudian menguraikannya. Ini juga mencegah pelaksanaan skrip dan gaya CSS hingga dimuat secara khusus.

Saya pribadi menemukan ini penyalahgunaan <noscript>tag. Saya bahkan tidak yakin apakah itu kode HTML5 yang valid. Menggunakan metode lain seperti mendeklarasikan dependensi dalam objek JavaScript dengan skrip loader harus digunakan jika memungkinkan.

Qantas 94 Heavy
sumber
71
Para peretas kode yang licik;). Saya harap mereka mendokumentasikannya dengan baik, sebelum beberapa orang pintar menghapusnya 'karena tidak ada gunanya'.
Patrick Hofman
6
Saya pernah melihat <script type="text/html">...</script>digunakan untuk tujuan yang sama - ada yang mendapat pro / kontra dari keduanya?
Shai
4
Kemungkinan apa pun di dalamnya <noscript>akan terlihat oleh pengguna non-JavaScript; sebagian besar situs tidak mendukung pengguna tersebut, tetapi Anda juga ingin menunjukkan pesan penjelasan sederhana kepada mereka.
Katana314
8
Itu adalah beberapa praktik buruk luar biasa yang mereka lakukan
tcooc
3
Adakah yang bisa menjelaskan apa yang kode ini lakukan? .. 86 upvotes dan saya tidak tahu apa kode ini tentang .. Saya merasa bodoh! ..
Lakshay