Description
In rustdoc, we currently have a few, small scripts in the <head>
element, which we allow to be render-blocking because they affect styling:
<script id="default-settings" {# -#}
{% for k, v in layout.default_settings %}
data-{{k}}="{{v}}"
{%- endfor -%}
></script> {#- -#}
<script src="{{static_root_path | safe}}storage{{page.resource_suffix}}.js"></script> {#- -#}
<script src="{{page.root_path | safe}}crates{{page.resource_suffix}}.js"></script> {#- -#}
We also have some scripts that show up at the bottom of the page, including in particular the main JS:
<script src="{{static_root_path | safe}}main{{page.resource_suffix}}.js"></script> {#- -#}
{%- if layout.scrape_examples_extension -%}
<script src="{{static_root_path | safe}}scrape-examples{{page.resource_suffix}}.js"></script> {#- -#}
{%- endif -%}
{%- for script in page.static_extra_scripts -%}
<script src="{{static_root_path | safe}}{{script}}.js"></script> {#- -#}
{% endfor %}
{%- for script in page.extra_scripts -%}
<script src="{{page.root_path | safe}}{{script}}.js"></script> {#- -#}
{% endfor %}
Per this Stack Overflow answer, putting scripts at the bottom of the page was a common technique to prevent large scripts from blocking the page render while they download. Now, we can achieve the same result using the async
or defer
attributes on the script tag. That has the advantage that it allows the browser to start downloading the JS while it's still downloading and parsing the HTML.
defer
is more straightforward because it preserves script ordering and only runs the script once the DOM is ready. async
sometimes requires a little more finagling so the script can handle being run before the DOM is ready (usually you put the DOM-touching parts of the script in an event listener for DOMContentLoaded
.