are dust helper dependencies bundled within compiled templates? - javascript

I'm wondering how helper dependencies are managed in compiled dust templates, specifically relating to being used on the client -- is the helper method bundled with the compiled dust template? What about dependencies that might not be supported on the client? Or if that dependency has multiple other dependencies?
Here's a trivial example of a dust template I'd like to be able to use on the client:
// foo.dust
{#myHelper}
<div>{foo}{bar}</div>
{/myHelper}
// my-helper.js
const isomorphicDep = require('isomorphic-dep');
const nodeDep = require('node-dep');
module.exports = function(dust) {
dust.helpers.myHelper = function(chunk, context, bodies, params) {
// do some stuff using deps
let foo = nodeDep.getFoo();
let bar = isomorphicDep.getBar(params.someInput);
return chunk.render(bodies.block, context.push({ foo, bar });
};
};
Thanks

A compiled template just contains instructions for how to render-- it does not include any client code itself.
For example, a simple template like this:
{#helper}foo{/helper}
Compiles into these two instruction sets:
function body_0(chk, ctx) {
return chk.h("helper", ctx, {
"block": body_1
}, {}, "h");
}
function body_1(chk, ctx) {
return chk.w("foo");
}
When the template is rendered, it asks Dust to look for the helper named helper and execute it (in the body_0 function). The code for helper is not included with the template.
So on the client, you'll need to include a file containing the helper that loads the correct isomorphic dep (like node-fetch vs whatwg-fetch, for example).

Related

How to include/import an entire JS file with Webpack

I am new to Webpack, but I have a habit of building my web apps in the following manner:
Declare a global variable for the project.
Create several JS files that use the global variable to declare functions and variables
Link these separate js files in the HTML file, and combine them when going to production.
For example my first JS file would be "init.js":
let FP = {}; // Global Object
My second would be "processing.js":
FP.addNumbers = function(a, b){
return a+b;
}
The HTML would include:
<script src="init.js"></script>
<script src="processing.js"></script>
Then in production I use a node plugin I wrote to parse the HTML page and combine all the JS files into one.
I want to do something similar with Webpack, but the only way I found to combine files is with "include". Which requires each file use a separate variable name.
I literally just want to dump the contents of my separate JS files into init.js. Is there a way to do this?
If you're going to use Webpack to bundle your code, the right approach to something like this would be to take advantage of modular imports and exports to coordinate data between modules, otherwise the use of Webpack isn't really doing anything for you.
For example, here, try the following:
// index.js
import { addFns } from './addFns.js';
const FP = {};
window.FP = FP; // use this if the object needs to be global
addFns(FP);
// addFns.js
export const addFns = (FP) => {
FP.addNumbers = function(a, b){
return a+b;
}
};
Then, Webpack can create the complete bundle with only a single .js file as output automatically, and it'll be ready for production with any more post-processing.

NodeJS Module Exports with Additional Required Files

I am trying to break my nodejs code up into as small of files as possible to keep things modular. I have an app.js that is needing to use another method that I have moved to utils.js. The utils file however has a method that has a requirement for another library.
Should my utils.js file be "requiring" dependencies or should all those go in my app.js?
// app.js
var utilities = require('./utilities');
..
return utilities.anotherMethod();
// utils.js
module.exports = {
producer: function () {
// Handle mapping of fields depending on the source system
return 'map fields'
},
anotherMethod: function () {
// I require another lib. Do I do that here or app.js?
var kafka = require('kafka-node');
}
};
Update: Regarding the close request for an opinion based answer is essentially telling me that this can be done either way, which is what I was trying to clarify.

Compiling Typescript module to AMD but not wrapping result in object eg. Foo.Foo

I am working on converting part of a large Backbone application to use Typescript. Some of the core js files have been converted to Typescript and are referenced by other non-TS js files.
Before we converted our requirejs modules would be of the form:
View.js
define([backbone, deps...], function (backbone, deps...) {
return backbone.View.extend({
render: function () {...}
});
});
Which in the consuming code we could do:
define([View, ...], function (View,....) {
var view = new View({...});
view.render();
});
Using Typescript external modules and exports I can compile a file containing a Typescript class to AMD but the code generated sets a property on an exports object as the results which means consuming code looks like this now, given the file name is View.js:
var view = new View.View();
This is annoying and also means we can't maintain backward compatibility with the legacy non-TS code without changes (though minor). Is there anyway to get around this?
EDIT:
Relevant generated code (the define callback)
function (require, exports) {
var Backbone = require('backbone');
var View = (function (_super) {
__extends(View, _super);
function View(options) {
_super.call(this, options);
}
})(Backbone.View);
exports.View = View;
}
The aim is to have some core components in typescript so that we can use TS going forward, and have other older libraries require the completed js components.

How to precompile gulp-handlebars helpers?

I am precompiling my templates into JS using gulp-handlebars but I am having trouble getting custom handlebars helpers to also precompile. Does anyone know if there is any support/way to precompile custom helper methods?
I noticed that gulp-handlebars can use a specific handlebars library, essentially overriding its default. So, by just creating my own module and registering some helpers, and feeding that into the handlebars call, things are working locally.
// helpers.js
var handlebars = require('handlebars');
handlebars.registerHelper('upper', function(str){
return str.toUpperCase();
});
module.exports = handlebars;
And then in the gulpfile (something like this):
var handlebars = require('./src/js/helpers.js');
gulp.task('handlebars', function(){
gulp.src('src/html/*.html')
.pipe(gulp_handlebars({handlebars: handlebars})) // override library here
});
If you're using Browserify and optionally watchify and need the output to be a commonjs style module, gulp-defineModule will use a require('Handlebars') in the compiled template file.
This negates any registered helpers that you had passed into gulp-handlebars custom library option (see above). Here is an example of the output file we don't want:
// template.js
var Handlebars = require("handlebars");
module.exports = Handlebars.template({"compiler":[7,">= 4.0.0"]...
1: To fix this, create a helpers.js file that requires the handlebars library, adds the helpers, and then exports the library. Use gulp-defineModule's require option to pass in the handlebars library with the helpers like so:
.pipe(defineModule('node', {
require: {
Handlebars: '../helpers'
}
})
)
this will produce:
// template.js
var Handlebars = require("../helpers");
module.exports = Handlebars.template({...
Note that the relative path will be from the outputfile, and be careful on prod where filepaths may change.
2: Another way is to use gulp-wrap to define the module exactly how you want it. Something like:
.pipe(wrap('module.exports = function(Handlebars) {return Handlebars.template(<%= contents %>) }'))
then in main-js:
var Handlebars = require('./helpers');
var template = require('./template)(Handlebars);

Load submodules from different files - javascript module pattern

I am trying to create javascript extendable library with submodules in different files. I am using Module Pattern based on Ben Cherry article
module.js
var SERVICES = (function (service) {
var service = {},
privateVariable = 1;
function privateMethod() {
//
}
service.moduleMethod = function () {
//
};
return service;
}());
submodule.js
SERVICES.submodule = (function (service) {
var submodule = {},
privateVariable = 1;
submodule.moduleMethod = function () {
//
};
return submodule;
}(SERVICES));
What I want to achieve is the following. The module.js is a module which I want to act as a library. Submodules are separated in the different files, thus I am using Module Pattern. Clients will be able to write new submodules for the mentioned library (module.js). I want to create a script which will call library SERVICES with all submodules available. This script will be included in one front-end file just once, and there will be no need to change anything when someone writes new submodule. Library should load it.

Categories