I’m working on a large project and there appears to be no way to create a global for the entire project. At the very least I need a global object to which I can attach my class definitions so as to avoid polluting the global name space. Here is the load order of my project files per the Meteor load order rules:
The problem is that any definitions in /lib/globals.js are not available to lib_bar.js and lib_foo.js. Perhaps there is there a Meteor idiom that solves this difficulty?
What I really want is something like the way “main” filenames are treated. So files named global get promoted to the beginning of the load order even before lib directories.
Since files in subdirectories are loaded first, would it make sense to put globals.js in /lib/globals/ or /lib/lib/ ? Or am I not interpreting that correctly?
The problem with putting the globals in /lib/lib/lib/lib… is that it is a) obscure/tortured, and b) not general since you don’t know how many levels deep of /lib/lib… you’d need to go. Depends on how deep the hierarchy is of your app.
Putting the globals in a package seems really obscure and tortured as well.
I am currently struggling with the exact same problem.
My concerns are:
Ensure proper load order
Ensure easy refactoring
Ensure ide assistance
If I use packages, I need to declare all the dependencies (including basic things like templating, underscore etc) of the package manually. It is really a bothersome chore and often times puzzling. Also, moving the code around is really tough because one needs to update the paths on package.js every singl time.
If I use subdirectories, it quickly becomes ugly and once inter-dependence of libraries kick in, almost impossible to manage.
The only thing I’ve decided to keep is lay out the project structure by module, so that instead of some top level client, server, both etc directories, I have module/client, module/server, module/lib, module/blabla directories. This makes me feel better knowing that it would be easier one day to refactor them out into packages.
But, yeah, the problem is there and does not seem to have a proper, easy solution.
Use the scripting execution level only for class and function definitions. No logic or variables here.
Assign all definitions to a global object called APP. This avoids name conflicts.
Define all my logic in classes, even singleton objects. The class constructors initialize any variables common to the class methods.
Instantiate the singleton classes that comprise the application in main.coffee (which runs after everything else) and add the resulting objects to my APP global. This allows control over initialization order. And also makes sure that all your definitions are available at initialization time.
Coffeescript makes the use of classes much easier.
What does this not solve?
a) The global definition for APP needs to happen before everything else. (Hence the main motivation for this thread.)
b) It is helpful to allow configuration information alter your definitions. That APP.configuration variable needs to be available before everything else.
When your app becomes big, the only sane solution for the moment is to put everything in packages.
That way you get proper import/export.
The problem is that you can’t create hierarchies of packages (folders), so everything lies in the same flat folder.
Like sashko said, just create a package that exports your global(s). This way the globals are initialized before your app code, because packages are loaded before you app code. You can still use app files and don’t need to use a full package approach.
General rule: If you need full control, use a package.
I do agree using clasess (will also be easier with ES6) is a good way to keep and follow a structure.
On the other hand, I’m coming from the java world and find javascript’s functional approach a liberation from oop which itself calls for a philosophical argument
About they way I use classes to organize a project, this use is completely separate from the functional/OOP debate.
I am proposing singleton classes that simply allow your app to be organized in a hierarchical name space. So a function (method) in a module (class) in your app would have a hierarchical name APP.module1.function1. A similar effect can be had without classes by assigning a function to a global. In both cases this does nothing to impede (or help) functional programming styles.
The singleton class organization also enables a convenient place to save module constants like external references. Also global state. So where in node you are used to doing this:
foo = require('foo')
console.log foo.bar()
With my methodology, reference to a module in your hierarchy is similar:
@foo = APP.foo
console.log @foo.bar()
This is a very light weight mechanism to enable module linking within your app.
Member variables can be used to encapsulate module state in the naming hierarchy. For example a collection associated with your module can be referenced at the top level for debugging purposes as:
APP.foo.authors.find({name:'Juan'})
None of this interferes with functional programming styles.
(But what I still need to make this complete is to have globals.coffee promoted to the head of the load order so APP can be defined before anything else.)
I have another case, I already load at a specific version of require (With extra features and classes included for Qlik sense a dashboard app), just by putting it into the compatibility folder, works great. But how can I make 1 singleton object so that my header and my main template can both use the same app object? Session var or …?
Example code; (don’t mind the require statements)
Thanks!
var config = {
host: “myhost.com”,
prefix: “/”,
port: window.location.port,
isSecure: true
};
require([“js/qlik”], function(qlik) {
// open the app
var app = qlik.openApp(“c31e2aba-3b46-4b13-8b87-c5c2514dea1d”, config);
// insert Qlik objects into the page.
app.getObject(document.getElementById(“LB01”), “uPyZavD”)