require Mustache templates in requirejs - requirejs

I'm using mustache templates in requirejs with the text plugin.
define(['text!templates/popups.html', 'mustache'], function (Mustache,popups) {
var mustacheTmpl = Mustache.render(popups, {jData:jsonObj});
}
I would like to call the mustache templates within the module based on a condition like
define(['mustache'], function (Mustache) {
if ($('.element').length) {
require(['text!templates/mustachetemplate'],
function(mustachetemplate) {
var mustacheTmpl = Mustache.render(mustachetemplate, {jData:jsonObj});
})
}
}
How is that possible?

I found out that it actually is working the way I do it. The reason why it was failing was because some other code was blocking.

Related

change requireJS from adding the .js file extension automatically on intern.js

Currently I am working in custom html reporter for intern.js. The Templating engine that i am using is marko.js.
marko.js have extension file with ".marko" for me to input my html syntax
The file is generated correctly in normal node.js (common.js)
The issue occurred when i integrate the same code to intern.js. The requirejs(AMD) that use by internjs is adding the .js file extension automatically to my marko extension when i do
var template = require('./hello-world.marko');
which make the file become hello-world.marko.js and this caused the code broke in markojs
the custom html reporter code is below
define(function (require) {
// require('intern/dojo/node!marko/node-require').install();
var fs = require('intern/dojo/node!fs');
var template = require('./hello-world.marko');
console.log(template);
function JsonReporter(config) {
config = config || {};
this.output = config.output;
}
JsonReporter.prototype = {
runEnd(executor) {
// console.log("toJson: " + JSON.stringify(executor.suites))
data = JSON.stringify(executor.suites);
template.renderToString(data,
function (err, output) {
console.log(output);
fs.writeFile('result.html', output, function (err) {
if (err) return console.log(err);
console.log('Save done');
});
});
},
}
return JsonReporter;
})
The require function isn't really meant for loading arbitrary text resources in either Node's loader or an AMD loader. In Node, whether you're running Intern or not, you can use fs.readFile or fs.readFileSync. In Intern's Dojo-based AMD environment you can also use the dojo/text loader plugin, like this:
var template = require('dojo/text!./hello-world.marko');

What is exports.install in node js?

Hi I found a framework where they use a lot this pattern.
exports.install = function(){
//code
}
but usually you see this pattern in nodejs
module.exports = {
//code
}
Is this the same thing or is this something else ?
exports is the object corresponding to module.exports before you do anything to it. I think it's due to some legacy code, but basically folks use module.exports if they want to replace the whole object with their own object or a function, while they use exports if they just want to hang functions off the module. It's a little confusing at first, but essentially exports.install just means that calling code would do something like:
const mod = require('that-module');
mod.install(params, callback); // call that function
The framework you're looking at is probably using it as part of a bootstrapping process, afaik it doesn't have significance to the node engine itself.
Yes, it is the same thing. You can use one of 2 ways to setup your code.
The different thing is memory. They point to same memory. You can think exports like a variable and you can not use this way to export your module:
Given this module:
// test.js
exports = {
// you can not use this way to export module.
// because at this time, `exports` points to another memory region
// and it did not lie on same memory with `module.exports`
sayHello: function() {
console.log("Hello !");
}
}
The following code will get the error: TypeError: test.sayHello is not a function
// app.js
var test = require("./test");
test.sayHello();
// You will get TypeError: test.sayHello is not a function
The correct way you must use module.exports to export your module:
// test.js
module.exports = {
// you can not use this way to export module.
sayHello: function() {
console.log("Hello !");
}
}
// app.js
var test = require("./test");
test.sayHello();
// Console prints: Hello !
So, it just is style of developer.

how do you hide code in webpack but not node.js

i'm trying to write a library that works in both node.js and the browser. this code uses window.fetch, so i need a polyfill on the server. i would like to write my code something like this:
'use strict'
let fetch
if (ISNODE) {
fetch = require('node-fetch')
} else {
fetch = window.fetch
}
exports.get = params => {
return window.fetch() // and so forth
}
in webpack, it should eliminate the ISNODE tree so that it doesn't try to require('node-fetch') at all.
how do you do this? for now, I'm making window.fetch a global.
You want to use webpack's Define plugin to define constants, then use the Uglify plugin (or something similar) to eliminate dead/unreachable code.
With the Define plugin, define a 'constant' variable for the environment in your build, like IS_SERVER = true. In your conditional, check that constant. Note that this only works when checking variables with boolean values, so it will understand IS_SERVER = true, but not APP_ENV = 'server', for example.

If I use `module("somelib")` in typescript, it can't be running in browser

I'm trying to use typescript with angularjs in the client-side.
I found if I use external modules, the generated js won't be run in browser.
controllers.ts
/// <reference path="./libs/underscore.d.ts"/>
import _ = module("underscore");
module test {
export class Ctrl {
constructor($scope:any) {
$scope.name = "Freewind";
_.each($scope.name, function(item) {});
}
}
}
The generated js will be:
var _ = require("underscore")
var test;
(function (test) {
var Ctrl = (function () {
function Ctrl($scope) {
$scope.name = "Freewind";
_.each($scope.name, function (item) {
});
}
return Ctrl;
})();
test.Ctrl = Ctrl;
})(test || (test = {}));
Which can't run correctly. But if I remove the module("underscore") part, it will be OK.
Since I have add underscore.js in the HTML, I think it should be something wrong with the require() method. How to fix it?
There are two ways to load stuff in your HTML pages.
Bundling
The first one is to manually include all the script files in your page. You might run some kind of pre-release step to merge and minify your code - but you're taking responsibility for that instead of leaving it to the code to do. This is generally called bundling.
In the case on bundling, you only use references in your TypeScript code (not imports), like this:
/// <reference path="./libs/underscore.d.ts"/>
module test {
export class Ctrl {
constructor($scope:any) {
$scope.name = "Freewind";
_.each($scope.name, function(item) {});
}
}
}
Module loading
If you want to use a module loader, which for The Web is typically RequireJS, you can load External Modules using the import statement. Normally you wouldn't need the reference in this case...
import _ = module("./libs/underscore");
module test {
export class Ctrl {
constructor($scope:any) {
$scope.name = "Freewind";
_.each($scope.name, function(item) {});
}
}
}
RequireJS with non-modules
There is a third scenario, which is quite common. If you intend to import something that isn't an External Module (such as jQuery, but underscore may also fit this pattern), you are better off using a reference and a manual call to RequireJS.
RequireJS will load the dependency for you, so you would wrap your main program with it (which would probably be in a separate file such as app.ts.
///<reference path="./libs/require.d.ts" />
///<reference path="./libs/underscore.d.ts" />
module test {
export class Ctrl {
constructor($scope:any) {
$scope.name = "Freewind";
_.each($scope.name, function(item) {});
}
}
}
require(['underscore'], function (_) {
var ctrl = new test.Crtl({});
});
You can also use require.config to specify the path to underscore in your application.
require.config({
paths: {
"underscore": "libs/underscore"
}
});
When you use require, you asserting that underscore is exported as a loadable module. This further assumes that you are using some sort of module loader system (TypeScript currently supports AMD and CommonJS modules). Since you aren't using a module system, and underscore is simply available in global scope, you can use a /// reference to tell TypeScript that Underscore is available in global scope. Put the following at the top of your file:
/// <reference path="./libs/underscore.d.ts">
And you should be good to go!

pattern for module targeting browser and nodejs

backbone and underscore are usable in both the browser and nodejs.
they use the following pattern:
(function(){
// The top-level namespace. All public Backbone classes and modules will
// be attached to this. Exported for both CommonJS and the browser.
var Backbone;
if (typeof exports !== 'undefined') {
Backbone = exports;
} else {
Backbone = this.Backbone = {};
}
// ...
})();
is this the best way to achieve this?
"Best"? Well, that's a subjective thing; it's certainly a good way.
Something you left out that's quite important is that the function should use this as the reference to the global context — what code targeted at browsers would call "window":
(function() {
var global = this; // like "window"
That way, it's possible for the code to "export" symbols:
global.Foo = someFunction;
Another similar trick is to do this:
(function(global) {
// ...
})(this);
That has pretty much the same effect.
With ECMAScript 5 strict mode (and thus future versions of JavaScript), only Pointy’s version will work, because "this" does not point to the global object in non-method functions, any more. Instead:
(function() {
"use strict";
console.log("This is "+this); // "This is undefined"
}());

Resources