添加
最近我看到一些 HTML 在其 中只有一个
元素...
<head>
<title>Example</title>
<script src="script.js" type="text/javascript"></script>
<link href="plain.css" type="text/css" rel="stylesheet" />
</head>
这个 script.js
然后添加使用 document.write(...)
将任何其他必要的 元素和
元素添加到文档:(或它可以使用
document.createElement(...)
等)
document.write("<link href=\"javascript-enabled.css\" type=\"text/css\" rel=\"styleshet\" />");
document.write("<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js\" type=\"text/javascript\"></script>");
document.write("<script src=\"https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.10/jquery-ui.min.js\" type=\"text/javascript\"></script>");
document.write("<link href=\"http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.0/themes/trontastic/jquery-ui.css\" type=\"text/css\" rel=\"stylesheet\" />")
document.write("<script src=\"validation.js\" type=\"text/css\"></script>")
请注意,文档 中有一个
plain.css
CSS 文件> 和 script.js 只添加由支持 JS 的用户代理使用的所有 CSS 和 JavaScript。
这种技术有哪些优点和缺点?
Recently I saw some HTML with only a single <script>
element in its <head>
...
<head>
<title>Example</title>
<script src="script.js" type="text/javascript"></script>
<link href="plain.css" type="text/css" rel="stylesheet" />
</head>
This script.js
then adds any other necessary <script>
elements and <link>
elements to the document using document.write(...)
: (or it could use document.createElement(...)
etc)
document.write("<link href=\"javascript-enabled.css\" type=\"text/css\" rel=\"styleshet\" />");
document.write("<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js\" type=\"text/javascript\"></script>");
document.write("<script src=\"https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.10/jquery-ui.min.js\" type=\"text/javascript\"></script>");
document.write("<link href=\"http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.0/themes/trontastic/jquery-ui.css\" type=\"text/css\" rel=\"stylesheet\" />")
document.write("<script src=\"validation.js\" type=\"text/css\"></script>")
Note that there is a plain.css
CSS file in the document <head>
and script.js
just adds any and all CSS and JavaScript which would be used by a JS-enabled user agent.
What are some of the pros and cons of this technique?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
document.write 的阻塞性质
document.write
将暂停浏览器在页面上进行的所有操作(包括解析)。由于这种阻塞行为,强烈建议避免。浏览器无法知道此时您要向 HTML 文本流中写入什么内容,或者写入是否会完全丢弃 DOM 树上的所有内容,因此它必须停止,直到您完成为止。本质上,以这种方式加载脚本将强制浏览器停止解析 HTML。如果您的脚本是内联的,那么浏览器也会在继续之前执行这些脚本。因此,作为旁注,始终建议您推迟加载脚本,直到解析页面并向用户显示合理的 UI 之后。
如果您的脚本是从“src”属性中的单独文件加载的,则脚本可能无法在所有浏览器上一致执行。
失去浏览器速度优化和可预测性
这样,您就会失去现代浏览器所做的许多性能优化。此外,脚本的执行时间可能是不可预测的。
例如,某些浏览器会在您“编写”脚本后立即执行它们。在这种情况下,您会丢失脚本的并行下载(因为浏览器在下载并执行第一个脚本标签之前不会看到第二个脚本标签)。您会失去脚本和样式表以及其他资源的并行下载(许多浏览器可以同时下载资源、样式表和脚本)。
有些浏览器将脚本推迟到结束后才执行。
当 document.write 正在进行时,浏览器无法继续解析 HTML,在某些情况下,由于
document.write
的阻塞行为,当编写的脚本正在执行时,因此您的页面会显示慢得多。换句话说,您的网站的加载速度就像在没有优化的几十年前的浏览器上加载一样慢。
为什么有人会这样做?
您可能想要使用这样的东西的原因通常是为了可维护性。例如,您可能有一个包含数千个页面的大型网站,每个页面都加载相同的脚本和样式表集。但是,当您添加脚本文件时,您不想编辑数千个 HTML 文件来添加脚本标记。这在加载 JavaScript 库(例如 Dojo 或 jQuery)时尤其麻烦——升级到下一个版本时,您必须更改每个 HTML 页面。
问题是 JavaScript 没有 @include 或 @import 语句供您包含其他文件。
一些解决方案
解决这个问题的方法可能不是通过
document.write
注入脚本,而是通过:document.write
,而是通过 XHR 加载 JavaScript 文件,然后 但这可能会带来安全问题The blocking nature of document.write
document.write
will pause everything that the browser is working on the page (including parsing). It is highly recommended to avoid because of this blocking behavior. The browser has no way of knowing what you're going to shuff into the HTML text stream at that point, or whether the write will totally trash everything on the DOM tree, so it has to stop until you're finished.Essentially, loading scrips this way will force the browser to stop parsing HTML. If your script is in-line, then the browser will also execute those scripts before it goes on. Therefore, as a side-note, it is always recommended that you defer loading scripts until after your page is parsed and you've shown a reasonable UI to the user.
If your scripts are loaded from separate files in the "src" attribute, then the scripts may not be consistently executed across all browsers.
Losing browser speed optimizations and predictability
This way, you lose a lot of the performance optimizations made by modern browsers. Also, when your scripts execute may be unpredictable.
For example, some browsers will execute the scripts right after you "write" them. In such cases, you lose parallel downloads of scripts (because the browser doesn't see the second script tag until it has downloaded and executed the first). You lose parallel downloads of scripts and stylesheets and other resources (many browsers can download resources, stylesheets and scripts all at the same time).
Some browsers defer the scripts until after the end to execute them.
The browser cannot continue to parse the HTML while document.write is going on and, in certain cases, when the scripts written are being executed due to the blocking behavior of
document.write
, so your page shows up much slower.In other words, your site has just become as slow as it was loading on a decades-old browser with no optimizations.
Why would somebody do it like this?
The reason you may want to use something like this is usually for maintainability. For instance, you may have a huge site with thousands of pages, each loading the same set of scripts and stylesheets. However, when you add a script file, you don't want to edit thousands of HTML files to add the script tags. This is particularly troublesome when loading JavaScript libraries (e.g. Dojo or jQuery) -- you have to change each HTML page when you upgrade to the next version.
The problem is that JavaScript doesn't have an @include or @import statement for you to include other files.
Some solutions
The solution to this is probably not by injecting scripts via
document.write
, but by:document.write
, but load the JavaScript files via XHR, then eval() them -- this may have security concerns though一大缺点是浏览器不兼容。并非所有浏览器都能正确获取资源并将其合并到 DOM 中,因此使用这种方法是有风险的。样式表比脚本更是如此。
另一个问题是可维护性。在客户端连接和编写字符串来添加 DOM 元素可能会成为维护的噩梦。最好使用 DOM 方法(例如 createElement)来按语义创建元素。
一个明显的优点是它使资源的有条件使用变得更加容易。您可以使用逻辑来确定要加载的资源,从而减少页面的带宽消耗和总体处理时间。我会使用库调用(例如 jQuery $.getScript())来加载脚本而不是 document.write。优点是这种方法更干净,并且还允许您在请求完成或失败时执行代码。
One major disadvantage is browser incompatibility. Not all browsers correctly fetch and incorporate the resources into the DOM, so it's risky to use this approach. This is more true of stylesheets than scripts.
Another issue is one of maintainability. Concatenating and writing strings to add DOM elements on the client'side can become a maintenance nightmare. It's better to use DOM methods such as createElement to semantically create elements.
One obvious advantage is that it makes conditional use of resources much easier. You can have logic that determines which resources to load, thereby reducing the bandwidth consumption and overall processing time for the page. I would use a library call such as jQuery $.getScript() to load scripts versus document.write. The advantage being that such an approach is cleaner and also allows you to have code executed when the request is completed or fails.
好吧,我不妨向这个致敬……
如果你检查 google 的闭包库,base.js,你会发现在他们的
writeScriptTag_()
中使用了 document.write功能。这是“闭包”提供的依赖管理系统的重要组成部分,并且在创建复杂的、多文件的、基于库的 JavaScript 应用程序时具有巨大的优势 - 它让文件/代码先决条件确定加载顺序。我们目前使用这种技术并且几乎没有遇到什么问题。老实说,我们没有遇到任何浏览器兼容性问题,并且我们定期在 IE 6/7/8、FF3/2、Safari 4/5 和最新的 Chrome 上进行测试。到目前为止,我们遇到的唯一缺点是,追踪由于加载资源两次或根本加载失败而导致的问题可能具有挑战性。由于加载资源的行为是编程性的,因此可能会出现编程错误,并且与直接将标签添加到 HTML 不同,很难看出确切的加载顺序。然而,这个问题可以通过使用具有某种形式的依赖管理系统(例如闭包或dojo)的库来很大程度上解决。
编辑:我对此性质做了一些评论,但我认为最好在我的回答中总结一下:
dojo.require() 和 jQuery.getScript() (两者最终都会执行 ajax 请求和 eval)存在一些问题。
Well, I may as well throw my hat in the ring on this one...
If you examine google's closure library, base.js, you will see that document.write is used in their
writeScriptTag_()
function. This is an essential part of the dependency management system which 'closure' provides, and is an enormous advantage when creating a complicated, multi-file, library-base javascript application - it lets the file/code prerequisites determine loading order. We currently use this technique and have been having little trouble with it. TBH, we have not had a single issue with browser compatibility, and we test regularly on IE 6/7/8, FF3/2, Safari 4/5 and Chrome latest.The only disadvantage that we have had so far is that it can be challenging to track down issues caused by loading a resource twice, or failing to load one at all. Since the act of loading resources is programmatic, it is subject to programmatic errors, and unlike adding the tags directly to the HTML, it can be hard to see what the exact loading order is. However, this issue can be largely overcome by using a library with some form of dependency management system such as closure, or dojo.
EDIT: I have made a few comments to this nature, but I thought it best to summarize in my answer:
There are some problems with dojo.require() and jQuery.getScript() (both which ultimiately perform an ajax request and eval).
它的优点是您不需要在每个 HTML 文件中重复脚本引用。缺点是浏览器必须先获取并执行主 JavaScript 文件,然后才能加载其他文件。
It has the advantage that you don't need to repeat the script references in each HTML file. The disadvantage is that the browser must fetch and execute the main javascript file before it may load the others.
我想我能想到的一个优点是,如果您在多个页面上使用这些脚本,您只需要记住包含一个脚本,并且它可以节省一些空间。
I guess one advantage I could think of would be if you use these scripts on multiple pages, you only have to remember to include one script, and it saves some space.
在 Google PageSpeed,他们强烈建议您不要使用此技术,因为它会使速度变慢。除了在所有其他脚本之前顺序加载 script.js 之外,还有另一个问题:
At Google PageSpeed, they highly discourage you from using this technique, because it makes things slower. Apart from the sequential loading of your script.js before all the others, there's another catch:
这也可能是 SEO 公司的建议,如果可能的话,让 head 元素更短,这样独特的内容更接近文档的顶部 - 也创造了更高的文本与 HTML 的比率。尽管总而言之,这听起来确实不是一个很好的方法;尽管这会使维护更加耗时,但如果认为完全有必要减少头元素大小,更好的方法可能是将 javascript 压缩为单个 .js 文件,将 css 压缩为单个 .css 文件。
It's also possible that this was written as a recommendation by an SEO firm to make the head element shorter if possible, so unique content is closer to the top of the document - also creating a higher text-to-HTML ratio. Though it does sound, all-in-all, like not a very good way of doing this; though it would make maintenance more time-consuming, a better approach would probably be to condense javascript into a single .js file and css into a single .css file, if it were deemed utterly necessary to reduce head element size.
一个很大的缺点是,将
script
添加到 head 中会暂停文档的处理,直到这些脚本完全下载、解析并执行(因为浏览器认为它们可能使用document.write)。 - 这会损害反应能力。
现在,建议您将脚本标签放在
之前。当然,这不可能 100% 成功,但如果您使用 unobtrusve Javascript(正如您应该的那样),所有脚本都可以在文档末尾重新定位。
HTML5 提出了 async 属性,该属性建议浏览器仅在主文档加载后执行脚本。这是许多浏览器中插入脚本的脚本的行为,但并非所有浏览器都如此。
我建议不惜一切代价反对使用
document.write
。即使没有它,这也会导致向服务器发出一个额外的请求。 (我们喜欢最大化请求数量,例如使用 css sprites.)是的,正如其他人之前提到的,如果禁用脚本,您的页面将在没有 CSS 的情况下显示(这使得它可能无法使用)。
A great disadvantage is that adding
script
s into head will pause the processing of the document until those scripts were completely downloaded parsed and executed (because the browser thinks they may usedocument.write
). - This will hurt responsiveness.Now days it is recommended that you put your script tags right befo
</body>
. Of course this is not possible 100% of times, but if you are using unobtrusve Javascript (as you should), all scripts can be respositioned at the end of the document.HTML5 came up with the
async
attribute which suggests the browser only to execute the scripts after the main document has been loaded. This is the behaviour of script-inserted scripts in many browsers, but notin all of them.I advise against using
document.write
at all costs. Even without it, this results in one extra request towards the server. (We like to inimze the number of requests, for example with css sprites.)And yes, as others mentioned earlier, if scriping is disabled your page will be shown without CSS (which makes it potentially unusable).
如果 JavaScript 禁用 -
如果您将 JavaScript 初始化函数放在页面底部(这是一个很好的做法)并将 CSS 与 JavaScript 链接起来,则可能会在 CSS 加载之前造成一些延迟(在短时间内会看到损坏的布局)。
If JavaScript is disabled -
<script> and <link>
elements won't be added at all.If you place JavaScript init functions at the bottom of your page (which is a good practice) and link CSS with JavaScript, it may cause a some delay before CSS loads (broken layout will be visible for a short time).