Handlebars minify HTML - node.js

In a Node.js Express application is there a way of minifying all Handlebars templates before they are sent to the renderer?
I considered creating an Express middleware that does the minification on the HTML response body - but I soon realised that this is highly ineffective since the minification would occur on every HTTP request.
There has to be a way of minifying .hbs templates and cache them server side?

You can minify on the fly but for performance reasons I would recommend you to minify the file with an external minifier beforehand and therefore you just do it once. Otherwise you have to minify the html every time the file is called upon.
Therefore, another solution is to use html-minifier from the command line, with the option
--ignore-custom-fragments "/{{[{]?(.*?)[}]?}}/"
This regex will ignore everything between {{ and }} and HTML-minify the rest.

Only add the next flag "--continue-on-parse-error", the following command worked for me:
html-minifier --input-dir [SOURCE_DIR] --output-dir [TARGET_DIR] --file-ext hbs --collapse-whitespace --continue-on-parse-error --remove-comments --minify-css true --minify-js true

This did the trick:
https://github.com/helpers/handlebars-helper-minify
Only tiny issue is that you'd have to manually include the helper in every single template:
From the module's Github page:
{{#minify removeComments="true"}}
{{> header }}
{{/minify}}
{{#minify removeEmptyElements="true"}}
{{> body }}
{{/minify}}
{{#minify removeComments="true"}}
{{> footer }}
{{/minify}}

Related

node.js/Jade - How to pre-compile jade files and cache it?

Framework: node.js / express.js / Jade
Question: in production env, when a jade file is rendered by express, jade cache's it so future renders are faster.
When I start node.js app, how can I pre-compile (or) pre-render (like warmup) all the jade files so its already in cache when requests start to come in...
I can use a folder recursion, I just need to know how to pre-compile (or) pre-render.
Is this possible?
Jade has template pre-compiling and caching built in.
http://jade-lang.com/api/
Simply specify cache: true option to jade.compileFile, and iterate through all of your template files.
var options = {cache: true};
// iterate/recurse over your jade template files and compile them
jade.compileFile('./templates/foo.jade', options);
// Jade will load the compiled templates from cache (the file path is the key)
jade.renderFile('./templates/foo.jade');
If you're not using any parameters, you can compile jade templates directly to HTML with grunt or gulp and make it watch for file modifications
Try it from the command-line:
jade view/map-beacons.jade -D
If you do need to use parameters I would use something like in Andrew Lavers answer.
compileFile returns a function which you can use to pass in parameters i.e. fn({ myJsVar: 'someValue' })
There is also a client option in the command-line but I didn't find any use for it :
jade view/map-beacons.jade -cD
i do this solution, this code outside http.createServer function
let cache_index=jade.renderFile('index.jade');
and when return view
res.statusCode = 200;
res.setHeader('Content-Type', 'text/html');
res.end(cache_index);
when use this solution server return index to 1ms
but without solution server return index between 150ms to 400ms
result:
Picture 1 with cache
Picture 2 without cache

Grunt-jade, express.js and i18n

I use Grunt, Jade and express.js.
In my jade template i Use i18n - https://github.com/mashpie/i18n-node/
like this:
span #{__('Agencja')}
When i start grunt serve it is ok, it works excellent.
But if i want to compile it grunt-jade tell me that
> span #{__('Agencja')}
undefined is not a function
I have no idea what to do.
Use https://github.com/jeresig/i18n-node-2
then in your jade templates use:
span= __('Text')
or
span #{__("Text")}

Node.js - How to use jade partials with express.js (2.5.8)

I am posting this questions after reading this similar SO question
I have a node.js app running which uses Express 2.5.8 and Jade 0.26.0
I have a jade page that will consist of many widgets. On scouring the internet it seemed ideal to use partials to modularize these widgets.
So my jade main page called comp.jade is
!!! 5
html(lang='en')
head
body
h2.page-header REPORT FOR #{comp_name}
.other_ds
partial('partials/ln_profile')
And my ln_profile.jade is
p.ln_profile
strong #{comp_ln_name}
br
| #{comp_description}
On the server side my script looks like
res.render('comp',{comp_name: 'Some Company'}); // to pass data to comp.jade
res.partial( 'partials/ln_profile',{comp_ln_name: 'Test Company',comp_description:'Test Description'}); // to pass data to ln_profile.jade
But when I do this only ln_profile.jade gets rendered and the comp.jade is not getting rendered.
Where am I going wrong here ?
Partials is deprecated. You have to use Include statement instead of partials.

How do I escape EJS template code in node.js to be evaluated on the client side?

I use node.js/ejs on the server side and backbone.js on the client side.
Both server side and client side use the same templating style.
So the problem is, if I put template code meant for the client inside a template it still get's parsed on the server side.
If found out that something like this works:
<%- "<%= done ? 'done' : '' %\>" %>
However, IMHO this uglifies the code in a way which makes the whole point of using templates useless.
How would you approach this?
Is there a way to define blocks of code inside EJS-templates which do not get parsed like a {literal}-tag used in other templating languages?
Update: For now I use backbone's _.templateSettings to use different delimiters on the client side.
Update: Here's a similar solution in a JSP context: Underscore.js Templates Within JSP
The way I have dealt with this is to override the opening and closing tags on node so that the 2 instances of ejs are lookgin for different tags.
On node you can pass in options
{open:'<%',close:'%>'}
In my case I use <% and <# for my two versions. Then in node ejs template I have something like this (where name is from backbone and everyauth obviously from node):
<% if(everyauth.loggedIn) %><h1><#= name #></h1><% } %>
I assume the question could be read as following because it was this thread Google provide me at first link:
“How I can escape EJS template code delimiter tag only for limited items?”
tl;dr:
Use <%# %> to break the original parsing code (e.g. <<%# %>%= done ? 'done' : '' %<%# %>> will done the following unparsed code <%= done ? 'done' : '' %>)
Long explanation
Imagine a case I decide to change % by ? using { delimiter: '?' } option (that could be the case here, because we want not to use the same has Backbone.js).
Great, that solves your problem. Imagine now later, for some reason, you use your templating system to generate an XML. This XML will start with <?xml version="1.0" encoding="UTF-8"?>.
You will facing the same issue again. What do? You will change the delimiter again? And after that, you will change again? etc. No, for punctual escaping, what we should is just to be capable to say “Not parse this part of the document as EJS”.
So a trick is to avoid EJS understand it's an EJS delimiter parser. So avoid it (in our current case) parse <? (or <% in an original case).
So by simply adding <?# ?> to break the parsing, you will add nothing (the # item is for EJS comment) and you will avoid parser to understand <<?# ?>?xml version="1.0" encoding="UTF-8"?<?# ?>>. The output will be <?xml version="1.0" encoding="UTF-8"?>
Conclusion
In a punctual necessity to avoid EJS parsing, you can just trick the parser to produce the output you need by using <%# %> as a delimiter tag breaker.
For sure, probably in your case, you can just use the marked answer because you will use the EJS tag in a lot of cases.
Well, the way that I currently approach this is to use require.js with the text plugin; this allows me to include the templates using AJAX during development time and have them all compiled into an optimized/minified single file bundle during deploy time.
Of course, if you don't use require.js for dependency management of the rest of your JS code this doesn't work nearly as well, but I can't stand to do javascript dev without require.js anymore now that I'm used to it anyway.
Alternately, there may be other similar technologies that you could use to solve the same problem.
I use backbone.layout.manager on both the client and server side, because I want my templates to be exactly the same.
The way I solved the template delimiter issue was to render the page on the server side, then inject the raw backbone templates.
With new ejs you can add a custom delimiter at client side :
https://github.com/mde/ejs#custom-delimiters
eg :
Custom delimiters can be applied on a per-template basis, or globally:
var ejs = require('ejs'),
users = ['geddy', 'neil', 'alex'];
// Just one template
ejs.render('<?= users.join(" | "); ?>', {users: users}, {delimiter: '?'});
// => 'geddy | neil | alex'
// Or globally
ejs.delimiter = '$';
ejs.render('<$= users.join(" | "); $>', {users: users});
// => 'geddy | neil | alex'

How can express and jade does not compress html?

I using express and jade, but when I debug I doesn't want jade compress my html, are there any way to pass an option jade globally and make it does not compress html.
If you use Express 3.x, you can control compression via app.locals.pretty. I usually enable it while development:
app.configure('development', function () {
app.locals.pretty = true;
});
In the time since this answer was written an option has been added to control this behaviour.
app.locals.pretty = true;
At the moment, no. This feature has been discussed here:
https://github.com/visionmedia/jade/pull/205
The html doesn't actually get compressed or minified by default, though. It's just not formatted nicely. The simplest way I've found to make it human-readable is to use Chrome's dev tools, which give you a nice foldable representation of the source.
You can use Jade Comments to annotate your code for viewing in the browser.
//h1
h1 Some Title
//p
p some content
will output
<!--h1-->
<h1>Some Title</h1>
<!--p-->
<p>some content</p>
The template is already compiled once it leaves the server, so if you wanted to view the template in the browser you would have to write a plugin that de-compiles html to jade and than display the decompiled version.
Huh, new to nodejs so maybe missing something here; but in app.js adding app.set('view options', {pretty: true}); was ineffectual (using express 3.0.3).
..doesn't appear to be supported? did find a workaround, e.g. on a per route basis:
exports.index = function(req, res){
res.render('index', {
[... other stuff ...]
pretty: true
});
};
For whom using pug-cli, you need to add --pretty in cmd(terminal). Like the following,
pug --pretty -w -o dist/html/ assets/pug/index.pug

Resources