merge javascript files in directory with node uglify + watch? - node.js

Goal:
I am trying to build an effortless workflow for client side templating development.
Doc Root:
/views/uncompiled/
/static/js/compiled/
We start in /views/uncompiled/
This is where I can build stuff out, like /views/uncompiled/index.html for example.
Im building dust.js templates, so I am using dusterjs too listen for changes in my /views/uncompiled/ directory, and automatically render compiled *.js counterparts in my /static/js/compiled/ directory.
So /views/uncompiled/index.html renders out /static/js/compiled/index.js anytime a change is saved.
Problem:
My layout.html is growing bigger. I need to include a new *.js script everytime I add another template:
<head>
<script src='/static/js/compiled/index.js'></script>
<script src='/static/js/compiled/header.js'></script>
<script src='/static/js/compiled/footer.js'></script>
<script src='/static/js/compiled/baconstrips.js'></script>
...
</head>
Solution:
Use another watch on the /static/js/compiled/ folder too automatically concat *.js into a single app.js that will always be included in my <head> anytime the contents of that folder changes:
<head>
<script src='/static/js/app.js'></script>
</head>
Question:
I would like to use a concatonation tool like Uglify.js that also does compression.
Are there any node packages that automate the solution above?
Is there a native function of Uglify.js that already does this?

Use grunt.js. It has the ability to watch/concentate/minify your files through various contributed modules. Takes a little getting used to (I still am myself) but you will end up with a custom build process that works the way that you want it to work, which is priceless.

Related

Require vs refer to JS script in Electron's render process

I'm new to Electron. I'm writting an application that uses several client-side UI library, such as jQuery, mask-plugin and d3.js.
Considering perfomance, I would like to know if there is any difference between requireing a JS library in the Renderer process instead of directly refering in a script src tag. Precisely, are require calls more costly than simple scripts src tag in the Render process?
For instance (a very minimal and simple example), which one is faster?
<script>
"use strict"
window.$ = window.jQuery = require('jquery');
window.Tether = require('tether');
window.Bootstrap = require('bootstrap');
require("jquery-validation");
</script>
or refer to the min script directly in the src tag:
<script src="js/core/jquery.min.js"></script>
<script src="js/core/popper.min.js"></script>
<script src="js/core/bootstrap.min.js"></script>
<script src="js/plugins/jquery.validate.min.js"></script>
This is a matter of taste and style than performance I believe. For me personally, I prefer to call libraries from code with require (or import in newer JS) than to add additional scripts to the page.
This allows me to have better visibility of what is being called when working on the code, rather than jumping from source to view.

Remove main.js from Liferay Theme

I currently fight to reduce the amount of requests on page load. The main.js is not used in our custom theme, but still gets loaded.
So how can I remove the theme's main.js, so that the browser won't attempt to load it?
Overwriting it with an empty file in our theme is not an solution (wont reduce request count).
I can find the main.js instances in the following places:
In html/common/themes/bottom.jsp, (with a hook you can modify this)
<script src="<%= HtmlUtil.escape(PortalUtil.getStaticResourceURL(request, themeDisplay.getPathThemeJavaScript() + "/main.js")) %>" type="text/javascript"></script>
And in /themes/_unstyled/templates/init.vm (in your custom theme's init_custom.vm you can change this variable)
#set ($js_main_file = $htmlUtil.escape($portalUtil.getStaticResourceURL($request, "$javascript_folder/main.js")))
and finally in portal-impl/src/VM_liferay.vm (this is in the jar file so you might want to go the ext way but i think you may not need to do anything with this file since this is just a macro which is defined, the thing you may want to change is how this macro (sort of function in velocity) is accessed and from where it is accessed)
#macro (js $file_name)
#if ($file_name == $js_main_file)
<script id="mainLiferayThemeJavaScript" src="$file_name" type="text/javascript"></script>
#else
<script src="$file_name" type="text/javascript"></script>
#end
#end
I am not sure if modifying these files would give the behaviour you desire but you may try and find out. I have not tried yet.

using grunt-usemin to store minified references at dynamic path

In one of the project that I am working on, we need to create a folder named after version of the project and the minified JavaScript and CSS files are stored there. As per usemin's documentation, to update the reference in the HTML page, we need to add the build comment.
<!-- build:js 1.2.5/Combinedjs.js -->
<script src="file1.js"></script>
<script src="file2.js"></script>
<!-- endbuild -->
I want the name of folder mentioned above (1.2.5) to be dynamic and I don't want to change the build comment every time before running the grunt tasks. Does usemin provide any options to achieve this?
Take a look an alternative project named grunt-applymin: https://github.com/ghosert/grunt-applymin

Is there a way to ignore Handlebars templates within a Handlebars template?

I'm using Express + Handlebars in my server side node application, and I want to send client templates to the browser as part of the page that I'm rendering.
index.html
<html>
<head>
<title>{{title}}</title>
</head>
<body>
<div>
{{stuff}}
</div>
<script id="more-template" type="text/x-handlebars-template">
<div>{{more}}</div>
</script>
</body>
Unfortunately, handlebars tries to render the stuff in the #more-template script block. (Which just removes the {{more}} because it's undefined in the server template's context.
Is there a way I can get it to ignore the stuff inside the script tag? (So that the client side template can use it)
I already saw this question: Node.js with Handlebars.js on server and client, I'd rather just use 1 template engine.
In General, when your template is being compiled two times (e.g. when you are only server-side) and you want to ignore template tags in the first run, you can simply tell handlebars to ignore them by appending a backslash:
{{variable1}} \{{variable2}}
When compiling with variable1 set to value1 and variable2 being undefined, you get:
value1 {{variable2}}
(instead of getting the second tag replaced with empty string).
When compiling the second run with variable2 set to value2, you get:
value1 value2
Not the perfect solution (which would be a setting for Handlebars to leave undefined variables alone), but working for my special case.
So I didn't find a way to ignore client templates easily, but the general consensus is to precompile your client templates.
Install handlebars globally npm install handlebars -g
Precompile your templates handlebars client-template1.handlebars -f templates.js
Include templates.js <script src="templates.js"></script>
Execute the template var html = Handlebars.templates["client-template1"](context);
Extra info
Using pre-compiled templates with Handlebars.js (jQuery Mobile environment)
http://handlebarsjs.com/precompilation.html

AMD / RequireJs add decency on specific pages

Is there a way to have a main script that act like a "global" script for all pages of a site while still have specific page script when using requiere.js.
This would be called on all pages
<script data-main="resources/js/main" src="resources/js/libs/require.js"></script>
and on other page i would like to add other dependencies without having to create a different main.js script.
Is there any way to do so ?
EDIT: Just found a way that seems to be working pretty well so far:
<script> require.config({ deps : ['register'] }) </script>
Any other ideas?
You can implement a global main and a page main scripts, something like this (the data-start is not part of the requirejs, is hand-made as described on the link below):
<script data-main="globalmain.js" data-start="page/main" src="require.js"/>
More details here: How to use RequireJS build profile + r.js in a multi-page project

Resources