Critical rendering path

Bytes -> Characters -> Tokens -> nodes -> Object Model
HTML markup is transformed into a Document Object Model (DOM), CSS markup is transformed into a CSS Object Model (CSSOM)
DOM and CSSOM are independent data structures

Document Object Model (DOM)

CSS Object Model (CSSOM)

While the browser was construncting the DOM of our simple page, it encoutered a link tag in the head section of the document referencing an external CSS stylesheet: style.css. Anticipating that it will need this resource to render the page, it immediately dispatches a request for this resource.

Just as with HTML, we need to convert the received CSS rules into something that the browser can understand and work with.

The first step is for the browser to combine the DOM and CSSOM into a "render tree" that captures all the visible DOM content on the page, plus all the CSSOM style information for each node.

To construct the render tree, the browser roughly does the following:

  • Starting at the root of the DOM tree, traverse each visible node.
    • Some nodes are not visible at all, and are omitted since they are not reflected in the rendered output
    • Some nodes are hidden via CSS and are also omitted from the render tree
  • For each visible node find the appropriate matching CSSOM rules and apply them
  • Emit visible nodes with content and their computed styles.

'visibility: hidden' is different from 'display: none'
'visibility: hidden' makes the element invisible, but the element still occupies space in the layout
'display: none' removes the element entirely from the render tree such that the element is invisible and is not part of layout


By default, CSS is treated as a render blocking resource
Media types and media queries allow us to mark some CSS resources as non-render blocking
All CSS resources, regardless of blocking or non-blocking behavior, are downloaded by the browser

<link href="style.css"    rel="stylesheet">
<link href="style.css"    rel="stylesheet" media="all">
<link href="portrait.css" rel="stylesheet" media="orientation:portrait">
<link href="print.css"    rel="stylesheet" media="print">
  • The first declaration is render blocking and matches in all conditions.
  • The second declaration is also render blocking: “all” is the default type and if you don’t specify any type, it’s implicitly set to “all”. Hence, the first and second declarations are actually equivalent.
  • The third declaration has a dynamic media query which will be evaluated when the page is being loaded. Depending on the orientation of the device when the page is being loaded, portrait.css may or may not be render blocking.
  • The last declaration is only applied when the page is being printed, hence it is not render blocking when the page is first loaded in the browser.

Adding interactivity with JavaScript

First, our script is executed at the exact point where it is inserted in the document. When the HTML parser encounters a script tag, it pauses its process of constructing the DOM and yields control over to the JavaScript engine; once the JavaScript engine has finished running, the browser then picks up from where it left off and resumes the DOM construction.

In other words, our script block can't find any elements later in the page because they haven't been processed yet.

Or, executing our inline script blocks DOM construction, which will also delay the initial render.

JavaScript execution can lead to significant delays in how quickly the browser can process and render our page on the screen:

  • The location of the script in the document is significant
  • DOM constrction is paused when a script tag is encountered and until the script has finished executing
  • JavaScirpt can query and modify the DOM and CSSOM
  • Javascript execution is delayed until the CSSOM is ready

Parser Blocking vs. Asynchronous JavaScript

By default, JavaScript execution is 'parser blocking': when the browser encounters a script in the document it must pause DOM construction, hand over the control to the JavaScript runtime and let the script execute before proceeding with DOM construction.

In the case of an external JavaScript file the browser will also have to pause and wait for the script to be fetched from disk, cache, or a remote server, which can add tens of thousands of milliseconds of delay to the critical rendering path.

Adding the async keyword to the script tag tells the browser that it should not block the DOM construction while it waits for the script to become available.

<script src="app.js" async></script>
2016/4/10 posted in  GoogleDevelopersWebFundamentals

Optimizing content efficiency

Text compression with GZIP

  • GZIP performs best on text-based assets: CSS, Javascript, HTML
  • All modern browsers support GZIP compresion and will automatically request it
  • Your server needs to be configured to enable GZIP compression
  • Some CDNs require special care to ensure that GZIP is enabled

There are cases where GZIP can increase the size of the asset. Typically, this happens when the asset is very small and the overhead of the GZIP dictionary is higher than the comression saving.

Validating cached responses with ETags

First, the browser checks the local cache and finds the previous response, unfortunately it cannot use it as the response has now "expired".

At this point it could simply dispatch a new request and fetch the new full response, but that's inefficient because if the resource has not changed then there is no reason to download the exact same bytes that are already in cache.

That's the problem that validation tokens, as specified in the ETag header, are designed to solve: the server generates and returns an arbitrary token which is typically a hash or some other fingerprint of the contents of the file. If the fingerprint is still the same then the resource has not changed and we can skip the download.

The client automatically provides the ETag token within the "If-None-Match" HTTP request header, the server checks the token against the current resource, and if it has not changed returns a "304 Not Modified" response which tells the browser that the response it has in cache has not changed and can be renewed for another 120 seconds.

Cache-Control

The best request is a request that does not need to communication with the server: a local copy of the response allows us to eliminate all network latency and avoid data charges for the data transfer.

"no-cache" and "no-store"

"no-cache": If a proper validation token (ETag) is present, no-cache will incur a roundtrip to validate the cached response, but can eliminate the download if the resource has not changed.

"no-store": It disallows the browser and all intermediate caches to store any version of the returned response. Everytime the user requests this asset, a request is sent to the server and a full response is downloaded each and every time.

"private" vs. "public"

"public": it can be cached, even if it has HTTP authentication associated with it, and even when the response status code isn't normally cacheable.

"private": can be cached by user's browser, but not by a CDN

"max-age"

specifies the maximum time in seconds that the fetched response is allowed to be reused for from the tiem of the request

max-age=60 // response can be cached and reused for the next 60 seconds

Invalidating and updating cached response

All HTTP requests made by the browser are first routed to the browser cache to check if there is a valid cached response that can be used to fulfill the request. If there is a match, the response is read from the cache and we eliminate both the network latency and the data costs incurred by the transfer.

We can change the URL of the resource and force the user to download the new response whenever its content changes.

2016/4/10 posted in  GoogleDevelopersWebFundamentals

Instruct search engines how your multi-device page is structured

Determine URL structure of your webpage

Responsive Web Design

serves the same HTML for one URL and uses CS media quries to determine how the content is rendered on the client side.

Desktop and Mobile: http://www.example.com/
Separate mobile site

redirects users to a different URL depending on the user-agent

Desktop: http://www.example.com/
Mobile: http://m.example.com/
Dynamic serving

serves different HTML for one URL depending on the user-agent

Desktop and Mobile: http://www.example.com/

The best approach we recommend is to use responsive web design

Using link[rel=canonical] and link[rel=alternate] when serving from separate URLs

Serving similar contents on a desktop version and a mobile version at different URLs may cause confusion for both users and sertch engines because it's not obvious for viewers that they are intended to be identical. You should indicate:

  • Contents of those 2 URLs are identical
  • Which is mobile version
  • Which is desktop version

This information can help search engines better index content and ensure users find what they're looking for in a format that works for their device.

Use link[rel=alternate] for desktop version

On desktop page, indicate that there's a mobile version on a different URL by adding link tag with rel="alternate" pointing to mobile version URL with href. By adding media attribute with value of "only screen and (max-width: 640px)" will help search engines understand that this is explicitly targeting small screens.

<title>...</title>
<link rel="alternate" media="only screen and (max-width: 640px)" href="http://m.example.com/">
Use link[rel=canonical] for mobile version

On mobile specific pages, indicate that there's a desktop version at a different URL by adding link tag with rel="canonical" pointing to desktop version URL with href.

<title>...</title>
<link rel="canonical" href="http://www.example.com/">

Use Vary HTTP header for device oriented serving site

By letting search engines know that the content varies depending on user agent, they can optimize search results for the user agent that is sending queries.

Use Vary HTTP header
HTTP/1.1 200 OK
Content-Type: text/html
Vary: User-Agent
Content-Length: 5710
2016/4/10 posted in  GoogleDevelopersWebFundamentals