Packaging JavaScript Functions - javascript

I'm working to create a shared package of JavaScript functions. At this time, I'm trying to use them like this:
/app/index.js
const myPackage = require('../myPackage');
myPackage.function1();
myPackage.myScope.function2();
The above successfully loads myPackage. However, when I attempt to run function1, I receive an error that says: "TypeError: myPackage.function1 is not a function". My code in the "package" is organized like this:
/myPackage
index.js
root
function1.js
myScope
function2.js
The code looks like this:
index.js
require('./root/function1.js');
require('./myScope/function2.js');
function1.js
exports.function1 = function() {
console.log("Doing stuff in function1");
}
function2.js
exports.function2 = function() {
console.log("Doing stuff for function2");
}
I could understand function2 not working because, there's nothing putting it in myScope, which I don't know how to do. However, I don't understand why function1 isn't running. What am I doing wrong?

To elaborate bergi's answer, you need to have the following in your index.js file:
// file: index.js
exports.function1 = require('./root/function1.js').function1;
exports.myScope2 = {
function2: require('./myScope/function2.js').function2,
};
Because require('./root/function1.js') == exports object in function1.js. So if you
have multiple functions in your function1.js, you have to go like this:
// file: index.js
exports.function1 = require('./root/function1.js').function1;
exports.function11 = require('./root/function1.js').function11;
exports.function111 = require('./root/function1.js').function111;
...
A shortcut of that can be:
// file: index.js
Object.assign(exports, require('./root/function1.js'));
On the other hand: you can set the exports object to be your function:
// file: function1.js
module.exports = function() {
console.log("Doing stuff in function1");
}
Then you can have the following in your index.js file:
// file: index.js
exports.function1 = require('./root/function1.js');
exports.myScope2 = {
function2: require('./myScope/function2.js'),
};
Here require('./root/function1.js') == function1 from function1.js. Hope that explains
the issue.

Your index.js doesn't export anything. You will have to do
Object.assign(exports, require('./root/function1.js'));
exports.myScope = require('./myScope/function2.js');
Or maybe better have your function1.js and function2.js modules export the function itself (module.exports = function() { … };) instead of creating a property, then use
exports.function1 = require('./root/function1.js');
exports.myScope = {
function2: require('./myScope/function2.js'),
};

Related

Can i write firebase real time database triggers in other files instead of index.js?

I would like to split large index.js file into multiple files. To organize the code can i write firebase triggers in multiple js files? If so please help me with how to write properly
child.js
exports.testFunction = functions.database.ref(`/test/`).onWrite((snap, context) => {
console.log(snap.val());
return null;
});
...
index.js
const childFunction = require('./child.js');
...
Basically what you need to do is separate your functions in different files and import them in your index.js like:
1.) In the .js file to be imported such as ‘modA.js’
module.exports = {
func1: function () {
// function 1
},
func2: function () {
// function 2
}
};
2.) Import it in your index.js:
var moduleA = require('./modA');
3.) Run it like:
moduleA.func1();

Webpack 4: How to call a global function with arguments?

I'm writing a new build script for my project using Webpack 4, so far, I have not faced any issue until today, when I have to call a global function with parameters.
Below is an example, I did without parameters for Google reCaptcha:
const enableFormButton = () => {
var elements = "#form_submit_btn, #form_submit_btn_alt";
$(elements).removeAttr("disabled");
$(elements).css({"cursor":"pointer"});
$(elements).removeClass("button button-3d button-red button-small").addClass("button button-3d button-green-invert button-small");
}
const recaptcha = document.querySelectorAll(".g-recaptcha");
recaptcha.forEach((captcha) => {
captcha.setAttribute('data-callback', 'enableFormButton');
});
export { enableFormButton }
and in my entry index.js file, it would look like this:
import {enableFormButton} from './some_js_file'
window.enableFormButton = enableFormButton
Now, this is what I tried with a global function with parameters:
const exampleFunction = (arg1) => {
// do something here
}
export {exampleFunction}
and in the index.js file:
import {exampleFunction} from './some_js_file'
window.exampleFunction = exampleFunction
I tried it, there are no build errors but I get an error in the console saying
"Uncaught TypeError: exampleFunction is not a function"
Any idea on how to solve this? Btw, I'm kind of new to using Webpack.
Thanks to #CertainPerformance's tip, I added the export keyword to the function exampleFunction(arg1), which should look like this:
export exampleFunction(arg1){
// something
}
Imported the function to another .js file:
import {exampleFunction} from './somescript';
And then, it worked! :)
So turns out, I learnt something for the day!

Load JavaScript file in angular2 app

I'm working on a angular2 application written in TypeScript.
This works:
I have a module called plugin-map.ts which looks something like this:
import { Type } from '#angular/core';
import { SomeComponent } from './plugins/some.component';
export const PluginMap: { [key: string]: Type<any> } = {
'e690bec6-f8d1-46a5-abc4-ed784e4f0058': SomeComponent
};
It gets transpiled to a plugin-map.js which looks something like this:
"use strict";
var some_component_1 = require('./plugins/some.component');
exports.PluginMap = {
'e690bec6-f8d1-46a5-abc4-ed784e4f0058': some_component_1.SomeComponent
};
//# sourceMappingURL=plugin-map.js.map
And in other modules I'm importing my PluginMap like this:
import { PluginMap } from './plugin-map';
What I want:
Now I want to create plugin-map.js at runtime when my server starts. So I want to get rid of my plugin-map.ts and instead have only a (generated) plugin-map.js. And I don't want to have any transpile-time dependencies to that plugin-map.js.
What I tried:
In modules where I need to access the PluginMap I replaced the import statement with a declaration like this:
declare const PluginMap: { [key: string]: Type<any> };
Now of course at runtime I get a Error: (SystemJS) 'PluginMap' is undefined. So my next step was to load plugin-map.js explicitly from my index.html like this:
...
<script src="js/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('./app/plugins/plugin-map.js').catch(function (err) { console.error(err); });
System.import('app').catch(function(err){ console.error(err); });
</script>
...
When I start my application I can see that the browser actually requests the plugin-map.js file. But I still get the Error: (SystemJS) 'PluginMap' is undefined.
Question:
How/where do I have to load my generated plugin-map.js so that this works?
I had to make sure that PluginMap is available in the global context. So the generated plugin-map.js has to look like this:
var some_component_1 = require('./plugins/some.component');
PluginMap = {
'e690bec6-f8d1-46a5-abc4-ed784e4f0058': some_component_1.SomeComponent
};
and not like this:
"use strict";
var some_component_1 = require('./plugins/some.component');
exports.PluginMap = {
'e690bec6-f8d1-46a5-abc4-ed784e4f0058': some_component_1.SomeComponent
};
//# sourceMappingURL=plugin-map.js.map
Now it seems to work.

How do I use SystemJS Builder buildStatic?

I am trying to do a simple example using SystemJS Builder by building a SFX bundle, but I cannot get it to work. I cannot figure out how to call exported functions that were in the bundle. Am I missing something obvious?
index.html
<html>
<head>
<script src="app.bundle.js"></script>
<script>
all();
</script>
</head>
<body>
</body>
</html>
gulpfile.js
var path = require('path');
var gulp = require('gulp');
var Builder = require('systemjs-builder');
gulp.task('default', function(cb) {
var builder = new Builder('.', './jspm.config.js');
builder.buildStatic('src/app.js', 'dist/app.bundle.js').then(cb());
});
app.js
import { hello } from 'src/app/hello';
export function all() {
hello();
}
hello.js
export function hello() {
console.log("hello");
};
When I try to load index.html, it loads the app.bundle.js file correctly, but I can't seem to figure out how to call all() and I get Uncaught ReferenceError: all is not defined in Chrome.
The bundle file looks reasonable, I think:
// ... Some minified SystemJS content...
(["1"], [], function($__System) {
$__System.register("2", [], function (_export) {
"use strict";
_export("hello", hello);
function hello() {
console.log("hello");
}
return {
setters: [],
execute: function () {
;
}
};
});
$__System.register('1', ['2'], function (_export) {
'use strict';
var hello;
_export('all', all);
function all() {
hello();
}
return {
setters: [function (_) {
hello = _.hello;
}],
execute: function () {}
};
});
})
(function(factory) {
if (typeof define == 'function' && define.amd)
define([], factory);
else if (typeof module == 'object' && module.exports && typeof require == 'function')
module.exports = factory();
else
factory();
});
Exporting the all function does not mean it's accessible by the global object (window in the browser).
It just means that it can be imported using a module loaded (e.g. systemjs).
When creating a self-executing bundle you should just load the bundle file in the browser (as you already do) and do all bootstrapping also in the js files that are going to be in the bundle.
If you really need to access the all function in that script tag you must add the function to the global object.
in your app.js
window.all = all;
But i don't think this is the way its intended to be used.

How do I import a named SystemJS module from a bundle file?

I've got one file (app.js) with two named modules in it ("foo", and "bar" - where "bar" depends on "foo").
Question: How to I load "bar" it in the browser?
Disclaimer: I'm new to SystemJS and the docs look a little intimidating.
app.js
System.register("foo", [], function(exports_1) {
"use strict";
var App;
return {
setters:[],
execute: function() {
App = (function () {
function App() {
this.bar = 'Hello world.';
console.log(this.bar);
}
return App;
})();
exports_1("App", App);
;
}
}
});
System.register("bar", ["foo"], function(exports_1) {
"use strict";
var App;
return {
setters:[],
execute: function() {
App = (function () {
function App() {
this.bar = 'Mony a mickle maks a muckle.';
console.log(this.bar);
}
return App;
})();
exports_1("App", App);
;
}
}
});
Got the results I wanted by doing the following:
Added the <script src="app.js"> tag to my index file.
Also added System.import('bar'); to the page.
I wonder if this is the standard/recommended way of doing it.
Edit:
The issue with this approach is that I need two strategies for development and production.
In development I don't add the <script> tag and I import the module using System.import('path/app.js');
I think using a bare bones seed can help you out by showing a simple working example, this seed has a PRODUCTION and DEV MODE and you dont need to have 2 strategies, just choose between running it bundled or not
try:
npm i -g slush-jspm-react-seed

Categories

Resources