Single Page App – Loading, Caching LoDash or Underscore Templates Using RequireJS, AppCache

image613As you learned in the previous post, you learned how you can load templates inline in your app using RequireJS. The next step is to load and compile a template file. And for your offline app, learn how you can cache templates. Caching saves a round trip to the server, making your application incredibly responsive.

In this tutorial we will compile, load, and cache LoDash (or Underscore) templates and then use those templates to transform data in our single page app.

The technique uses RequireJS, so there is no more dynamic loading. Templates are bundled within your code which saves some HTTP requests.

Getting Started

For this project, you will need LoDash (or Underscore), and RequireJS. For this tutorial, the files are all in Scripts folder.You can get the libraries from their websites or for your Visual Studio project from NuGet.

Next, create a template named productsTmpl.html in a Templates folder:


<ul>
<% _.forEach(products, function(product) { %>
<li>
<strong><%- product.name %></strong>
<span>( Cateogry: <span class="value"><%- product.category %></span> )</span>
</li>
<% }); %>
</ul>

Next, create an HTML page that contains a reference to required.js. Note that the starting point for will on the page for simplicity, but in real life you would put the code into an main.js or app.js file (and some file references would change when you do that).

Setup the Page

In this page, you should also set requirejs.config to point to the Scripts folder as the RequireJs baseUrl and also map the paths for using _ . You can also map the use of underscore to lodash. The file name does not really matter, but take note, because later you will use the filename in the AppCache.


<!DOCTYPE html>
<html>
<head>
<title>Load Text Template</title>
</head>
<body>
<script src='require.js'></script>
<script>
requirejs.config({
baseUrl: 'Scripts',
paths: {
"_": "Scripts/lodash"
},
map: {
'*': { 'underscore': 'lodash' }
}
});
// Your code goes here
</script>
</body>
</html>

For more information on setting up require.js, see Using RequireJS Asynchronous Module Definition (AMD) Modules with jQuery, LoDash.

DomReady

You may find that RequireJS loads scripts before the DOM is ready.

The domReady module implements a cross-browser way to determine when the DOM is ready. Download the domReady Require module directly from the RequireJS site, click the Download button and copy and paste the code into a file named domready.js in the Scripts folder.

You will use it as one of your dependencies.

Text PlugIn

The key to using a file as a dependency is using Require’s Text.js plugin.  Great for loading templates or other HTML files.

The plugin tells Require.js to load text files and treat them as dependencies when RequireJS see text! as the prefix of a dependency.

Get the plugin from The Require Text.js Plugin on GitHub and put it in the Scripts folder.

Your files should look similar to this:

image

Loading Template Script

The add the following code to the script:


require(['underscore', 'text!../Templates/productsTmpl.html', 'domReady!'],
function (_, productsTemplate) {
var productsData = [{ name: 'Action Figure', category: 'Toy' },
{ name: 'Bicycle', category: 'Transportation' }];
var output = _.template(productsTemplate, { products: productsData });
document.body.innerHTML = output;
}
);

underscore will be resolved using the map lodash.js that is in the baseUrl. domReady is a RequireJS plugin which requires the !.

To load the file as a dependency, you designate:

  • The text plugin using the text! prefix
  • The path to the file begins at the baseUrl
  • Specify the .html suffix.

require() second parameter returns with the return values each item in the required array. For from underscore, you get _ . From the template, you get the text of productsTmpl/html that you set to the variable named productsTemplate.

Next, you:

  1. Create some data.
  2. Render the template with the data.
  3. Apply the output to the body tag.

For more information on the template rendering works, see HTML Templates With Logic Using Underscore, LoDash.

Restrictions on XHR

The text plugin works by using XMLHttpRequest (XHR) to fetch the text for the resources it handles.

  • Many browsers do not allow file:// access to just any file.
  • There are restrictions for using XHR to access files on another web domain – not all browsers support CORS.

If you need to go across domains, when the text plugin determines that the request for the resource is on another domain, it will try to access a “.js” version of the resource by using a script tag. Script tag GET requests are allowed across domains.

A .js version of the resource should just be a script with a define() call in it that returns a string for the module value.

For an example, see the documentation on Require Text.js Plugin on GitHub.

Optimization

If you use the Require.js optimizer, you can make the text strings inline. the RequireJS optimizer will inline any text! references with the actual text file contents into the modules, so after a build, the modules that have text! dependencies can be used from other domains.

For more details, see the RequireJS documentation.

Caching Templates Using AppCache

Next, we want to be able to cache the templates and use them for users who are disconnected. We will first use AppCache to do this.

You need to be sure your web server will serve .appcache files as the text/cache-manifest Mime type. For more details see, 23.1 – AppCache for Offline Apps.

NOTE: For development in Visual Studio, you may need to also need to change your IIS Server so you will no longer use IIS Express. Right-click your solution, click Properties. Click Web. Clear Use IIS Express checkbox.

image

Next, create a new file named products.appcache and put it in the same directory as your html file (the root). As you learned in earlier posts, the AppCache has a particular format, beginning with CACHE MANIFEST, then CACHE and a list of files. You can also add

List each of the files that your app will need to run should it be offline. In this case, we add each of the script files, the template file and your html file. As best practice, also include a comment with the date that you can use when you want to update your cache.


CACHE MANIFEST
# 2013-07-31
CACHE:
Scripts/tmpl.js
Scripts/require.js
Scripts/text.js
Scripts/domReady.js
Scripts/lodash.js
Templates/productsTmpl.html
YourHtmlFileName.html

Finally, add the manifest attribute to your html tag.


<html manifest="products.appcache">

The first time you run, you will get the template from server. Following times, you will get the files from the AppCache on the client.

While developing, you will want to clear or change the cache. You can:

  • Delete the manifest file, which should cause the AppCache to be deleted the next time the browser attempts to update.
  • Change the date (or version number) in the comment.

For more information, see AppCache for Offline Apps.

Sample Code

Samples for this project are available in the DevDays GitHub: https://github.com/devdays/single-page-app/tree/master/LoadTemplates

This project uses 2-LoadEverythingWithAppCache.html

Resources


One thought on “Single Page App – Loading, Caching LoDash or Underscore Templates Using RequireJS, AppCache

Comments are closed.