This is the second part of a series. Read technical background about how to load scripts fast in the first part. You will find some real world patterns that should be avoided in part 3.

Size of scripts matters two times

Bigger scripts take longer to download and execute. Minification and compression of script files is therefore mandatory (but very often forgotten!). To be really fast try to stay below 14kb in file size. That is the amount of data that usually can be transferred in the first package round-trip of the underlying TCP connection. Additionally bytes will be transferred afterwards in the next round-trip which causes a unproportionally high slowdown of the transfer time. You can read more about this in the great blog of Ilya Grigorik.

DemoUps has invested a lot of effort to stay below this limit. Our performance critical stage2.js can get as small as 11kb. This is quite an achievement compared to all the work it is doing. We achieved the tiny file size by avoiding any of the big frameworks, forking any mini library we use and stripping away every dispensable code from them. In example we do not use jQuery but rely on native browser functionality and use the tiny (3kb in size) but great Preact library for rendering elements.

See a DemoUp example that illustrates how much script size can impact evaluation time of scripts.

Old jQuery based implementation of DemoUps time-critical script. Evaluation time for this 45kb size chunk of code is 60ms.

Current preact based implementation of the same functionality. Size is down to 11kb. Execution time is a magnitude faster with 9ms.

DemoUp was able to make execution of its script faster by a magnitude by optimizing their main script for size. Note that this times are taken on a fast workstation PC. There are many times slower CPUs used out there in the mobile world and they might be busy with other work too. Usually there are many more scripts in one page and the evaluation times sum up. That is why:

File sizes matter even for the CPU

and

You might not need jQuery or React. Learn about alternative mini libraries. We recommend Preact.

Throwing away time by waiting for the rest

When having created a script which loads fast and executes as fast as DemoUps stage2, there is another slowdown that developers might run into. From jQuery we have learned to do our work inside of the ready function, like this:

Using the ready function that code is not executed before the browser fires the DOMContentLoaded event, which indicates that DOM tree is build up completely so that all DOM selectors will find their targets.

However, this event may fire seconds after the browser has started rendering the page due to blocking script tags or and/or a large DOM tree. This causes an ugly effect when the page can already be seen and starts to shift around its content during initialization of some components.

Waiting for the whole page to be ready is unnecessary, all you really need to be initialized are the DOM elements your script is actually doing work on.

That is the approach DemoUp uses. When it wants to render a play button, it does just wait for the containing element to be loaded. It will render the play button when this has happened.

This is an example of a page loading process which involves slow loading of scripts and rendering on DOMContentLoaded. The result is not just slow loading but intensive shifting around of content during page load what is ugly and a usability issue. Note that no user scrolling is done on the page, the change of page height is created by the loading process.

Summary:

All in all DemoUp uses any optimization you can think of to be really fast. When shops integrate our code as we recommend them to, we often can render our play button faster than the other components on the screen. The DemoUp play button can feel like a native element of a website although being conditionally injected by an external script.

Read technical background about how to load scripts fast in the first part of this series. You will find some real world patterns that should be avoided in part 3.