{"id":254,"date":"2013-08-09T14:39:08","date_gmt":"2013-08-09T03:39:08","guid":{"rendered":"https:\/\/mindbleach.com\/words\/?p=254"},"modified":"2013-08-09T15:30:20","modified_gmt":"2013-08-09T04:30:20","slug":"more-javascript-templates-using-src","status":"publish","type":"post","link":"https:\/\/mindbleach.com\/words\/2013\/08\/09\/more-javascript-templates-using-src\/","title":{"rendered":"More Javascript Templates Using \u2018src\u2019"},"content":{"rendered":"<p>There was some concern about my <a title=\"Javascript Templates Using 'src'\" href=\"https:\/\/mindbleach.com\/words\/javascript-templates-using-src\/\">previous solution<\/a>, that it loads templates <span style=\"text-decoration: underline;\">synchronously<\/span> and <span style=\"text-decoration: underline;\">serially<\/span>. An application <strong>should<\/strong> have templates inlined before it goes to production anyway.<\/p>\n<p>Fair point though, there is a better way.<\/p>\n<h2>Better Definition<\/h2>\n<p>Firstly; <a href=\"http:\/\/marionettejs.com\/\" target=\"_blank\">Marionette.js<\/a> can transparently lazy-load and cache DOM-stored templates;<\/p>\n<pre class=\"brush: javascript; gutter: true\">\/\/What I had been doing\r\nvar MyView1 = Marionette.ItemView.extend({\r\n\ttemplate: _.template( $(&quot;#template_myview1&quot;).html() )\r\n});\r\n\r\n\/\/What I should have been doing\r\nvar MyView2 = Marionette.ItemView.extend({\r\n\ttemplate: &quot;#template_myview2&quot;\r\n});<\/pre>\n<p>The difference between the two is significant.<\/p>\n<ul>\n<li><em>MyView1<\/em> will access the DOM as soon as the class is defined, and build the template immediately.<\/li>\n<li><em>MyView2 <\/em>will access the DOM only when a\u00a0<em>MyView2<\/em> instance is constructed, but only builds the template once.<\/li>\n<\/ul>\n<p>This means the templates are only built at the time they are first used. The template blocks don&#8217;t need to be accessible at the time the classes are defined. The app only needs to <em>build<\/em> the template functions the first time they are used.<\/p>\n<p>Using the <em>MyView2<\/em> style will give much faster start-up times for larger applications.<\/p>\n<p>(<a href=\"http:\/\/marionettejs.com\/docs\/backbone.marionette.html#section-121\" target=\"_blank\">Marionette.TemplateCache<\/a> can be used stand-alone, or you can fairly easily create your own caching DOM template loader)<\/p>\n<h2>Better Loading<\/h2>\n<p>Now, the template blocks won&#8217;t be referenced until they are used. We can load them asynchronously now, but we still don&#8217;t want to start the app until the templates have been fetched. <em>$.ready(&#8230;) <\/em>won&#8217;t wait for the templates, but there&#8217;s a fairly easy workaround;<\/p>\n<pre class=\"brush: javascript; gutter: true\">\/\/A list of promises that need to resolve before starting\r\nvar loaded = [];\r\n\r\n\/\/Load all templates\r\nvar $templates = $(&#039;script[type=&quot;text\/template&quot;]&#039;);\r\n$templates.each(function() {\r\n\tvar src = $(this).attr(&quot;src&quot;);\r\n\tif (src) {\r\n\t\tloaded.push( \/\/Wait for the template to load\r\n\t\t\t$.ajax(src, {context:this}).\r\n\t\t\tdone(function(data) {\r\n\t\t\t\t$(this).html(data);\r\n\t\t\t})\r\n\t\t);\r\n\t}\r\n});\r\n\r\n\/\/Wait for the DOM to be ready\r\nloaded.push($.ready);\r\n\r\n\/\/Initialise after everything is loaded\r\n$.when.apply($,loaded).done(function() {\r\n\t\/\/Start application\r\n});<\/pre>\n<p>There! With that in place;<\/p>\n<ul>\n<li>Templates are loaded into script blocks as you&#8217;d expect, asynchronously and in parallel.<\/li>\n<li>The application starts after the DOM and the templates are loaded.<\/li>\n<li>For production, the templates are inlined. Without any code changes, the application will transparently start as soon as $.ready is completed.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>There was some concern about my previous solution, that it loads templates synchronously and serially. An application should have templates inlined before it goes to production anyway. Fair point though, there is a better way. Better Definition Firstly; Marionette.js can &hellip; <a href=\"https:\/\/mindbleach.com\/words\/2013\/08\/09\/more-javascript-templates-using-src\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[24,11],"tags":[17,25,22,20,21,19,18,23],"class_list":["post-254","post","type-post","status-publish","format-standard","hentry","category-javascript-programming","category-programming","tag-javascript","tag-marionette","tag-mustache","tag-remote","tag-resource","tag-tag","tag-template","tag-underscore"],"_links":{"self":[{"href":"https:\/\/mindbleach.com\/words\/wp-json\/wp\/v2\/posts\/254"}],"collection":[{"href":"https:\/\/mindbleach.com\/words\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mindbleach.com\/words\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mindbleach.com\/words\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mindbleach.com\/words\/wp-json\/wp\/v2\/comments?post=254"}],"version-history":[{"count":7,"href":"https:\/\/mindbleach.com\/words\/wp-json\/wp\/v2\/posts\/254\/revisions"}],"predecessor-version":[{"id":263,"href":"https:\/\/mindbleach.com\/words\/wp-json\/wp\/v2\/posts\/254\/revisions\/263"}],"wp:attachment":[{"href":"https:\/\/mindbleach.com\/words\/wp-json\/wp\/v2\/media?parent=254"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mindbleach.com\/words\/wp-json\/wp\/v2\/categories?post=254"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mindbleach.com\/words\/wp-json\/wp\/v2\/tags?post=254"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}