Skip to content

Instantly share code, notes, and snippets.

@brendo
Created February 18, 2012 04:11
Show Gist options
  • Save brendo/1857345 to your computer and use it in GitHub Desktop.
Save brendo/1857345 to your computer and use it in GitHub Desktop.
Using <script type='text/html'>

Using <script type='text/html'>

While looking for a more manageable way to maintain my Mustache templates, I came across the icanhaz, which promotes putting your templates in your DOM using:

<script type='text/html' id='your-template>
    // Template in here
</script>

Being a bit of a performance nut, I was nervous about putting my templates into the DOM like this for a couple of reasons:

  1. Typically your HTML can't be cached as long as your Javascript
  2. If I added templates to the DOM, would it affect my page load time

I asked @souders about this on Twitter, and his reply was try it and see, so here this gist is.

My test case is very simple, I want to see the effect that the text/html attribute has on my page being 'ready'. To do this I'm using a small snippet that tracks compares the current time the snippet has been executed, and when the page started to load using the Navigation Timing API.

The baseline:

<script src='http://1.cuzillion.com/bin/resource.cgi?type=js&sleep=2&expires=-1'></script>
<script src='http://1.cuzillion.com/bin/resource.cgi?type=js&sleep=3&expires=-1'></script>
<script src='http://1.cuzillion.com/bin/resource.cgi?type=js&sleep=4&expires=-1'></script>
<script src='http://1.cuzillion.com/bin/resource.cgi?type=js&sleep=5&expires=-1'></script>

Firefox 10.0.2 Page loading time: 5541 Chrome 17 Page loading time: 5459

Lets add type='text/html'

<script src='http://1.cuzillion.com/bin/resource.cgi?type=js&sleep=2&expires=-1' type='text/html'></script>
<script src='http://1.cuzillion.com/bin/resource.cgi?type=js&sleep=3&expires=-1' type='text/html'></script>
<script src='http://1.cuzillion.com/bin/resource.cgi?type=js&sleep=4&expires=-1' type='text/html'></script>
<script src='http://1.cuzillion.com/bin/resource.cgi?type=js&sleep=5&expires=-1' type='text/html'></script>

Firefox 10.0.2 Page loading time: 73 Chrome 17 Page loading time: 27

So awesome right? Well sorta. While my page according to the timing spec is relatively instant, Firefox was displaying loading indicators for quite some time, so I thought I'd dig a little deeper into why. This wasn't the case in Chrome though, the page said it loaded in 23ms, and the interface also reflected this.

The inspectors

To find out what was happening, I used Firebug's Net panel and Chrome's Network panel and the results were interesting.

Firebug Net Panel

Chrome Network Panel

So even though the type is set to text/html, Firefox is still loading each of the src attributes, where Chrome does not. To make sure that it wasn't Firebug who was lying to me, I thought I'd use Firefox's Web Console to retest.

Firefox Web Console

Same deal, Firefox will load these resources regardless of the type on the <script> element.

So, where to from here?

Adding type='text/html' to <script> elements won't affect your onready event from firing, but on Firefox these resources will be loaded and to a user it will look like your page is still loading.

This made me more concerned, what if I place the Mustache templates before other assets on my site? Such as images or CSS? Will Firefox's loading of the scripts then block the other assets from executing?

I started with a clean slate by just adding some assets to my page (gif, jpg, png, one script and one CSS file) to see the result.

<img src='http://1.cuzillion.com/bin/resource.cgi?type=gif&sleep=2&n=1' />
<img src='http://1.cuzillion.com/bin/resource.cgi?type=jpg&sleep=2&n=1' />
<img src='http://1.cuzillion.com/bin/resource.cgi?type=png&sleep=2&n=1' />
<link rel='stylesheet' href='http://1.cuzillion.com/bin/resource.cgi?type=css&sleep=2&n=1' />
<script src='http://1.cuzillion.com/bin/resource.cgi?type=js&sleep=2&expires=-1'></script>

Firefox Test 2 initial results

Chrome Test 2 initial results

Firefox 10.0.2 Page loading time: 2563 Chrome 17 Page loading time: 2456

And then I added in the scripts from my first test before these 5 assets to see what affect it would have.

Firefox Test 2 real results

Chrome Test 2 real results

Firefox 10.0.2 Page loading time: 2727 Chrome 17 Page loading time: 2468

So in short, <script> elements with type='text/html' will still add to your page's load time in Firefox 10 and may even block additional assets from loading, but they won't in Chrome.

My original question to Steve also asked if the defer attribute would help if it did block. After a quick test of adding defer to the text/html scripts, I can answer no, it doesn't help at all.

Did I miss something? Tell me

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Script onLoad - Test 1</title>
</head>
<body>
<script src='http://1.cuzillion.com/bin/resource.cgi?type=js&sleep=2&expires=-1' type='text/html'></script>
<script src='http://1.cuzillion.com/bin/resource.cgi?type=js&sleep=3&expires=-1' type='text/html'></script>
<script src='http://1.cuzillion.com/bin/resource.cgi?type=js&sleep=4&expires=-1' type='text/html'></script>
<script src='http://1.cuzillion.com/bin/resource.cgi?type=js&sleep=5&expires=-1' type='text/html'></script>
<script src='http://1.cuzillion.com/bin/resource.cgi?type=js&sleep=2&expires=-1'></script>
<script>
var now = +new Date(),
page_load_time = now - window.performance.timing.navigationStart;
console.log('Page loading time: ' + page_load_time);
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Script onLoad - Test 2</title>
</head>
<body>
<script src='http://1.cuzillion.com/bin/resource.cgi?type=js&sleep=2&expires=-1' type='text/html' defer ></script>
<script src='http://1.cuzillion.com/bin/resource.cgi?type=js&sleep=3&expires=-1' type='text/html' defer></script>
<script src='http://1.cuzillion.com/bin/resource.cgi?type=js&sleep=4&expires=-1' type='text/html' defer ></script>
<script src='http://1.cuzillion.com/bin/resource.cgi?type=js&sleep=5&expires=-1' type='text/html' defer ></script>
<img src='http://1.cuzillion.com/bin/resource.cgi?type=gif&sleep=2&n=1' />
<img src='http://1.cuzillion.com/bin/resource.cgi?type=jpg&sleep=2&n=1' />
<img src='http://1.cuzillion.com/bin/resource.cgi?type=png&sleep=2&n=1' />
<link rel='stylesheet' href='http://1.cuzillion.com/bin/resource.cgi?type=css&sleep=2&n=1' />
<script src='http://1.cuzillion.com/bin/resource.cgi?type=js&sleep=2&expires=-1'></script>
<script>
var now = +new Date(),
page_load_time = now - window.performance.timing.navigationStart;
console.log('Page loading time: ' + page_load_time);
</script>
</body>
</html>
@ricardobeat
Copy link

When using <script type="text/html"> as a template container you are not going to set the src attribute, so what is the point of this test?

@DynamicField
Copy link

hello hi

@xgqfrms
Copy link

xgqfrms commented May 21, 2020

fallback

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment