Apr 15

结论:

whatwg开发者版规范中说,关于HTML的parsing,scripting,styling的规则,因为各种原因必然是分散在规范的各处。

内嵌的script和style会blocking,包括blocking文档的parsing,blocking后面的没用async属性的外部script的fetch,blocking后面的link的外部style的fetch。

外部资源形式的script和style,就更复杂了。
在文档解析到link元素并且开始fetch外部style的时候,会blocking,后面没用async属性的外部script的fetch和后面link的外部style的fetch。
其他情况看示意图吧,看不懂后面有解释。

With <script>, parsing is interrupted by fetching and execution. With <script defer>, fetching is parallel to parsing and execution takes place after all parsing has finished. And with <script async>, fetching is parallel to parsing but once it finishes parsing is interrupted to execute the script. The story for <script type="module"> is similar to <script defer>, but the dependencies will be fetched as well, and the story for <script type="module" async> is similar to <script async> with the extra dependency fetching.

也就是默认情况下,link元素和script元素的导入外部资源都是sync和blocking parsing的方式。

script有了async和defer属性后,可以并行读取parallel fetch外部资源,但是async也可能会blocking parsing,因为async只是异步了fetch的过程,execution的过程还是sync的。

只有defer是parallel fetch并且non-blocking的,直到文档解析完成才会execution脚本,不会阻塞解析。

还有这只是规范中的理想情况,实际UA,也就是浏览器之类的,还会有各种诡异的hacks。

@import css和link css的根本区别是,前者是CSS规范中加载外部CSS的机制,后者是HTML规范中加载外部CSS的机制。使用link加载CSS是并行下载,而@import则不一定。比如在外部CSS内再@import另一个css,则是串行下载。默认情况下,CSS加载完后都会阻塞文档解析渲染render blocking。Avoid CSS imports的原因是, introduce additional roundtrips into the critical path: the imported CSS resources are discovered only after the CSS stylesheet with the @import rule itself has been received and parsed 。GOOGLE建议尽量Inline render-blocking CSS,因为可实现a “one roundtrip” critical path length。就是为了加快解析渲染,@import 会降低渲染效率,inline则提高。

具体可以看这几个文章。
Intent to Implement: Block parser on external CSS
https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/ZAPP8aTnyn0
阻塞渲染的 CSS
https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-blocking-css?hl=zh-cn
避免使用 CSS import
https://developers.google.com/web/fundamentals/performance/critical-rendering-path/page-speed-rules-and-recommendations
Loading CSS without blocking render
http://keithclark.co.uk/articles/loading-css-without-blocking-render/
link elements block DOM parsing too
https://remysharp.com/2011/06/08/link-elements-block-dom-parsing-too

规范中相关内容的汇总:

翻译得好痛苦,觉得不好请见谅。

Scripting

Scripts allow authors to add interactivity to their documents.
脚本允许作者给他们的文档增加交互性。

The script element allows authors to include dynamic script and data blocks in their documents.
script元素允许作者包含动态脚本和数据块在它们的文档中。

type属性的三种情况:

Omitting the attribute, or setting it to a JavaScript MIME type, means that the script is a classic script, to be interpreted according to the JavaScript Script top-level production. Classic scripts are affected by the charset, async, and defer attributes. Authors should omit the attribute, instead of redundantly giving a JavaScript MIME type.
省去这个属性,或者设置它为一个JavaScript MIME type,意思是这个脚本是个classic script,按照the JavaScript Script top-level production解译。Classic scripts受charset, async, defer属性影响。当脚本是JavaScript MIME type时,作者应省写这属性,因为多余。

Setting the attribute to an ASCII case-insensitive match for the string “module” means that the script is a module script, to be interpreted according to the JavaScript Module top-level production. Module scripts are not affected by the charset and defer attributes.
设置这属性值是”module”,不区分大小写,意思是这是个module script,按照the JavaScript Module top-level production解译。Module scripts不受charset和defer属性影响。

Setting the attribute to any other value means that the script is a data block, which is not processed. None of the script attributes (except type itself) have any effect on data blocks. Authors must use a valid MIME type that is not a JavaScript MIME type to denote data blocks.
设置这个属性值为前两种情况外的其他值,意思是这个脚本是个data block,它是不加工处理的。除了type属性外的其他script属性在这种情况下都无效。作者必须用一个valid MIME type而不是JavaScript MIME type去表示data blocks。

Classic scripts and module scripts may either be embedded inline or may be imported from an external file using the src attribute, which if specified gives the address of the external script resource to use. If src is specified, it must be a valid non-empty URL potentially surrounded by spaces. The contents of inline script elements, or the external script resource, must conform with the requirements of the JavaScript specification’s Script or Module productions, for classic scripts and module scripts respectively.
Classic scripts 和 module scripts 可以嵌入行内或使用src属性导入外部文件,通过给src属性指定外部脚本资源地址的方式。如果src指定了值,它必须是valid non-empty URL potentially surrounded by spaces。script元素内嵌的内容,或者外部脚本资源,必须符合JavaScript规范关于Script or Module productions的要求。

When used to include data blocks, the data must be embedded inline, the format of the data must be given using the type attribute, and the contents of the script element must conform to the requirements defined for the format used. The src, charset, async, defer, crossorigin, and nonce attributes must not be specified.
当用来包含data blocks的时候,数据必须是嵌入行内的,数据的格式必须使用type属性给出,并且内嵌的内容必须符合数据格式要求。src, charset, async, defer, crossorigin, nonce属性不是必须指定。

The charset attribute gives the character encoding of the external script resource. The attribute must not be specified if the src attribute is not present, or if the script is not a classic script. (Module scripts are always interpreted as UTF-8.) If the attribute is set, its value must be an ASCII case-insensitive match for one of the labels of an encoding, and must specify the same encoding as the charset parameter of the Content-Type metadata of the external file, if any.
charset属性是用来指明外部脚本资源的字符编码。这个属性不是必须指定的,如果src属性不存在,或者脚本不是classic script。Module scripts永远作为UTF-8编码字符解译。如果要设置这个属性,它的值必须是一个encoding标记,不区分大小写,如果外部文件有Content-Type metadata的charset参数,则这个属性值必须和它一致。

The async and defer attributes are boolean attributes that indicate how the script should be evaluated. Classic scripts may specify defer or async; module scripts may specify async.
async和defer属性是布尔属性,它们表明了脚本将如何evaluated。Classic scripts可以指定defer和async,module scripts可以指定async。

There are several possible modes that can be selected using these attributes, and depending on the script’s type.
使用这些属性的方式依赖于脚本的类型。

For classic scripts, if the async attribute is present, then the classic script will be fetched in parallel to parsing and evaluated as soon as it is available (potentially before parsing completes). If the async attribute is not present but the defer attribute is present, then the classic script will be fetched in parallel and evaluated when the page has finished parsing. If neither attribute is present, then the script is fetched and evaluated immediately, blocking parsing until these are both complete.
对于classic scripts,如果async属性存在,那么传统脚本将在文档解析时并行的读取,一旦它读取完成可用了,就立即evaluated,就是说可能在文档解析完成前,脚本已经fetched并evaluated了。如果async属性不存在,但是defer属性存在,那么传统脚本将在文档解析时并行的读取,然后直到文档解析完成后再evaluated。如果两个都不存在,那么解析到脚本元素时会暂停文档解析,即阻塞解析blocking parsing,开始读取脚本,读取完成后立即运行计算,然后继续解析。

For module scripts, if the async attribute is present, then the module script and all its dependencies will be fetched in parallel to parsing, and the module script will be evaluated as soon as it is available (potentially before parsing completes). Otherwise, the module script and its dependencies will be fetched in parallel to parsing and evaluated when the page has finished parsing. (The defer attribute has no effect on module scripts.)
对于module scripts,如果async属性存在,那么模块脚本和所有它依赖的模块都会在文档解析时并行的读取,直到读取完成开始运行计算。除此之外的情况,脚本会在页面解析完成后才开始读取和运行。

示意图:

The nonce attribute represents a cryptographic nonce (“number used once”) which can be used by Content Security Policy to determine whether or not the script specified by an element will be executed. The value is text.
nonce属性表示一个加密随机数(“一次性数字”),它被用于一种内容安全策略确定无论如何脚本都将运行。值是文本。

src (source)

When used to include dynamic scripts, the scripts may either be embedded inline or may be imported from an external file using the src attribute. If the language is not that described by “text/javascript”, then the type attribute must be present, as described below. Whatever language is used, the contents of the script element must conform with the requirements of that language’s specification.
当用来包含动态脚本的时候,脚本可以嵌入在行内,或者可以使用src属性导入一个外部文件。如果这个语言并非被描述为”text/javascript”,那么type属性是必须存在的。不管用什么脚本语言,这个script元素的内容必须符合该语言的规范。

When used to include data blocks (as opposed to scripts), the data must be embedded inline, the format of the data must be given using the type attribute, the src attribute must not be specified, and the contents of the script element must conform to the requirements defined for the format used.
当用来包含数据块,数据必须嵌入在行内,数据的格式必须使用type属性指定,src属性不能指定,script元素的内容必须符合定义的格式。

The type attribute gives the language of the script or format of the data. If the attribute is present, its value must be a valid MIME type. The charset parameter must not be specified. The default, which is used if the attribute is absent, is “text/javascript”.
type属性给出脚本是什么语言或者数据是什么格式。如果type属性存在,它的值必须是有效的MIME类型。charset属性不能指定。默认情况,如果type属性没有,则是”text/javascript”。

The src attribute, if specified, gives the address of the external script resource to use. The value of the attribute must be a valid non-empty URL potentially surrounded by spaces identifying a script resource of the type given by the type attribute,
src属性,用来指定外部脚本资源的地址。属性值必须是valid non-empty URL potentially surrounded by spaces,能够识别为指定类型的脚本资源,

The async and defer attributes are boolean attributes that indicate how the script should be executed. The defer and async attributes must not be specified if the src attribute is not present.
async和defer属性是布尔属性,它们表明脚本将如何执行。如果src属性不存在,则不能有defer和async。

There are three possible modes that can be selected using these attributes. If the async attribute is present, then the script will be executed asynchronously, as soon as it is available. If the async attribute is not present but the defer attribute is present, then the script is executed when the page has finished parsing. If neither attribute is present, then the script is fetched and executed immediately, before the user agent continues parsing the page.
有三种可能的模式可以使用这些属性。如果async属性存在,那么脚本将以异步的方式执行,一直到它是可用的时候就执行。如果async属性不存在,但是defer属性存在,那么脚本将在页面解析完成后执行。如果两个属性都不存在,那么UA在解析到script元素时就会读取脚本并立即执行,再继续解析页面,即为同步阻塞synchronous blocking behavior。

The exact processing details for these attributes are, for mostly historical reasons, somewhat non-trivial, involving a number of aspects of HTML. The implementation requirements are therefore by necessity scattered throughout the specification.
对于这些属性的确切处理详情,主要是历史原因,有点特殊意义,涉及HTML的许多方面。因此解析器实现的需求必然分散在规范的各处。

The defer attribute may be specified even if the async attribute is specified, to cause legacy Web browsers that only support defer (and not async) to fall back to the defer behavior instead of the synchronous blocking behavior that is the default.
即使script元素指定了async属性,defer属性也可能被指定,这是浏览器遗留原因造成的,浏览器只支持defer而不支持async,这种情况退回到用defer行为替代默认的同步阻塞synchronous blocking行为。

The crossorigin attribute is a CORS settings attribute.
crossorigin属性是一个CORS设置属性。

Changing the src, type, charset, async, defer, and crossorigin attributes dynamically has no direct effect;
动态的改变这些src, type, charset, async, defer, crossorigin属性是没有直接影响的。

script.text [ = value ]
Returns the contents of the element, ignoring child nodes that aren’t Text nodes.
script.text返回元素的内容,忽略所有不是Text节点的子节点。

Can be set, to replace the element’s children with the given value.
可以给script.text赋值,替换元素的孩子。

When inserted using the document.write() method, script elements execute (typically synchronously), but when inserted using innerHTML and outerHTML attributes, they do not execute at all.
当使用document.write()插入脚本时,script元素通常同步执行,但是使用innerHTML和outerHTML属性插入时,根本不会执行。

Restrictions for contents of script elements
script元素内容的限制规定

"<!--" 要写成 "<\!--", "<script" 要写成 "<\script", and "</script" 要写成 "<\/script"

像这样的写法
if (x<!--y) { ... }
if ( player<script ) { ... }

要改成
if (x < !--y) { ... }
if (!--y > x) { ... }
if (!(--y) > x) { ... }
if (player < script) { ... }
if (script > player) { ... }

写JavaScript养成空格和圆括号的习惯啊。

如果script元素的src属性设置了有效值,那么元素内容的脚本不会执行。

Styling

The style element allows authors to embed style information in their documents. The style element is one of several inputs to the styling processing model.
style元素允许作者嵌入样式信息在它们的文档。style元素是若干种输入样式方法中的一种。

Interactions of styling and scripting
样式和脚本的相互影响

Style sheets, whether added by a link element, a style element, an <?xml-stylesheet?> PI, an HTTP Link header, or some other mechanism, have a style sheet ready flag, which is initially unset.
样式表,无论以a link element, a style element, an <?xml-stylesheet?> PI, an HTTP Link header,或者一些其他机制添加到文档,都有一个样式表的准备状态标记,初始是unset。

When a style sheet is ready to be applied, its style sheet ready flag must be set. If the style sheet referenced no other resources (e.g., it was an internal style sheet given by a style element with no @import rules), then the style rules must be immediately made available to script; otherwise, the style rules must only be made available to script once the event loop reaches its update the rendering step.
当一个样式表已经准备好可以用时,那一定set了它的ready flag。如果样式表没有引用其他资源,例如,它是通过style元素给出的内部样式表并且没有@import rules,那么这个样式规则一定是可立即给脚本使用的。除此以外的情况,只有在渲染步骤中样式规则完成更新的事件到达时才可以给脚本使用。

A style sheet in the context of the Document of an HTML parser or XML parser is said to be a style sheet that is blocking scripts if the element was created by that Document’s parser,
一个在HTML解析器的文档上下文中的样式表,是说这个样式表会阻塞脚本,如果这个元素是由文档的解析器创建,

and the element is either a style element or a link element that was an external resource link when the element was created by the parser,
并且这个元素是一个style元素或者是一个链接了外部资源的link元素,当这个元素被解析器创建的时候,

and the element’s style sheet was enabled when the element was created by the parser,
并且这个元素的样式表是启用的,当这个元素被解析器创建的时候,

and the element’s style sheet ready flag is not yet set,
并且这个元素的样式表的ready flag还没设置,

and, the last time the event loop reached step 1, the element was in that Document,
并且最后一次event loop到达步骤一,这个元素是在文档中,

and the user agent hasn’t given up on that particular style sheet yet.
并且UA还没有放弃这个样式表。

A user agent may give up on a style sheet at any time.
UA可能随时放弃一个样式表。

Giving up on a style sheet before the style sheet loads, if the style sheet eventually does still load, means that the script might end up operating with incorrect information.
在样式表加载前放弃这个样式表,如果最终它还是加载了,意思是脚本可能会用不正确的信息结束操作。

or example, if a style sheet sets the color of an element to green, but a script that inspects the resulting style is executed before the sheet is loaded, the script will find that the element is black (or whatever the default color is), and might thus make poor choices .
例如,如果一个样式表设置一个元素的颜色是绿色,但是在这个样式加载完成前,脚本已经完成了查找样式的行为,这个脚本发现这个元素的颜色是黑色,或者其他默认颜色,可能因此造成错误的选择。

Links

Links are a conceptual construct, created by a, area, and link elements, that represent a connection between two resources, one of which is the current Document. There are two kinds of links in HTML:
链接是一种概念机制,通过创建a,area,link元素,它表示在两种资源之间建立联系,其中一个是当前文档。在HTML里是两种链接类型:

Links to external resources
These are links to resources that are to be used to augment the current document, generally automatically processed by the user agent.
链接外部资源
链接的资源是用来扩充当前文档,通常由UA自动处理。

Hyperlinks
These are links to other resources that are generally exposed to the user by the user agent so that the user can cause the user agent to navigate to those resources, e.g. to visit them in a browser or download them.
超链接
链接到其他资源通常是通过UA提供给用户使用的,方便用户导航到其他资源,比如在浏览器中访问或下载它们。

href(hyperlink reference)rel(relationship)

For link elements with an href attribute and a rel attribute, links must be created for the keywords of the rel attribute, as defined for those keywords in the link types section.
link元素有一个href属性和一个rel属性,link必须创建指定关键字为rel属性值,在link类型章节由rel关键字的定义。

A hyperlink can have one or more hyperlink annotations that modify the processing semantics of that hyperlink.
一个超链接可以有多个注释用来修改超链接的处理语义。

Links created by a and area elements
通过a和area元素创建链接
a,area元素的href属性和rel属性是可选的。如果没有href则不创建超链接,如果没有rel属性或值,则表示当前文档和链接的那个资源没有特定关系。

The link element allows authors to link their document to other resources.
link元素允许作者链接文档到其他资源。

The destination of the link(s) is given by the href attribute, which must be present and must contain a valid non-empty URL potentially surrounded by spaces. If the href attribute is absent, then the element does not define a link.
这个目标地址是由链接的href属性指定,这个属性是必须有并且必须包含一个有效的非空URL。如果没有href属性,那么这个元素没有定义一个链接。

A link element must have a rel attribute. NOTE:If the rel attribute is used, the element is restricted to the head element.
一个link元素必须有一个rel属性。注意如果用rel属性,这个元素是受限于head元素。

The types of link indicated (the relationships) are given by the value of the rel attribute, which, if present, must have a value that is a set of space-separated tokens. The allowed keywords and their meanings are defined in a later section. If the rel attribute is absent, has no keywords, or if none of the keywords used are allowed according to the definitions in this specification, then the element does not create any links.
link的类型是通过rel属性的值给出,如果rel出现,必须有值,值是一组以空格分隔的标记集合,值允许使用的关键字后面章节定义。如果rel属性没有,值没有关键字,或者值不是规范定义的关键字,那么这个元素不创建任何link。

Two categories of links can be created using the link element: Links to external resources and hyperlinks.
这个link元素可以使用两种link种类:链接到外部资源或者超链接。

https://html.spec.whatwg.org/multipage/
https://w3c.github.io/html/
http://www.html5rocks.com/zh/tutorials/webcomponents/imports/

 

written by panhezeng \\ tags: ,

©panhezeng for 阿潘道, 2006-2017. 原文地址:http://apsay.com/?p=1653
本文遵循署名-非商业性使用共享协议,转载请注明。

Leave a Reply