¿Para qué sirve una etiqueta <script> dentro de una etiqueta <noscript>?


139

He estado en una juerga de "ver fuente" últimamente en sitios web con diseño y contenido interesantes. Uno de esos sitios web, Squarespace , tiene bloques de <script>etiquetas dentro de una <noscript>etiqueta, así:

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

Me pareció extraño, y busqué información en Google para ver si hay algún tipo de funcionalidad / propósito oculto para un HTML tan extraño, pero fue en vano. ¿Hay algún tipo de propósito para tener <script>etiquetas dentro de los <noscript>elementos, o es solo un ejemplo de HTML incorrecto?


18
En mi humilde opinión eso no tiene sentido y es solo un error.
Sebastien C.

12
Tal vez esa sea solo una forma extraña de comentar a JS.
AlexR

8
A juzgar por el hecho de que tienen una cabecera completa (incluyendo <base href="">, <meta … />, <title>y <link … />elementos) parece que están abusando <noscript>de plantillas.
Bergi

2
Gran pregunta! Pero horrible porque ahora has iniciado otra juerga de "ver fuente" para mí ... ¡Acabo de dejar ese hábito!
Bobo

2
@Bobo: ¡Pero, mirar el código para entender lo que sucede dentro de Matrix es algo bueno! ;)
Agent.Logic_

Respuestas:


139

Hice un poco de búsqueda a través de su código y encontré este fragmento (lo he limpiado para que sea más legible):

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 puede ver, la <noscript>etiqueta tiene la ID #inline-deps, a la que se hace referencia en el código (línea 3) para cargar dependencias de forma asíncrona y bajo demanda.

Probablemente usan un <noscript>elemento, ya que les permite acceder directamente a elementos DOM, en lugar de tener que colocarlo en una cadena o un comentario (lo que considero particularmente malo, ya que los comentarios no están destinados a información real) y luego analizarlo. También evita la ejecución de scripts y estilos CSS hasta que se cargue específicamente.

Personalmente, considero que se trata de un abuso de la <noscript>etiqueta. Ni siquiera estoy seguro de si es un código HTML5 válido. El uso de otros métodos, como declarar dependencias en un objeto JavaScript con un cargador de scripts, se debe utilizar siempre que sea posible.


71
Esos tortuosos piratas informáticos;). Espero que lo hayan documentado bien, antes de que un tipo inteligente lo elimine 'ya que no tiene uso'.
Patrick Hofman

66
He visto que se <script type="text/html">...</script>usa para el mismo propósito: ¿alguien tiene pros / contras de los dos?
Shai

44
Es probable que cualquier cosa dentro <noscript>sea ​​visible para usuarios que no sean JavaScript; la mayoría de los sitios simplemente no admiten esos usuarios, pero también querrás mostrarles un mensaje explicativo simple.
Katana314

8
Estas son algunas prácticas extraordinariamente malas que están realizando
tcooc

3
¿Alguien puede explicar qué hace este código? ... 86 votos a favor y no tengo idea de qué se trata este código ... ¡Me siento tonto! ...
Lakshay
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.