{"id":128,"date":"2017-06-19T15:28:52","date_gmt":"2017-06-19T13:28:52","guid":{"rendered":"http:\/\/www.kopf.com.br\/kaplof\/?p=128"},"modified":"2017-06-19T19:17:50","modified_gmt":"2017-06-19T17:17:50","slug":"a-real-loading-indication-for-aurelia-and-requirejs","status":"publish","type":"post","link":"https:\/\/www.kopf.com.br\/kaplof\/a-real-loading-indication-for-aurelia-and-requirejs\/","title":{"rendered":"A &#8220;real&#8221; loading indication for Aurelia and RequireJS"},"content":{"rendered":"<p><a href=\"https:\/\/aurelia.io\">Aurelia<\/a> is a nice and modern JavaScript framework which simplifies much the development of single page applications. One of its most criticized weakness is the\u00a0 size of its libraries, which are usually loaded using RequireJS. Its tutorial comes with an explanation on how to <a href=\"https:\/\/aurelia.io\/hub.html#\/doc\/article\/aurelia\/framework\/latest\/contact-manager-tutorial\/9\">add a loading indication<\/a> to your application using nprogress. Nevertheless this <em>loading<\/em> will only kick in after Aurelia itself is fully loaded. This will exclude the most expensive part which is the download and process of at least 400kb of g-zipped JavaScript libraries. On a not so modern mobile device using a not so modern mobile network this can take some time.<\/p>\n<p>The below solution aims to display the progress while loading the RequireJS modules themselves. It is theoretically applicable to any application using RequireJS.<\/p>\n<p>&nbsp;<\/p>\n<h2>Measuring the progress<\/h2>\n<p>RequireJS will load asynchronously each individual module and its dependencies one-by-one. This is good as the browser won&#8217;t freeze while loading and also gives us a chance to measure the loading progress. For the sake of simplification, we can state that each individual module has the same weight meaning that if my application loaded 10 out of 20 modules, it has done 50% of its job. This simplification might not render a perfect linear time progress but I&#8217;ve also never seen any.<\/p>\n<p>RequireJS saves the list of loaded modules in the global variable:<\/p>\n<pre class=\"prettyprint lang-javascript\" data-start-line=\"1\" data-visibility=\"visible\" data-highlight=\"\" data-caption=\"\">window.require.s.contexts._.defined\r\n<\/pre>\n<p>The property <code class=\"prettyprint lang-javascript\" data-start-line=\"1\" data-visibility=\"visible\" data-highlight=\"\" data-caption=\"\">defined<\/code> is not an array but an object where every module is a property. Therefore simply using <code class=\"prettyprint lang-javascript\" data-start-line=\"1\" data-visibility=\"visible\" data-highlight=\"\" data-caption=\"\">defined.length<\/code> won&#8217;t work. To get the actual number of modules one have to count the number of properties using <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Object\/keys\">Object.keys<\/a> method which returns an array with all the object&#8217;s enumerable properties.<\/p>\n<pre class=\"prettyprint lang-javascript\" data-start-line=\"1\" data-visibility=\"visible\" data-highlight=\"\" data-caption=\"\">var loadedModules = Object.keys(window.require.s.contexts._.defined).length;\r\n<\/pre>\n<p>Now that we know how many modules were loaded so far we have to find out how many modules are expected to be loaded. The easiest way is to:<\/p>\n<ol>\n<li>Load your application in a browser<\/li>\n<li>Open the Developer Tools window<\/li>\n<li>Pause the execution<\/li>\n<li>Evaluate at the watch window the variable <code class=\"prettyprint lang-javascript\" data-start-line=\"1\" data-visibility=\"visible\" data-highlight=\"\" data-caption=\"\">Object.keys(window.require.s.contexts._.defined).length<\/code>.<\/li>\n<\/ol>\n<p>Finally the current progress in percentage can be calculated as:<\/p>\n<pre class=\"prettyprint lang-javascript\" data-start-line=\"1\" data-visibility=\"visible\" data-highlight=\"\" data-caption=\"\">var loadedModules = Object.keys(window.require.s.contexts._.defined).length;\r\nvar currentProgress = Math.round(loadedModules \/ expectedModules * 100);\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h2>Implementing the code<\/h2>\n<p>We want our progress code to be as low level as possible to avoid any additional overhead and to get immediate results. The lowest we can get is to implement it as a plain JavaScript code (without any external dependency) and add it to the index.html page itself. The same thing for the progress indication: you should avoid loading external images and just implement it with plain inline css. The website <a href=\"https:\/\/loading.io\">loading.io<\/a> can generate some nice loading effects using css only. Also Google will love your site for having a fully self-contained page.<\/p>\n<p>Whatever we do in the body of our index.html will be erased by Aurelia once the application is ready. So if you want to reuse the javascript or any of the css classes in your application, you should put it on the head section.<\/p>\n<p>The base code for the progress should be:<\/p>\n<ol>\n<li>Evaluate progress<\/li>\n<li>If not done sleep x milliseconds and evaluate again<\/li>\n<\/ol>\n<p>As JavaScript is single-threaded and cannot sleep, the best way to achive it is to call the same function again and again via setTimeout.<\/p>\n<p>Finally the code should look something like the one below. You can copy\/paste it to your index.html and extend it if needed. It assumes that there is an HTML element in your page with\u00a0<code class=\"prettyprint lang-html_ruby\" data-start-line=\"1\" data-visibility=\"visible\" data-highlight=\"\" data-caption=\"\">id=\"loadingProgress\"<\/code> where the actual progress is displayed. To implement a progress bar one could have two DIVs with different colors and manipulate their widths in the <em>outputProgress<\/em> function.<\/p>\n<p>You can find a working example here: <a href=\"https:\/\/www.kopf.com.br\/puzzle\">https:\/\/www.kopf.com.br\/puzzle<\/a><\/p>\n<p>&nbsp;<\/p>\n<pre class=\"prettyprint lang-javascript\" data-start-line=\"1\" data-visibility=\"visible\" data-highlight=\"\" data-caption=\"\">        \/* \r\n        Add this code as a &lt;script&gt; inside of your index.html\r\n        Set expectedModules to the number of your RequireJS modules\r\n        *\/\r\n        var expectedModules = 177;\r\n        function outputProgress() {\r\n            var loadedModules = 0;\r\n            \/\/ Make sure that requirejs is loaded and welll defined to avoid any exception here\r\n            if (window &amp;&amp; window.require &amp;&amp; window.require.s &amp;&amp;\r\n                window.require.s.contexts &amp;&amp; window.require.s.contexts._ &amp;&amp;\r\n                window.require.s.contexts._.defined)\r\n                loadedModules = Object.keys(window.require.s.contexts._.defined).length;\r\n            \r\n            \/\/ Calculate the progress\r\n            var progress = Math.round(loadedModules \/ expectedModules * 100);\r\n\r\n            \/\/ Get the HTML element with id=\"loadingProgress\" \r\n            var elem = document.getElementById(\"loadingProgress\");\r\n            if (elem) {\r\n                if (progress &gt; 100) {\r\n                    \/\/ Oops, something went wrong. We underestimate the number of modules\r\n                    progress = 100;\r\n                }\r\n                \/\/ Set the progress text\r\n                elem.innerHTML = progress + \"%\";\r\n                if (progress &lt; 100) {\r\n                    \/\/ Evaluare again in 100 milliseconds\r\n                    setTimeout(outputProgress, 100);\r\n                }\r\n            }\r\n        }\r\n        \/\/ Initial call done in the global scope\r\n        outputProgress();\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Aurelia is a nice and modern JavaScript framework which simplifies much the development of single page applications. One of its most criticized weakness is the\u00a0 size of its libraries, which are usually loaded using RequireJS. Its tutorial comes with an explanation on how to add a loading indication to your application using nprogress. Nevertheless this [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[45],"tags":[46,41,22,47],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v21.6 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>A &quot;real&quot; loading indication for Aurelia and RequireJS - Kaplof<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.kopf.com.br\/kaplof\/a-real-loading-indication-for-aurelia-and-requirejs\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"A &quot;real&quot; loading indication for Aurelia and RequireJS - Kaplof\" \/>\n<meta property=\"og:description\" content=\"Aurelia is a nice and modern JavaScript framework which simplifies much the development of single page applications. One of its most criticized weakness is the\u00a0 size of its libraries, which are usually loaded using RequireJS. Its tutorial comes with an explanation on how to add a loading indication to your application using nprogress. Nevertheless this [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.kopf.com.br\/kaplof\/a-real-loading-indication-for-aurelia-and-requirejs\/\" \/>\n<meta property=\"og:site_name\" content=\"Kaplof\" \/>\n<meta property=\"article:published_time\" content=\"2017-06-19T13:28:52+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2017-06-19T17:17:50+00:00\" \/>\n<meta name=\"author\" content=\"Bruno Marotta\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Bruno Marotta\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/a-real-loading-indication-for-aurelia-and-requirejs\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/a-real-loading-indication-for-aurelia-and-requirejs\/\"},\"author\":{\"name\":\"Bruno Marotta\",\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/#\/schema\/person\/a096a6de30951e12938c6a800eeaa891\"},\"headline\":\"A &#8220;real&#8221; loading indication for Aurelia and RequireJS\",\"datePublished\":\"2017-06-19T13:28:52+00:00\",\"dateModified\":\"2017-06-19T17:17:50+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/a-real-loading-indication-for-aurelia-and-requirejs\/\"},\"wordCount\":613,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/#organization\"},\"keywords\":[\"Aurelia\",\"HTML5\",\"javascript\",\"RequireJS\"],\"articleSection\":[\"Aurelia\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.kopf.com.br\/kaplof\/a-real-loading-indication-for-aurelia-and-requirejs\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/a-real-loading-indication-for-aurelia-and-requirejs\/\",\"url\":\"https:\/\/www.kopf.com.br\/kaplof\/a-real-loading-indication-for-aurelia-and-requirejs\/\",\"name\":\"A \\\"real\\\" loading indication for Aurelia and RequireJS - Kaplof\",\"isPartOf\":{\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/#website\"},\"datePublished\":\"2017-06-19T13:28:52+00:00\",\"dateModified\":\"2017-06-19T17:17:50+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/a-real-loading-indication-for-aurelia-and-requirejs\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.kopf.com.br\/kaplof\/a-real-loading-indication-for-aurelia-and-requirejs\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/a-real-loading-indication-for-aurelia-and-requirejs\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.kopf.com.br\/kaplof\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"A &#8220;real&#8221; loading indication for Aurelia and RequireJS\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/#website\",\"url\":\"https:\/\/www.kopf.com.br\/kaplof\/\",\"name\":\"Kaplof\",\"description\":\"Sharing problems and solutions for software development\",\"publisher\":{\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.kopf.com.br\/kaplof\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/#organization\",\"name\":\"Kopf\",\"url\":\"https:\/\/www.kopf.com.br\/kaplof\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/i0.wp.com\/www.kopf.com.br\/kaplof\/wp-content\/uploads\/2015\/04\/Logo-grande.png?fit=78%2C76&ssl=1\",\"contentUrl\":\"https:\/\/i0.wp.com\/www.kopf.com.br\/kaplof\/wp-content\/uploads\/2015\/04\/Logo-grande.png?fit=78%2C76&ssl=1\",\"width\":78,\"height\":76,\"caption\":\"Kopf\"},\"image\":{\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/#\/schema\/person\/a096a6de30951e12938c6a800eeaa891\",\"name\":\"Bruno Marotta\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.kopf.com.br\/kaplof\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/8e15f82b4b9672c32c601286a40eb46f?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/8e15f82b4b9672c32c601286a40eb46f?s=96&d=mm&r=g\",\"caption\":\"Bruno Marotta\"},\"url\":\"https:\/\/www.kopf.com.br\/kaplof\/author\/bmarotta\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"A \"real\" loading indication for Aurelia and RequireJS - Kaplof","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.kopf.com.br\/kaplof\/a-real-loading-indication-for-aurelia-and-requirejs\/","og_locale":"en_US","og_type":"article","og_title":"A \"real\" loading indication for Aurelia and RequireJS - Kaplof","og_description":"Aurelia is a nice and modern JavaScript framework which simplifies much the development of single page applications. One of its most criticized weakness is the\u00a0 size of its libraries, which are usually loaded using RequireJS. Its tutorial comes with an explanation on how to add a loading indication to your application using nprogress. Nevertheless this [&hellip;]","og_url":"https:\/\/www.kopf.com.br\/kaplof\/a-real-loading-indication-for-aurelia-and-requirejs\/","og_site_name":"Kaplof","article_published_time":"2017-06-19T13:28:52+00:00","article_modified_time":"2017-06-19T17:17:50+00:00","author":"Bruno Marotta","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Bruno Marotta","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.kopf.com.br\/kaplof\/a-real-loading-indication-for-aurelia-and-requirejs\/#article","isPartOf":{"@id":"https:\/\/www.kopf.com.br\/kaplof\/a-real-loading-indication-for-aurelia-and-requirejs\/"},"author":{"name":"Bruno Marotta","@id":"https:\/\/www.kopf.com.br\/kaplof\/#\/schema\/person\/a096a6de30951e12938c6a800eeaa891"},"headline":"A &#8220;real&#8221; loading indication for Aurelia and RequireJS","datePublished":"2017-06-19T13:28:52+00:00","dateModified":"2017-06-19T17:17:50+00:00","mainEntityOfPage":{"@id":"https:\/\/www.kopf.com.br\/kaplof\/a-real-loading-indication-for-aurelia-and-requirejs\/"},"wordCount":613,"commentCount":0,"publisher":{"@id":"https:\/\/www.kopf.com.br\/kaplof\/#organization"},"keywords":["Aurelia","HTML5","javascript","RequireJS"],"articleSection":["Aurelia"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.kopf.com.br\/kaplof\/a-real-loading-indication-for-aurelia-and-requirejs\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.kopf.com.br\/kaplof\/a-real-loading-indication-for-aurelia-and-requirejs\/","url":"https:\/\/www.kopf.com.br\/kaplof\/a-real-loading-indication-for-aurelia-and-requirejs\/","name":"A \"real\" loading indication for Aurelia and RequireJS - Kaplof","isPartOf":{"@id":"https:\/\/www.kopf.com.br\/kaplof\/#website"},"datePublished":"2017-06-19T13:28:52+00:00","dateModified":"2017-06-19T17:17:50+00:00","breadcrumb":{"@id":"https:\/\/www.kopf.com.br\/kaplof\/a-real-loading-indication-for-aurelia-and-requirejs\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.kopf.com.br\/kaplof\/a-real-loading-indication-for-aurelia-and-requirejs\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/www.kopf.com.br\/kaplof\/a-real-loading-indication-for-aurelia-and-requirejs\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.kopf.com.br\/kaplof\/"},{"@type":"ListItem","position":2,"name":"A &#8220;real&#8221; loading indication for Aurelia and RequireJS"}]},{"@type":"WebSite","@id":"https:\/\/www.kopf.com.br\/kaplof\/#website","url":"https:\/\/www.kopf.com.br\/kaplof\/","name":"Kaplof","description":"Sharing problems and solutions for software development","publisher":{"@id":"https:\/\/www.kopf.com.br\/kaplof\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.kopf.com.br\/kaplof\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.kopf.com.br\/kaplof\/#organization","name":"Kopf","url":"https:\/\/www.kopf.com.br\/kaplof\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.kopf.com.br\/kaplof\/#\/schema\/logo\/image\/","url":"https:\/\/i0.wp.com\/www.kopf.com.br\/kaplof\/wp-content\/uploads\/2015\/04\/Logo-grande.png?fit=78%2C76&ssl=1","contentUrl":"https:\/\/i0.wp.com\/www.kopf.com.br\/kaplof\/wp-content\/uploads\/2015\/04\/Logo-grande.png?fit=78%2C76&ssl=1","width":78,"height":76,"caption":"Kopf"},"image":{"@id":"https:\/\/www.kopf.com.br\/kaplof\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.kopf.com.br\/kaplof\/#\/schema\/person\/a096a6de30951e12938c6a800eeaa891","name":"Bruno Marotta","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.kopf.com.br\/kaplof\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/8e15f82b4b9672c32c601286a40eb46f?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/8e15f82b4b9672c32c601286a40eb46f?s=96&d=mm&r=g","caption":"Bruno Marotta"},"url":"https:\/\/www.kopf.com.br\/kaplof\/author\/bmarotta\/"}]}},"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/www.kopf.com.br\/kaplof\/wp-json\/wp\/v2\/posts\/128"}],"collection":[{"href":"https:\/\/www.kopf.com.br\/kaplof\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kopf.com.br\/kaplof\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kopf.com.br\/kaplof\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kopf.com.br\/kaplof\/wp-json\/wp\/v2\/comments?post=128"}],"version-history":[{"count":10,"href":"https:\/\/www.kopf.com.br\/kaplof\/wp-json\/wp\/v2\/posts\/128\/revisions"}],"predecessor-version":[{"id":145,"href":"https:\/\/www.kopf.com.br\/kaplof\/wp-json\/wp\/v2\/posts\/128\/revisions\/145"}],"wp:attachment":[{"href":"https:\/\/www.kopf.com.br\/kaplof\/wp-json\/wp\/v2\/media?parent=128"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kopf.com.br\/kaplof\/wp-json\/wp\/v2\/categories?post=128"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kopf.com.br\/kaplof\/wp-json\/wp\/v2\/tags?post=128"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}