Does anyone know how to use node's native "module" module (!) to load in a module manually from file as an alternative to using the normal require mechanism?
I know it's an odd request, but I need modules that declare their variables globally (to that module) and that are wrapped as new modules each time they are required, e.g.
var private;
module.exports = {
setPrivate: function (value) {private = value}
}
To elaborate, if you call require twice in separate places with the same path you get the same module back. I need to always get a new module so that when required in twice setPrivate can only affect its own variable;
Basically, I need to work out the mechanism that require() uses to create and return a module the first time it is called. Have played around with instantiating Module directly (as in https://github.com/joyent/node/blob/master/lib/module.js#L293), but no luck - the exports property is always an empty object.
Please guys no suggestions to just use a constructor... I appreciate I have an unusual use case.
You don't need to do anything so complicated.
Instead, you can simply delete it from the cache:
delete require.cache[module.id];
Related
requireJS is giving me a headache atm. requireJS is AMD which by definition says it's asynchronous. Normally I would define a module like this.
define("some Name", ["./moduleOne"],function(moduleOne){
//this would be undefined
moduleOne.whatEver();
var aMethod = function(){
//user aModule.whatever();
}
return {
method: aMethod;
}
});
Ok, I got that I can't directly use moduelOne.whatever because it is loaded asynchronous and it's not there if the callback is being called.
First Question, is this correct?
Now if I change the module definition to this:
define("some Name", function(require, exports){
var moduleOne = require(".moduleOne");
//this is OK
moduleOne.whatEver();
var aMethod = function(){
//user aModule.whatever();
}
exports.method = aMethod;
});
I can use aModule.whatever directly. As I read from the docs, using this (commonJS) style, requires parses the function with Function.prototype.toString, sees the require statement and load the modules directly.
I am pretty sure, I am misunderstanding something here and it would be nice of someone could explain how exactly requireJS works and if the second style is really synchronous.
Thanks
You've misunderstood how it works.
In both examples you give in your question the sequence of execution is:
Something requires the module named some_Name. (I don't think RequireJS is happy with module names that have spaces so I'm assuming a module name with an underscore.)
RequireJS looks for the dependencies and the factory function for the module some_Name. The factory is the function given to define when you define the module.
a. If it happens that define("some_Name"... was called before this step, then RequireJS just gets the dependencies and factory function that was given to define.
b. If define("some_Name"... has not been executed yet, RequireJS will go to the network and attempt to fetch a file that contains the define call and execute it. By convention this will be a file with the same name as the module name + the .js extension, but this can be overridden in RequireJS' configuration.
RequireJS checks whether the dependencies are loaded. If not, then it issues require calls for each dependency that is not loaded yet.
RequireJS calls the factory function with the resolved dependencies.
Note that I did not go over all possible scenarios here. I'm sticking with the most common cases to keep things simple.
So...
Ok, I got that I can't directly use moduelOne.whatever because it is loaded asynchronous and it's not there if the callback is being called.
First Question, is this correct?
No, this is not correct. By the time moduleOne.whatEver(); executes, the module moduleOne must have been loaded already. If moduleOne is undefined this is not because of RequireJS' asynchronous nature but because there is a bug in how moduleOne is defined. For instance, if it exports the value undefined, then moduleOne will be undefined. Or you may get an undefined value for moduleOne.whatEver which will then cause an error when you try to call it, but this would be caused by, for instance, forgetting to export whatEver.
The difference between the 2nd case and the first is that the 2nd uses the CommonJS sugar syntax and this causes step 2 above to have a bit of additional processing. Before RequireJS executes the factory it parses the function (as you mentioned) and then processes the factory function as if the defined had been called like this:
define("some_Name", ['require', 'exports', './moduleOne'], function (require, exports) {
The require and exports modules are special modules defined internally by RequireJS. Note how RequireJS adds ./moduleOne at the end of the list of dependencies. Once this is done, the process is exactly the same as for the 1st case.
By the time var moduleOne = require("./moduleOne"); is executed, the module has already been loaded. So what this line does is merely return a reference to the module.
I use TypeScript to code my javascript file with Object Oriented Programing.
I want to use the node module https://npmjs.org/package/typescript-require to require my .ts files from other files.
I want to share my files in both server and client side. (Browser) And that's very important. Note that the folder /shared/ doesn't mean shared between client and server but between Game server and Web server. I use pomelo.js as framework, that's why.
For the moment I'm not using (successfully) the typescript-require library.
I do like that:
shared/lib/message.js
var Message = require('./../classes/Message');
module.exports = {
getNewInstance: function(message, data, status){
console.log(requireTs);// Global typescript-require instance
console.log(Message);
return new Message(message, data, status);
}
};
This file need the Message.js to create new instances.
shared/classes/Message.ts
class Message{
// Big stuff
}
try{
module.exports = Message;
}catch(e){}
At the end of the fil I add this try/catch to add the class to the module.exports if it exists. (It works, but it's not really a good way to do it, I would like to do better)
If I load the file from the browser, the module.export won't exists.
So, what I did above is working. Now if I try to use the typescript-require module, I'll change some things:
shared/lib/message.js
var Message = requireTs('./../classes/Message.ts');
I use requireTs instead of require, it's a global var. I precise I'm using .ts file.
shared/classes/Message.ts
export class Message{
// Big stuff
}
// remove the compatibility script at the end
Now, if I try like this and if I take a look to the console server, I get requireTs is object and Message is undefined in shared/lib/message.js.
I get the same if I don't use the export keyword in Message.ts. Even if I use my little script at the end I get always an error.
But there is more, I have another class name ValidatorMessage.ts which extends Message.ts, it's not working if I use the export keyword...
Did I did something wrong? I tried several other things but nothing is working, looks like the typescript-require is not able to require .ts files.
Thank you for your help.
Looking at the typescript-require library, I see it hasn't been updated for 9 months. As it includes the lib.d.ts typing central to TypeScript (and the node.d.ts typing), and as these have progressed greatly in the past 9 months (along with needed changes due to language updates), it's probably not compatible with the latest TypeScript releases (just my assumption, I may be wrong).
Sharing modules between Node and the browser is not easy with TypeScript, as they both use very different module systems (CommonJS in Node, and typically something like RequireJS in the browser). TypeScript emits code for one or the other, depending on the --module switch given. (Note: There is a Universal Module Definition (UMD) pattern some folks use, but TypeScript doesn't support this directly).
What goals exactly are you trying to achieve, and I may be able to offer some guidance.
I am doing the same and keep having issues whichever way I try to do things... The main problems for me are:
I write my typescript as namespaces and components, so there is no export module with multiple file compilation you have to do a hack to add some _exporter.ts at the end to add the export for your library-output.js to be importable as a module, this would require something like:
module.exports.MyRootNamespace = MyRootNamespace
If you do the above it works, however then you get the issue of when you need to reference classes from other modules (such as MyRootNamespace1.SomeClass being referenced by MyRootNamespace2.SomeOtherClass) you can reference it but then it will compile it into your library-output2.js file so you end up having duplicates of classes if you are trying to re-use typescript across multiple compiled targets (like how you would have 1 solution in VS and multiple projects which have their own dll outputs)
Assuming you are not happy with hacking the exports and/or duplicating your references then you can just import them into the global scope, which is a hack but works... however then when you decide you want to test your code (using whatever nodejs testing framework) you will need to mock out certain things, and as the dependencies for your components may not be included via a require() call (and your module may depend upon node_modules which are not really usable with global scope hacking) and this then makes it difficult to satisfy dependencies and mock certain ones, its like an all or nothing sort of approach.
Finally you can try to mitigate all these problems by using a typescript framework such as appex which allows you to run your typescript directly rather than the compile into js first, and while it seems very good up front it is VERY hard to debug compilation errors, this is currently my preferred way but I have an issue where my typescript compiles fine via tsc, but just blows up with a max stack size exception on appex, and I am at the mercy of the project maintainer to fix this (I was not able to find the underlying issue). There are also not many of these sort of projects out there however they make the issue of compiling at module level/file level etc a moot point.
Ultimately I have had nothing but problems trying to wrestle with Typescript to get it to work in a way which is maintainable and testable. I also am trying to re-use some of the typescript components on the clientside however if you go down the npm hack route to get your modules included you then have to make sure your client side uses a require compatible resource/package loader. As much as I would love to just use typescript on my client and my server projects, it just does not seem to want to work in a nice way.
Solution here:
Inheritance TypeScript with exported class and modules
Finally I don't use require-typescript but typescript.api instead, it works well. (You have to load lib.d.ts if you use it, else you'll get some errors on the console.
I don't have a solution to have the script on the browser yet. (Because of export keyword I have some errors client side) I think add a exports global var to avoid errors like this.
Thank you for your help Bill.
I have searched high and low for documentation on this, but I just cannot find anything anywhere.
I am using Aloha and want to use their sidebar prototype to create a new side bar of my own attached to other plugin functionality.
Their sidebar.js starts off with this, but I can't for the life of me find any documentation that explains what it means.
define( [
'aloha/core',
'aloha/jquery',
'aloha/selection'
], function (Aloha, jQuery, Selection, Plugin) {
It then goes on in that wrapper to define a bunch of functions, so vars and some proptotypes- which I can just about get my head around...
What is that saying or where can I find an explanation?
I can't say for sure without seeing the entire script, but it's likely to be the define function from RequireJS, in particular the "define with dependencies" form of that function. It is used to define a "module":
A module is different from a traditional script file in that it
defines a well-scoped object that avoids polluting the global
namespace. It can explicitly list its dependencies and get a handle on
those dependencies without needing to refer to global objects, but
instead receive the dependencies as arguments to the function that
defines the module.
And the "define with dependencies" form of define is described as follows:
If the module has dependencies, the first argument should be an array
of dependency names, and the second argument should be a definition
function. The function will be called to define the module once all
dependencies have loaded. The function should return an object that
defines the module.
This is AMD pattern for writing modules which AMD stands for Asynchronous Module Definition for when you need to import modules async basically rather than something like commonJS.
define(['module1', 'module2'], function(module1, module2) {
console.log(module1.sayHi());
});
Define takes an array of dependencies and once all those are loaded in the background (async) in a non-blocking way, define calls the callback which in turn accepts arguments (in this case the dependencies).
Another thing to note is that each one of those modules also needs to be defined using "define" keyword. So for instance module1 would be defined like below :
define([], function() {
return {
sayHi: function() {
console.log('Hi Hi');
},
};
});
This way of writing modules (AMD) allows you to write with browser compatibility in mind (no require() like in nodeJS) and also you can define many formats including objects, JSON, etc while for instance commonJS needs modules to be objects.
Keep in mind, AMD has it's own downfalls. Hope this helps someone.
require.js states the way of defining objects inside modules with define([requiremens], object) as best way.
So every page, or other js file, will do require() call and receive modules as parameters.
This works pretty fine, each function/module has own namespace.
The problem is that I have:
// AJAX/Requests.js
define(['UI/Message'],function(Message){
var Requests={
checkResponse:function(response){
//1==ok
//0==error
//2==good message
//3==good message, but still stop
if(response.status==1){
return true;
}
else if(response.status==2){
Message.good(response.message);
return true;
}
else if(response.status==3){
Message.good(response.message);
return false;
}
else{
Message.bad(response.message);
return false;
}
}
};
return Requests;
});
Now the UI/Message is defined in the same way, and it returns object.
But when I edit file with requests, I can't navigate by code, so if I want to edit Message object, the only way is to go and open file the myself and to find function I need, rather than have the IDE jump there for me.
Is there some workaround for pycharm specifically or to require.js in common to solve this issue? When you have a lot of code it becomes a mess to navigate it, which is why I use an IDE in the first place!
And what worse: The editor never knows what functions objects have!
The one possible solution I can see is to not to use enclosed namespaces, and to declare global variable before the define() call, but in this case all objects shall be called like UI_Message, AJAX_Requests. In order to be sure, that I don't have some Message in two different locations....
And I am not sure, if require.js optimizer will use this correctly. Require.js documentation states very clear, to stay away from global variables.
It's a known issue, please star/vote.
From the issue description:
The dojo library switched to AMD's format define() for loading modules
instead of dojo.require(). Previously I was able to use Ctrl+B on
dojo.require('path.to.someJs') to jump to the declaration. This does
not work on the new format define(['path/to/someJs]', ...).
As PyCharm, WebStorm, PhpStorm and IntelliJ IDEA share the same JavaScript plug-in, this issue also applies to the product that you are using. You will continue to observe the described problem until this bug is fixed. Sorry for the inconvenience.
WebStorm (at least 6.0.2) supports code navigation with RequireJs if you're defining your modules with the CommonJs wrapper and use the exports and module arguments:
//foo.js
define(function(require, exports, module) {
//use exports to expose properties for code navigation in other modules
exports.bar = function() {}
});
Apparently, it works even if the module using it doesn't use the CommonJs wrapper format:
define(['./foo'], function(foo) {
foo.bar(); //code navigation works here
}
If the other IDEs use the same JavaScript plug-in as CrazyCoder said, it may work on their newer releases as well.
I know how to make modules in NodeJS (it's rather simple). However, if I want to make something that is supposed to work in both server- and client-side environments, then would would one accomplish this?
Let's imagine you want to create a Model type ("class"). Let's say you have a class-creation function called Lib.define(). So, you write this:
Lib.Model = Lib.define({
init: function() {
// constructor...
},
save: function() {
// saves the model.
}
});
The above code would make Lib.Model an object which represents an instantiable type. However, how would you write it so that it's also NodeJS compliant? If you try to require the above file (require('Model.js')), it would not do anything since there is no assignment to export. If, however, I do that, then am I just supposed to have a useless export object in client-side environments?
Is there other ways to do this besides require that could just simply load and parse the JS and work globally so that the above code would produce Model member in the global variable Lib?
I am looking into vm right now, but I am not sure how would I use it properly. I do have a file/class loader that resolves paths and loads scripts just like what Dojo does. Should I write some logic there that works as usual on client-side (places script tags), and for NodeJS, it would simply read the file contents and vm.runInThisContext(code)?.
JSHint just detects whether there's an exports symbol and adds to it if there is. Their check looks like this:
// Make JSHINT a Node module, if possible.
if (typeof exports == 'object' && exports)
exports.JSHINT = JSHINT;
That checks to see if exports is an object and then checks that it's not null (via && exports). Seems a reasonable approach, although of course it's specific to the CommonJS module system (which is what Node uses).