Qual é o objetivo de uma marca <script> dentro de uma marca <noscript>?

139

Ultimamente, tenho estado em uma série de "fontes de visualização" em sites com design e conteúdo interessantes. Um desses sites, o Squarespace , possui blocos de <script>tags dentro de uma <noscript>tag, assim:

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

Isso me pareceu estranho e me levou a pesquisar informações para ver se há algum tipo de funcionalidade / finalidade oculta para um pouco de HTML tão estranho, mas sem sucesso. Existe algum tipo de objetivo em ter <script>tags dentro dos <noscript>elementos ou isso é apenas um exemplo de HTML incorreto?

Agent.Logic_
fonte
18
IMHO que não faz sentido e é apenas um erro.
Sebastien C.
12
Talvez seja apenas uma maneira estranha de comentar JS.
precisa saber é
8
A julgar pelo fato de que eles têm um cabeçalho completo (incluindo <base href="">, <meta … />, <title>e <link … />elementos) parece que eles estão abusando <noscript>de templates.
Bergi
2
Ótima pergunta! Mas horrível, porque você iniciou outra série de "fontes de visualização" para mim. Acabei de sair desse hábito!
Bobo
2
@Bobo: Mas, olhar o código para entender o que acontece dentro da Matrix é uma coisa boa! ;)
Agent.Logic_

Respostas:

139

Pesquisei o código e encontrei esse trecho (limpei-o para torná-lo mais legível):

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

Como você pode ver, a <noscript>tag possui o ID #inline-deps, que é referenciado no código (linha 3) para carregar dependências de forma assíncrona e sob demanda.

Eles provavelmente usam um <noscript>elemento, pois permite acessar diretamente os elementos DOM, em vez de colocá-lo em uma sequência ou comentário (o que considero particularmente ruim, pois os comentários não são para informações reais) e, em seguida, analisam-no. Também impede a execução de scripts e estilos CSS até que seja carregado especificamente.

Pessoalmente, acho isso um abuso da <noscript>tag. Eu nem tenho certeza se é um código HTML5 válido. O uso de outros métodos, como declarar dependências em um objeto JavaScript com um carregador de scripts, deve ser usado sempre que possível.

Qantas 94 Heavy
fonte
71
Esses hackers de código desonestos;). Espero que eles tenham documentado bem, antes que um cara esperto o excluísse 'porque não tem utilidade'.
Patrick Hofman
6
Eu já vi <script type="text/html">...</script>usado para o mesmo propósito - alguém tem prós / contras dos dois?
Shai
4
É provável que qualquer coisa dentro <noscript>dele esteja visível para usuários que não sejam JavaScript; a maioria dos sites simplesmente não oferece suporte a esses usuários, mas você também gostaria de mostrar uma mensagem explicativa simples para eles.
precisa saber é o seguinte
8
Isso é algumas práticas extraordinariamente ruins eles estão realizando
tcooc
3
? Alguém pls pode explicar o que este código faz .. 86 upvotes e não tenho idéia do que este código é sobre .. Eu estou sentindo idiota ..!
Lakshay