How can I autoload Moment.JS in Compound.JS? - javascript

I want Moment to be available globally, and I understand Compound is capable of auto-loading modules - so how would I use it? If I include "moment" in the autoload array, how can I use it in the application?

I know there's thoughts about redoing the module loading in compound, and I know it's also not easy to find information about how to do it.
I solved it by putting a loadLibs.js in config->initializers where I load modules like so:
module.exports = function(compound) {
compound.module1 = require('module1');
compound.module2 = require('module2');
//etc.
};
modules will then be available on the compound object.
just be careful not to try to overwrite some already existing keys on the compound object. you could also put it under a namespace like compound.myApp.module

Related

How can I reload an ES6 module at runtime?

Prior to ES6 modules, it was (I'm told by other Stack answers) easy to force a JS script to be reloaded, by deleting its require cache:
delete require.cache[require.resolve('./mymodule.js')]
However, I can't find an equivalent for ES6 modules loaded via import.
That might be enough to make this question clear, but just in case, here's a simplified version of the code. What I have is a node server running something like:
-- look.mjs --
var look = function(user) { console.log(user + " looks arond.") }
export { look };
-- parser.mjs --
import { look } from './look.mjs';
function parse(user, str) {
if (str == "look") return look(user);
}
What I want is to be able to manually change the look.mjs file (e.g. to fix a misspelled word), trigger a function that causes look.mjs to be reimported during runtime, such that parse() returns the new value without having to restart the node server.
I tried changing to dynamic import, like this:
-- parser.mjs --
function parse(user, str) {
if (str == "look") {
import('./look.mjs').then(m => m.look(user))
}
}
This doesn't work either. (I mean, it does, but it doesn't reload look.mjs each time it's called, just on the first time) And I'd prefer to keep using static imports if possible.
Also, in case this is not clear, this is all server side. I'm not trying to pass a new module to the client, just get one node module to reload another node module.
I don't know what the reason behind doing this,
I think this is not safe to change the context of modules at runtime and cause unexpected behaviors and this is one of the reasons that Deno came to.
If you want to run some code evaluation at runtime you can use something like this using vm:
https://nodejs.org/dist/latest-v16.x/docs/api/vm.html
You could try using nodemon to dynamically refresh when you make code changes
https://www.npmjs.com/package/nodemon
I agree with #tarek-salem that it's better to use vm library. But there is another way to solve your problem.
There is no way to clear the dynamic import cache which you use in question (btw there is a way to clear the common import cache because require and common import has the same cache and the dynamic import has its own cache). But you can use require instead of dynamic import. To do it first create require in parser.mjs
import Module from "module";
const require = Module.createRequire(import.meta.url);
Then you have 2 options:
Easier: convert look.mjs into commonjs format (rename it look.cjs and use module.exports).
If want to make it possible to either import AND require look.mjs you should create the npm package with package.json
{
"main": "./look.cjs",
"type": "commonjs"
}
In this case in parser.mjs you will be able to use require('look') and in other files import('look') or import * as look from 'look'.

How to package object prototypes in separate file

I have created a number of String.prototype functions which for maintainability I'd like to have in its own file. That is, I'd like to include the file in a javascript project and thus have all the String functions defined.
I could create a module that exports each function, but then I'd have to assign each function as its own String prototype, yes? Something like
var myStringFunctions = require("myStringFunctions");
String.prototype.func1 = myStringFunctions.func1;
Is there a way to include such a file so that the prototypes are defined as part of the inclusion?
Try it, you will see your code and using require("./myStringFunctions"); works just fine.
./myStringFunctions.js
String.prototype.func1 = function() {
return this.toUpperCase(this);
};
./index.js
require("./myStringFunctions");
console.log("foo".func1()); // FOO
If your JS is going to run in the browser, you can use JS modules with the import and export syntax if you use a module bundling build tool like Webpack: https://webpack.js.org/ .
If your JS is running in a Node.js environment, modules are supported: https://www.w3schools.com/nodejs/nodejs_modules.asp

returning instanced class + babel JS

I'm building a "library" on JS, and it is mandatory to be only one .js file.
I just started to build, and i got this until now:
app-es6/main.js
class Sjs {
create(obj) {
console.log(obj);
}
}
index.html
<script src="app/main.js"></script>
<script>
let sjs = new Sjs();
sjs.create({
type: 'select'
});
</script>
.babelrc
{
"presets": ["es2015"]
}
What i need to do:
1) The class should not be instantiated in html, the instance should come ready from js, so i can just type sjs.create(), like jQuery, moment, etc.
2) If i need to import more JS files, to build somehting more structured, can i "wrap" to a single js, minimized?
Thanks in advice.
1) The class should not be instantiated in html, the instance should come ready from js, so i can just type sjs.create(), like jQuery, moment, etc.
Just put it in the main.js, after the class declaration:
let sjs = new Sjs();
let at global scope creates a global variable (though not a property on the global object [usually accessed as window on browsers]). If you want that property as well, use var instead of let or assign to window.sjs (which will also create a global variable; all properties on the global object are globals, it's just that as of ES2015, not all globals are properties on the global object).
That said, if it's a singleton, there isn't much benefit to using class. It's probably also worth noting that jQuery and MomentJS both expose functions (jQuery/$, moment), not non-callable objects.
2) If i need to import more JS files, to build somehting more structured, can i "wrap" to a single js, minimized?
You're looking for a bundler, like Webpack, Rollup, etc. They have plugins for integrating with Babel, doing minification, ...

Faux-server dosnt work corectly with require.js

I have some Backbone Model structure in my project. Each of this model need to fetch or save and I decided to use a faux-server to mocks the server-side. In my projekt i also use a require.js and with it I have a problem.
Example:
define([
'models/billings/details',
'models/statistics/abonent',
'mocks/billings/details',
'mocks/statistics/abonent'
], function(detailsModel, statisticsAbonentModel) {
var detailsM = new detailsModel();
detailsM.fetch({async: false});
var statisticsAbonentM = new statisticsAbonentModel();
statisticsAbonentM.fetch({async: false});
});
When I define more then one mocks - only the last always run, the previous not.
When i define only one, it always run.
I try to use shim in requrie to have a one global fauxServer for each mocks but it doesnt work.:
shim:{
fauxServer: {
deps['backbone'],
exports: 'fauxServer'
}
}
I dont know where is the problem.
Here is an answer
update the lib version of faux-server to at least 0.9.3
You dont need the shim - faux-server is an AMD module
Be sure if your route function name is a unique

require.js: how can I load a module that defines a name under a different name?

I'm trying to load underscore.js with require.js like this:
require(["libs/underscore-1.2.3.js"], function(_) {
...
});
But this doesn't work because underscore.js exports a module name: define('underscore', function() { ... }).
Without renaming lib/underscore-1.2.3.js, how can I load it with require.js?
Alright, after some more googling, I've found: https://github.com/documentcloud/underscore/pull/338#issuecomment-3245213
Where
#dvdotsenko all AMD loaders allow mapping a module ID to a partial path, usually the configuration is called 'paths', so to do what you want:
requirejs.config({
paths:
underscore: 'js/libs/underscore-1.2.3.min'
}
});
require(['underscore'], function () {});
Since underscore is used by other higher-level modules, like backbone, a common dependency name needs to be used to communicate a common dependency on underscore, and it makes sense to call that dependency 'underscore'. The paths config gives a way to do the mapping to a specific URL you want to use for that dependency.
This doesn't answer my question (ie, I still don't know how I'd go about loading underscore if all I had was a URL), but at least it's a functional workaround.
While this doesn't strike me as the most ideal solution, you can require your external files, and then require their registered module names in the inner block.
JSFiddle Example
require(
['require','http://documentcloud.github.com/underscore/underscore-min.js'],
function(require){
require(['underscore'],function(_){
var a = _.intersection([1,2,3],[2,3,4]);
document.write("Underscore is available in the closure : " + a);
})
}
)
It might not look pretty, but that might be a recommended pattern for loading up initial assets so that they can be required intuitively in dependent modules.

Categories