Mục đích của thẻ <script> phục vụ bên trong thẻ <noscript> là gì?


139

Gần đây tôi đã có một "nguồn xem" trên các trang web có thiết kế và nội dung thú vị. Một trong những trang web đó, Squarespace , có các khối <script>thẻ bên trong <noscript>thẻ, như vậy:

<!-- 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>
...
...

Nó gây cho tôi sự kỳ quặc và khiến tôi phải tìm kiếm thông tin để xem liệu có một loại chức năng / mục đích ẩn nào đó cho một bit HTML kỳ quặc như vậy, nhưng không có kết quả. Có một số mục đích để có <script>các thẻ bên trong các <noscript>yếu tố, hay đây chỉ là một ví dụ về HTML xấu?


18
IMHO không có ý nghĩa và đó chỉ là một sai lầm.
Sebastien C.

12
Có lẽ đó chỉ là một cách kỳ lạ để bình luận về JS.
AlexR

8
Đánh giá từ thực tế rằng họ có một tiêu đề đầy đủ (bao gồm <base href="">, <meta … />, <title><link … />các yếu tố) có vẻ như họ đang lạm dụng <noscript>cho khuôn mẫu.
Bergi

2
Câu hỏi tuyệt vời! Nhưng thật kinh khủng bởi vì bây giờ bạn đã khởi động một "nguồn xem" khác cho tôi .. Tôi đã thoát khỏi thói quen đó!
Bobo

2
@Bobo: Nhưng, nhìn vào mã để hiểu những gì xảy ra bên trong Ma trận là một điều tốt! ;)
Đặc vụ.Logic_

Câu trả lời:


139

Tôi đã thực hiện một số tìm kiếm thông qua mã của họ và tìm thấy đoạn trích này (Tôi đã dọn sạch nó để dễ đọc hơn):

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 };
})();

Như bạn có thể thấy, <noscript>thẻ có ID #inline-deps, được tham chiếu trong mã (dòng 3) để tải phụ thuộc không đồng bộ và theo yêu cầu.

Họ có thể sử dụng một <noscript>phần tử vì nó cho phép họ truy cập trực tiếp các phần tử DOM, thay vì phải đặt nó trong một chuỗi hoặc một nhận xét (mà tôi cho là đặc biệt xấu, vì các bình luận không có nghĩa là thông tin thực tế) và sau đó phân tích nó. Nó cũng ngăn chặn việc thực thi các tập lệnh và kiểu CSS cho đến khi được tải cụ thể.

Cá nhân tôi thấy đây là một sự lạm dụng của <noscript>thẻ. Tôi thậm chí không chắc chắn nếu đó là mã HTML5 hợp lệ. Sử dụng các phương pháp khác như khai báo các phụ thuộc trong một đối tượng JavaScript bằng trình tải tập lệnh nên được sử dụng khi có thể thực hiện được.


71
Những tin tặc mã sai lệch;). Tôi hy vọng họ đã ghi lại nó một cách tốt đẹp, trước khi một người thông minh nào đó xóa nó 'vì nó không có tác dụng'.
Patrick Hofman

6
Tôi đã thấy <script type="text/html">...</script>được sử dụng cho cùng một mục đích - bất kỳ ai cũng có ưu / nhược điểm của cả hai?
Shai

4
Có vẻ như mọi thứ bên trong <noscript>sẽ hiển thị cho người dùng không phải là JavaScript; hầu hết các trang web chỉ đơn giản là không hỗ trợ những người dùng đó, nhưng bạn cũng muốn hiển thị một thông báo giải thích đơn giản cho họ.
Katana314

8
Đó là một số thực hành cực kỳ xấu mà họ đang thực hiện
tcooc

3
? Pls bất cứ ai có thể giải thích những gì mã này không .. 86 upvotes và tôi không có ý tưởng gì mã này là về .. Tôi đang cảm thấy ngớ ngẩn ..!
Lakshay
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.