Making use of browserified NodeJS file into browser - javascript

I have a NodeJS file which I browserfied using browserify module. I used following command
browserify testFile.js -o bundle.js
To make use of this file in browser, I am making use of window object.
Assume below code is generated after browserifying the file.
var Main = function () {
this.foo = function () {
},
this.temp= function () {
},
this.bar= function () {
}
}
to make use I changed it to
window.Main = function () {
this.foo = function () {
},
this.temp= function () {
},
this.bar= function () {
}
}
and then to use of these functions, I used following code:
var obj= new Main ();
and then I can say obj.foo(); or obj.bar();
All this is working fine but I wonder if this is the right way to call function from a browserfied file.
Please suggest correct way to make use of browserfied file.

Browserify is a great tool when you use it for the entire project. It makes almost no sense to use it for single files only. The whole point of it is avoiding globals, instead of setting window.Main you could do this:
module.exports = function () {
this.foo = function () {
},
this.temp= function () {
},
this.bar= function () {
}
}
And then in all files that need access to the above, do:
var Main = require('./path/to/main.js');
Browserify resolves and inlines all require calls automatically so you only need to run Browserify on the single file that fires up the app.

Related

Loading dependencies with or without react

I have an old IIFE that is injected into legacy pages via <script src.
However, I want to use all these old libraries in a react app. I just need to use the global function exposed.
I figure loading dependencies that will work both via script or via react's import or nodejs require
Here is an example of an example IIFE
example.js :
var $ = $;
var geocomplete = $.fn.geocomplete;
var OtherExternalLib = OtherExternalLib;
var Example = (function() {
return {
init: function () {
// stuff
}
}
)();
Where the legacy code is calling Example.init(), and likewise the react code will call the same function.
Where $ (jQuery), $.fn.geocomplete, and OtherExternalLib are all dependencies that must be loaded, either they should be loaded on-demand or just throw a big loud error message.
I suspect if the solution loads dynamically example.js would look something like
var $ = load("\libs\jquery.js");
var geocomplete = load("\libs\$.fn.geocomplete.js");
var OtherExternalLib = load("\libs\OtherExternalLib.js");
var Example = (function() {
return {
init: function () {
// stuff
}
}
)();
And the legacy application can still use <script src=example.js and React can use
import {Example} from example
Understandably this is somewhat a round-about way to of using legacy code in new applications, so I am open to other ideas on how best to expose an IIFE (with or without dependencies) and using it in React
I am using react+typescript in my project with some limitations which is why I had to dynamically import my package (my project runs in a shell project with AMD module, not having my own startup, and change the way project files get bundled).
Since I could only use the dependent modules on the fly during the run time, I had to assume them were valid while building and bundling . Most of them were IIFE.
So I used the lazy dynamic import .
something like this
import("somePolyfill");
This would be translated by TSC
new Promise(function (resolve_3, reject_3) { require(["arrayPolyfill"], resolve_3, reject_3); });
This would call the IIFE and execute the polyfills or initializing any window or global variable, so the rest of the code is aware of that.
If it returns a module or throughs error can be handled like normal promise then and catch.
So I created a wrapper
export class DepWrap {
public static Module: any = {};
public constructor() {
this.getPI();
this.getSomeModule();
}
public async getPI() {
DepWrap.Module["PI"] = 3.14;
}
public async getSomeModule() {
await import('somepath/somemodule').then(($package) => {
DepWrap.Module["somemodule"] = $package;
}).catch(() => {
window.console.log("Some Module error");
});
}
}
this got compiled to
define(["require", "exports", "tslib"], function (require, exports, tslib_1) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var DepWrap = /** #class */ (function () {
function DepWrap() {
this.getPI();
this.getSomeModule();
}
DepWrap.prototype.getPI = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
DepWrap.Module["PI"] = 3.14;
return [2 /*return*/];
});
});
};
DepWrap.prototype.getSomeModule = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, new Promise(function (resolve_1, reject_1) { require(['somepath/somemodule'], resolve_1, reject_1); }).then(function ($package) {
DepWrap.Module["somemodule"] = $package;
}).catch(function () {
window.console.log("Some Module error");
})];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
DepWrap.Module = {};
return DepWrap;
}());
exports.DepWrap = DepWrap;
});
with this I could use all the dependency modules from my wrapper and every time i need to import a new one I would create another function to add that to my wrap module.
import { DepWrap } from "wrapper/path";
const obj = new DepWrap(); // initialize once in the beginning of project so it would import all the dependencies one by one .
Afterwards in all file, I can import my module from the wrapper
import { DepWrap } from "wrapper/path";
const { PI, somemodule} = DepWrap.Module;
I am not sure if the code will work for your scenario as well, but I guess tweaking it a bit might come in handy for your useCase .
Plus : if you are writing unit test case it will help jest to just ignore the modules and can create a mock for this so that you can test your actual code .

Accessing an Immediately Invoked Function Expression variable in Node.js in another file using require

File 1 - Monitor.js
var MONITOR = (function () {
// File Content
return {
doThing: function() {
doThing();
}
};
})();
File 2 - Test.js
var monitor = require('../public/js/monitor.js');
I want to access doThing() in File 2. I have tried various syntax and no luck so far.
From the frontend HTML I can simply include Monitor.js in a script tag, and call MONITOR.doThing(); without trouble but in Test.js this is proving difficult.
Any advice on how?
You have to export MONITOR so that someone else can access it with require().
Add this:
module.exports = MONITOR;
at the bottom of Monitor.js.
And, if you want the monitor.doThing() method to return some value, then you have to add a return statement to the function as in:
var MONITOR = (function () {
// File Content
return {
doThing: function() {
return "hello";
}
};
})();

Can I break an ES6 JavaScript program using the revealing pattern into separate files?

I have a large and growing JavaScript program that I'd like to break into separate files for maintainability but I don't know if it is possible. I have broken it into modules using the revealing pattern as described here. That helps and it may be all I can logically do.
This is a non-Rails Ruby/Sinatra/Rack middleware/ES6 JavaScript application. I have Sprockets implemented to maintain the asset pipeline. It uses jQuery Mobile Single Page Architecture which is required to maintain an active IoT WebSocket connection. As such, the HTML page and JavaScript function, once loaded, must always be maintained.
A mock-up of the JavaScript is:
$(function ($, window, document) {
let globalTriggered;
const constOne = [1, 2, 3];
const consDot = '.';
$("body").pagecontainer({
defaults: false
});
$(document).on("pagecreate", null, function () {
if (globalTriggered === false) {
globalTriggered = true;
let Module1 = (function () {
let privateMethod1 = function () {
Module2.anotherMethod2()
};
let someMethod1 = function () {
privateMethod1()
};
let anotherMethod1 = function () {
};
return {
someMethod1: someMethod1,
anotherMethod1: anotherMethod1
};
})();
let Module2 = (function () {
let privateMethod2 = function () {
};
let someMethod2 = function () {
Module1.someMethod1();
privateMethod2()
};
let anotherMethod2 = function () {
Module1.anotherMethod1()
};
return {
someMethod2: someMethod2,
anotherMethod2: anotherMethod2
};
})();
} // stabilzer end
}); // pagecreate end
}(window.jQuery, window, document)); // function end
What I would like to do would be to separate modules, like Module1 and Module2 in this example, into their own source files, again for maintainability.
I considered ES6's export/import option, but the import/export must always be done at the top level. Sprocket has a similar restriction in that it stops searching for directives once it hits code. I considered attempting to hack Sprocket past this by using require_self, but that probably won't work and it would be ugly if it did.
Any options? Thanks.
Well, it was nearly as simple as dandavis hinted (thanks). I am just moving the modules into their own file, executing the internal function when they are defined, eliminating their default execution [change their last line from })(); to }()); ], require them at the top using Sprockets (though ES6 export/import should work), and fire them when I need them.
//= require Module1.js
let Module1 = (function () {
let privateMethod1 = function () {
Module2.anotherMethod2()
};
let someMethod1 = function () {
privateMethod1()
};
let anotherMethod1 = function () {
};
return {
someMethod1: someMethod1,
anotherMethod1: anotherMethod1
};
}());
//= require Module2.js
let Module2 = (function () {
let privateMethod2 = function () {
};
let someMethod2 = function () {
Module1.someMethod1();
privateMethod2()
};
let anotherMethod2 = function () {
Module1.anotherMethod1()
};
return {
someMethod2: someMethod2,
anotherMethod2: anotherMethod2
};
}());
$(function ($, window, document) {
let globalTriggered;
const constOne = [1, 2, 3];
const consDot = '.';
$("body").pagecontainer({
defaults: false
});
$(document).on("pagecreate", null, function () {
if (globalTriggered === undefined) {
globalTriggered = true;
Module2.anotherMethod2();
} // stabilzer end
}()); // pagecreate end
}(window.jQuery, window, document)); // function end
Update: Any callbacks, including functions fired on something like click, must be exposed with the returned associative array and must use the module name in its reference even within that module since the callback will occur externally.

Writing multiple functions in AMD javascript module

I am quite new to writing javascript code using AMD. I am stuck at figuring out how to write multiple functions in a file:
define(function(){
return {
and: function(a,b){
return (a&&b);
}
};
}
);
I tried writing another function plus in the following way:
define(function(){
return {
plus: function(a,b){
return (a+b);
}
};
}
);
But when I use grunt for testing, it is not able to detect the function plus
You should place each module in it's own file. At least requireJS (are you using that?) determines the module name by it's file name (without the .js).
So a file sitting in /modules/A.js will have the module name "modules/A".
If you really want to define multiple modules in one file, you can do it in a more explicit way like this:
define("A", [], function () { return ...whatever... });
define("B", [], function () { return ...whatever... });
Edit:
for defining one module with two functions you can use different patterns. For a singleton (i.e. no "Class") I usually do something like this:
define(function () {
var myModule = {
fn1: function () { .... },
fn2: function () { .... }
};
return myModule;
});

Structure application by using jQuery

I am going to build an application as it is not too much rich otherwise I can use angularjs for that purpose. I wanted to organize my JS code into proper modular programming approach.
E.g
var SignUpModule = {
elem: $('#id'), // unable to access jquery object here
init: function (jQuery) {
alert(jQuery('.row').html());
}
};
var application = {
modules: [],
addModule: function (module) {
this.modules.push(module);
},
run: function (jQuery) {
_.each(this.modules, function (module) {
//Iterate each module and run init function
module.init(jQuery);
});
}
}
jQuery(document).ready(function () {
application.addModule(SignUpModule);//add module to execute in application
application.run(jQuery);//Bootstrap application
});
Please now look at it I have updated my question with actual code
The biggest mistake you've done is using anonymous first parameter of an anonymous function taken by $.each method. The first argument is just index, and the second argument is an element you were looking for. Below you can find working code.
And no, you don't need to pass jQuery object everywhere. It's global. It already is everywhere. You can see it in the code below.
var SignUpModule = {
elem: $('.row'), //jQuery works fine here
init: function () {
alert(this.elem.html());
}
};
var application = {
modules: [],
addModule: function (module) {
this.modules.push(module);
},
run: function () {
$.each(this.modules, function (index, module) { //this function takes 2 parameters
//Iterate each module and run init function
module.init();
});
}
}
//document.ready
$(function () {
application.addModule(SignUpModule);//add module to execute in application
application.run();//Bootstrap application
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="row">alert <b>me!</b></div>

Categories

Resources