< script > 标记在 < noscript > 标记中的作用是什么?

最近我在一些设计和内容都很有趣的网站上大肆浏览资源。其中的一个网站,方格,在 <noscript>标签内有 <script>标签块,像这样:

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

这让我觉得很奇怪,于是我开始在谷歌上搜索信息,看看这些奇怪的 HTML 是否有某种隐藏的功能/用途,但是毫无用处。在 <noscript>元素内部使用 <script>标记是否有某种目的,或者这只是糟糕 HTML 的一个例子?

7740 次浏览

我在他们的代码中进行了一些搜索,发现了这个片段(我已经对其进行了清理,使其更具可读性) :

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

如您所见,<noscript>标记具有 ID #inline-deps,该 ID 在代码(第3行)中被引用,用于异步和随需加载依赖项。

他们可能使用 <noscript>元素,因为它允许他们直接访问 DOM 元素,而不必将其放在字符串或注释中(我认为这尤其糟糕,因为注释不是为实际信息准备的) ,然后解析它。它还阻止脚本和 CSS 样式的执行,直到专门加载。

我个人认为这是对 <noscript>标签的滥用。我甚至不确定它是否是有效的 HTML5代码。在可行的情况下,应该使用其他方法,比如使用脚本加载器在 JavaScript 对象中声明依赖项。