{"id":4538,"date":"2012-07-15T07:00:36","date_gmt":"2012-07-15T11:00:36","guid":{"rendered":"http:\/\/www.ericfeminella.com\/blog\/?p=4538"},"modified":"2020-03-12T23:00:41","modified_gmt":"2020-03-13T03:00:41","slug":"managing-client-side-templates-with-requirejs","status":"publish","type":"post","link":"https:\/\/www.ericfeminella.com\/blog\/2012\/07\/15\/managing-client-side-templates-with-requirejs\/","title":{"rendered":"Managing Client-side Templates with RequireJS"},"content":{"rendered":"<p>When developing single page web applications, patterns of structure, organization and reuse become ever more important. This especially holds true when there is a need to maintain mulitiple web applications, each of which targeting a specific form factor, while also sharing many of the same underlying core APIs.<\/p>\n<p>In the context of client-side templating, such patterns begin to emerge, quite naturally so, when leveraging RequireJS <a href=\"http:\/\/requirejs.org\/docs\/api.html#define\">modules<\/a> and the RequireJS <a href=\"http:\/\/requirejs.org\/docs\/api.html#text\">text plugin<\/a>.<\/p>\n<h2>Template Modules<\/h2>\n<p>One specific pattern I have found myself implementing is that of a single <em>Templates Module<\/em> which provides a centralized location from which all compiled templates within an application can be referenced. A rather simple pattern, Template Modules are only concerned with loading, compiling and providing a public API to access compiled templates; that is, a Templates Module simply requires all external templates, and provides named methods for retrieving the compiled template functions of each.<\/p>\n<p>A basic implementation of a Templates module is as follows (while <a href=\"http:\/\/handlebarsjs.com\/\" target=\"_blank\" rel=\"noopener noreferrer\">Handlebars<\/a> may be used in this example, any template engine would suffice):<\/p>\n<pre lang=\"js\">\r\ndefine( function( require ) {\r\n\tvar Handlebars = require('Handlebars')\r\n\t  , _template1 = require('text!app\/templates\/template-1.tpl')\r\n\t  , _template2 = require('text!app\/templates\/template-2.tpl')\r\n\t  , _template3 = require('text!app\/templates\/template-3.tpl')\r\n\t  , _template4 = require('text!app\/templates\/template-4.tpl');\r\n\r\n\treturn {\r\n\t\ttemplate1: function() {\r\n\t\t\treturn Handlebars.compile( _template1 );\r\n\t\t},\r\n\t\ttemplate2: function() {\r\n\t\t\treturn Handlebars.compile( _template2 );\r\n\t\t},\r\n\t\ttemplate3: function() {\r\n\t\t\treturn Handlebars.compile( _template3 );\r\n\t\t},\r\n\t\ttemplate4: function() {\r\n\t\t\treturn Handlebars.compile( _template4 );\r\n\t\t}\r\n\t}\r\n});\r\n<\/pre>\n<p>The main benefit of implementing a Templates Module is reuse, as different modules can use the same templates without a need for redundantly requiring and compiling the templates themselves. Additionally, Template Modules provide a convenient means of abstracting away the underlying template engine from client code, thus reducing the amount of refactoring needed should the template engine itself ever need to change. <\/p>\n<p>When using the <a href=\"http:\/\/requirejs.org\/docs\/optimization.html\">RequireJS Optimizer<\/a>, each external template will be included in the optomized build and loaded synchronously, and so there is no additional overhead in terms of HTTP requests when requiring each template in a single location.<\/p>\n<p>You can check out a basic example implementation of a <em>Templates Module<\/em> (in the context of <a href=\"http:\/\/backbonejs.org\/\" target=\"_blank\" rel=\"noopener noreferrer\">Backbone<\/a>) <a href=\"https:\/\/github.com\/efeminella\/requirejs-template-module-example\" target=\"_blank\" rel=\"noopener noreferrer\">here<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When developing single page web applications, patterns of structure, organization and reuse become ever more important. This especially holds true when there is a need to maintain mulitiple web applications, each of which targeting a specific form factor, while also sharing many of the same underlying core APIs. In the context of client-side templating, such patterns begin to emerge, quite&#8230; <a class=\"read-more\" href=\"https:\/\/www.ericfeminella.com\/blog\/2012\/07\/15\/managing-client-side-templates-with-requirejs\/\">Continue Reading<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[42,44,23,59,78,31,45,35],"tags":[],"class_list":["post-4538","post","type-post","status-publish","format-standard","hentry","category-apis","category-code-review","category-design-patterns","category-html5","category-javascript-2","category-oop","category-refactoring","category-software-engineering"],"jetpack_publicize_connections":[],"aioseo_notices":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.ericfeminella.com\/blog\/wp-json\/wp\/v2\/posts\/4538","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ericfeminella.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ericfeminella.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ericfeminella.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ericfeminella.com\/blog\/wp-json\/wp\/v2\/comments?post=4538"}],"version-history":[{"count":0,"href":"https:\/\/www.ericfeminella.com\/blog\/wp-json\/wp\/v2\/posts\/4538\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.ericfeminella.com\/blog\/wp-json\/wp\/v2\/media?parent=4538"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ericfeminella.com\/blog\/wp-json\/wp\/v2\/categories?post=4538"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ericfeminella.com\/blog\/wp-json\/wp\/v2\/tags?post=4538"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}