Reducing your app's loading time (HTML)
The user's first experience with an app begins by tapping the app tile to launch it. First impressions matter, so it's to important to limit how much time the user spends waiting while the app launches. How you package your app and reference your code files can improve your app launch time.
Keep content within the app package
You can dramatically improve the loading time of an app by packaging its contents locally, such as JavaScript, CSS, images, and any other files important to the app. Disk operations are faster than network operations, such as a retrieving the file from a remote server. In addition, packaging your files locally provides other performance benefits, such as bytecode caching.
Take advantage of bytecode caching
To help reduce the amount of time it takes to load an app's JavaScript files, Windows 8 uses a feature called bytecode caching. Bytecode caching is a technique in which the system creates bytecode for each JavaScript file once, rather than recreating the bytecode each time it launches the app.
To understand how bytecode caching works, you must first understand how the system installs apps. An app begins as a package. This package contains all the files that make up the app, including its HTML, JavaScript, CSS, and media. When the app is deployed on a system, the system extracts the package into separate files.
When a typical browser loads a JavaScript files, one of the first steps is to process the JavaScript into bytecode, a format of JavaScript that the browser can run. The browser does this for every JavaScript file, and this process increases the loading time for the files.
In contrast, when you install a Windows Store app using JavaScript on the system, the system locates the JavaScript files in the package and converts them into bytecode. From that point on, the app uses the bytecode version of the JavaScript. Bytecode caching speeds up the app's launch because the JavaScript files have already been converted to bytecode and don't have to be reprocessed. Bytecode caching improves load time by approximately 30% in larger applications.
The platform can perform bytecode caching only for JavaScript that's included in your app's package, providing another reason to keep your app's content within its local package.
To ensure that your app benefits from bytecode caching:
- Ensure all JavaScript files are UTF8 encoded with a byte-order mark (BOM).
- Ensure all JavaScript files are statically referenced in the root of your HTML start page.
Load JavaScript files faster
When an app begins loading, the first thing Windows loads is the HTML Start Page specified by the package manifest. The Start Page is the starting point for your app and determines which content and code gets loaded and executed first. How you include your code can have a big impact on performance. Code can be included through static markup, dynamically loaded, or declared inline in the start page's HTML. Here are the different ways to include code:
Use static markup in the Start Page
he fastest way to load your app's JavaScript is to use a script element and set its src attribute to a local JavaScript file. In this case, Windows begins loading the file as soon as it parses the Start Page. Here's an example of such a script element:
<script type="text/javascript" src='code.js'></script>
For faster load times, use static markup to load all the JavaScript needed to initialize your app.
Dynamically load JavaScript through code execution
Another way to load a JavaScript file is through JavaScript code execution. This example uses JavaScript to dynamically create a script element that loads additional JavaScript:
var s = document.createElement(‘script'); s.src = ‘code.js'; document.head.appendChild(s);
The problem with loading JavaScript files dynamically is the system can't load the dynamic code until after the it loads and executes other code first—the code that performs the dynamic load.
We recommend dynamic loading only when:
- The app doesn't need the JavaScript file when it launches. It can load the file later.
- The app doesn't know the URI of the JavaScript file until after it launches, so the file can't be included statically.
Declare inline JavaScript (not recommended)
A third way to include JavaScript is to declare the JavaScript code inline in your HTML file. This example declares a simple JavaScript statement inline:
<script type="text/javascript"> // JavaScript code here var a = 2 + 2; </script>
We recommend against declaring inline JavaScript because it can't receive the same performance optimizations (such as bytecode caching) as JavaScript declared in its own file. Always put your JavaScript code in an external file and use the src attribute of a script element to load it.
If your app needs a JavaScript file when it launches, add a script element to your Start Page that references the JavaScript file, rather than loading it dynamically. This optimization can dramatically decrease your app's loading time. We've seen cases where an app has spent 700ms dynamically loading JavaScript.
Tip Define all files that are needed for app initialization in the HTML of the app's Start Page. Don't use a script loader to dynamically load JavaScript files that the app needs for initialization.
Load only what you need
Another way to improve your app's loading time, which people often forget to do, is to load only what you need for the first page, and load the rest later. This recommendation applies to images, JavaScript, CSS files, and other related files.
The next sections describe a few ways to avoid loading files that your app doesn't need immediately:
Defer load JavaScript
There are two ways you can use the script element to load JavaScript for your app. The first way is to use the script element and only specify the type and src values. When the host processes the script element, it performs a non-deferred load. The host process must load and execute this file before the app can be considered loaded, so it increases the amount of time it takes to initialize your app.
This example doesn't use deferred loading:
<script type="text/javascript" src='file1.js'></script>
The second way to use the script element is to specify the defer attribute. The script attribute informs the host process that the code located within this script is not vital to the app's initialization and can be loaded and executed at a later point. The next example uses deferred loading:
<script type="text/javascript" src='file1.js' defer='defer'></script>
Reference JavaScript within the associated fragment
Fragments, a feature provided by the Windows Library for JavaScript, enable an app to break different pages and views into components. One of the big advantages of using fragments is that app can reference JavaScript within the fragment, and the system loads the fragment JavaScript file only when that page is needed. Some apps can have many lines of JavaScript code that are relevant only later in the app, and not on the initial loading screen. If this code is separated into a different JavaScript file, the app can speed up its loading time by waiting to load the fragment's JavaScript file until it's needed.
Most games are loaded this way. When a game is first launched, usually it gets to the main menu screen fast, because only the items needed for the menu screen are loaded. When a user gets further along in the game (creates or loads a game), then the game loads the remaining data.
Cache the app's fragments
You can use the WinJS.UI.Fragments.cache function to cache a fragment. After a fragment is cached, your app can display it quickly by using the renderCopy function. If the user interacts with the fragment right when your app is loaded or soon after, cache the fragment during activation or immediately after. If you don't explicitly cache a fragment, the app will cache it for you the first time it uses the fragment.
There's no need to track which fragments you cached or when you should clear the fragment cache. The WinJS maintains the cache for you.
Because caching a fragment is about performing the task ahead of time and the cached content consumes memory, and also it takes CPU time and IO to build the cache, we recommend that you:
- For a small app that activates quickly, cache all fragments before completing activation.
- On the other hand, if there is a lot of fragment content and the activation time for the app is already long, cache the fragments after activation is done. Cache the fragments one by one instead of caching all of them at once to avoid tying up too many resources when user might be interacting with the app.
- If you're not sure whether you should cache your fragments during activation or after, try both approaches and measure how much time it takes for the app to launch.
Don't duplicate references to Cascading Style Sheets (CSS) and JavaScript files in page fragments—reference common files in your start page.
Every time you reference a CSS or JavaScript file, it costs the system time to load and parse it. A common mistake is to reference a CSS or JavaScript file in a fragment that the start page or another fragment loaded already. Our testing shows that eliminating duplicating references can improve loading times by an average of 40ms.
Tip Defer load JavaScript files when possible and use Fragments to divide your JavaScript into separate files that don't all have to be loaded right when your app launches.