Skip to content

JST array for templates #319

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

prabirshrestha
Copy link

PR for #265

Introduces new classes main one being JavaScriptArrayHtmlTemplatePipeline.

bundles.Add<HtmlTemplateBundle>("assets/templates",
                b => b.Pipeline = new JavaScriptArrayHtmlTemplatePipeline(this.container, this.settings));

output:

window.JST=window.JST || {};
JST["todo/index"]="<div id=\"todo-container\">\r\n    Todo\r\n</div>";
JST["todo/item"]="<div id=\"todo-item\">\r\n    item\r\n</div>";

If you want to change the variable to something else besides JST pass the third parameter.

 new JavaScriptArrayHtmlTemplatePipeline(this.container, this.settings, "templateHashName")

Here is an example at how clients can cache the underscore templates.

    function buildTemplate(model) {
        var template = JST[this.templateName];
        if (typeof (template) === 'string') {
            template = JST[this.templateName] = _.template(template);
        }

        return template(model);
    }

@andrewdavey
Copy link
Owner

Many thanks for this (and all the twitter feedback too!)

I may refactor it and the current js html templating code into a single generalised bundle pipeline. The specific transformations could be moved into strategy classes, which describe how each template is expressed in JS and how to wrap all the templates.

Something like this, for example:

interface IJavaScriptHtmlTemplatingStrategy
{
    string DefineTemplate(string templateId, string templateContent);
    string WrapAllTemplates(string templatesScript);
}

This should make it easier to work with other JS templating systems, without needing to create loads of extra Cassette classes.

@prabirshrestha
Copy link
Author

Even I had thought of that, the interface would definitely be a better way to go with as most of my codes were duplicated.

The core can contain the dom and arrary implementation.
And stuffs like underscore compilation can go as a seperate nuget package.

We could also optimize the generated code to something like this. local var lookup becomes faster an also minimizes JST being repeated all the time which increases the size.

window.JST=window.JST || {};
(function(t){
t["a"]="...";
t["b"]="...";
})(JST);

Same goes for the dom implementation.

I also think in release mode we can remove the new lines. that might save few bytes :)

window.JST=window.JST || {};(function(t){t["a"]="...";t["b"]="...";})(JST);

@andrewdavey
Copy link
Owner

I'm working on this now. I've got the strategy pattern in place. Now working on the configuration. I'm leaning towards using a global configuration, instead of requiring a per-bundle customization. For example:

public class HtmlServicesConfig : ServicesConfiguration // Convenience base class already in Cassette
{
    public HtmlServicesConfig()
    {
        ConvertHtmlTemplatesIntoJavaScript();
    }
}

with a fluent interface for additional config...

public class HtmlServicesConfig : ServicesConfiguration
{
    public HtmlServicesConfig()
    {
        ConvertHtmlTemplatesIntoJavaScript()
            .StoreInGlobalVariable("templates"); // optional argument - defaults to "JST"
    }
}

Other fluent config methods include UsingIdStrategy and UsingScriptStrategy to provide alternative ways to generate template IDs and convert templates into JavaScript.

Thoughts?

@andrewdavey
Copy link
Owner

Code is in the jstmpl branch if you want to see the work in progress.

@prabirshrestha
Copy link
Author

Here are some of the things I would like to have. Not sure if this is already possible (I haven't tried the jstmpl branch yet. wil try it during this weekend).

If you app is very small you want both the templates and the javascript to be the same file instead of multiple files (one for template and one for javascript). (Though not very important to get this done, it would definitely be plus to have it.)

Also if I want to precompile the template in server side, how would I hook it? ConvertHtmlTemplatesIntoJavascript().StoreInGlobalVariable("JST").PreCompileUnderscoreTemplates()). It can then include stuff like precompile hogan/jquerytemplate and so on. PreCompileUnderscoreTemplates could be distributed as a nuget package too.

Generating ids should definitely be customized. Currently the dom implementation uses todo-index but when using JST it would be preferred to use todo/index.

I think it would be better to have default (global) as well as per bundle. Currently I'm creating multiple backbone apps in the same web app and these backbone apps may use different templating engines. So I would definitely want to have per bundle customization too. I might start with underscore templating, but later on I might want to move to hogan.js.

@andrewdavey
Copy link
Owner

I've added HTML templates to script bundles in a project before, by creating a custom pipeline. It works very nicely. I'm starting to wonder if there's a good reason to keep them separate from scripts any more in general. Serving a cacheable JS bundle of templates has to be better then bloating the page's HTML with <script> tags.

The API for all this is in flux right now. I would want to make it extensible, like you have suggested.

To change the IDs of templates, implement IHtmlTemplateIdStrategy and register your class in Cassette's container.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants