What is realprogress.js?
It's a very light JavaScript library providing website loading progress that's realitvely...
In some cases, it's not 100% accurate, but it still tells the viewer whether something is actually happening on your page. At the very least, it won't update when you have no internet connection.
Live demo
Use Chrome DevTools to apply network throttling and/or disable cache to better see how it works.
YouTube demo
A video showcasing realprogress with different throttling settings.
Installation
npm install realprogress
or
git clone https://github.com/hdodov/realprogress.js
How does it work?
Stuff like ProgressBar.js by Kimmo Brunfeldt trick the viewer by incrementing the progress value at random times by a random amount to simulate progress, even if there's no progress at all. What realprogress does is it scans the page's HTML for the different resources that have to be downloaded and emits a signal upon their onload
event.
Here's precisely what happens:
-
When realprogress is initialized, an
XMLHttpRequest
is fired withdocument.location.href
as the URL. This gets the full HTML of the page it has been loaded on.The reason something like
document.documentElement.innerHTML
isn't used is because it doesn't provide the full HTML. It will return just the HTML up to this point. It would be something like this:<head> <title>realprogress</title> <script type="text/javascript" src="../lib/realprogress.js"></script></head>
-
After realprogress is loaded and whenever the
onload
event of a<script>
is fired, aload
listener is attached to all<link>
,<script>
and<img>
elements to know when they're ready. The reason a check for new elements is made after theload
of each<script>
is because they block HTML parsing. This means that everything after the tag is parsed only after the script itself has loaded. -
When the request from #1 returns a response, the HTML is processed by a regular expression which finds all
<link>
tags withhref
attribute,<script>
withsrc
and<img>
withsrc
. This way, we find out how much resources we're expecting. -
After the HTML has been searched, the
onProgress
event starts dispatching the progress value whenever a resource has loaded. This value ranges from0
to1
. -
The end of all loading is marked by
window.onload
. When it fires, realprogress dispatches itsonProgress
with a value of1
and its ownonLoad
.
Usage
It's recommended to include the library as close to the top of the <body>
as possible (preferably at the top) and the script using it should be immediately after. You can even put it at the top of the <head>
.
Tip: When you handle the onProgress
event, check whether your progress bar (or whatever is visualizing the progress) exists. That's because <script>
tags block HTML parsing, so if your script is above the bar, it would not yet exist.
API
RealProgress.init = function (options) {};
RealProgress.onProgress = function (progress) {
// progress - value ranging from 0 to 1
};
RealProgress.onResourceLoad = function (resource) {
// resource - loaded resource's href/src attribute
};
RealProgress.onLoad = function (uncaptured) {
// uncaptured - array of resources that were found in the source code, but their "load" event wasn't captured
// fired when `window.onload` is dispatched
};
Options
Options are passed to the init()
metod.
-
regex: function (tag, attribute)
- You could provide a custom regular expression for searching resources in the source code. It should return aRegExp
object that matches the giventag
andattribute
. -
untracked: Array
- All resources you don't want to affect the progress. Can contain strings or regular expressions. If a string is found, it must match the whole resource name. If it's regex, it simply has to match.Tip: You could check which resources fail to be captured via the
onLoad
method and add them here, so that they're not tracked at all. This would improve the accuracy of your loading bar. -
tags: Object
- Which tags and attributes to search in the source code. Tag names should be the keys and their attributes should be the values. Those same pairs are passed to the function getting the regex above. Defaults to:{ "link": "href", "iframe": "src", "source": "src", "script": "src", "img": "src" }
Warning: You should always have
"script": "src"
or some resources might not be tracked.
Keep in mind that...
-
It uses a regular expression! Be careful with very large HTML files.
-
The
XMLHttpRequest
should be fast, because it requests the very document that it's been initialized from, which is likely to be cached. However, it's not instantaneous, meaning that some resources (probably in the<head>
) might be loaded before the library and not counted towards the progress. -
<script>
tags block HTML parsing until they're loaded! Let's say I have this markup:<img src="pic1.jpg"> <script src="script.js"></script> <img src="pic2.jpg"> <img src="pic3.jpg">
The progress of
pic1
would be effectively tracked, butpic2
andpic3
will have theload
listener attached to them only afterscript.js
has loaded. That's because everything after the</script>
tag is parsed after the contents of the<script>
are present. To avoid this, simply put your<script>
tags at the bottom of the<body>
. -
Tracking the progress of scripts will not be accurate.
😢 It's because of the previous bullet point. If you have this markup:<script src="script1.js"></script> <script src="script2.js"></script> <script src="script3.js"></script>
script2
will only be tracked afterscript1
has loaded andscript3
- afterscript2
. Ifscript2
andscript3
load beforescript1
, theirload
events would have been triggered before realprogress had the chance to add an event listener to them.