I am mildly familiar with require.js and Backbone.js having used them together for about a year now and relatively new to Backbone.Marionette although I am very interested in what it can bring to the table.
In looking for examples of project structure (I can get a little obsessed with this stuff) I have found https://github.com/BoilerplateMVC/Marionette-Require-Boilerplate and other similar examples.
Something that has been bothering me: in their app.js file, they return a reference to an instance of a Marionette application, ie:
var app = new Backbone.Marionette.Application();
app.addInitializer(...);
...
return app;
And in many components, they reference the app.js via require.js and use as follows:
define([..., 'app'], function (... , App) {
App.someProperty(...);
});
Now here's what I'm not understanding: I have been under the assumption that the code in their app.js is really more like a Factory than a Class since it returns an instance of an application rather than, say, a modified prototype or extension thereof.
Therefore, when they reference app.js, aren't they actually creating a whole new instance rather than accessing some sort of shared instance? There is nothing to suggest that app.js is returning a singleton in their code.
And yet, it works, and obviously I am the one who is confused.
So, why does this work?
This works because objects are passed by reference in javascript and the fact that require.js only loads every dependency once. Then, app.js returns an initialized instance, and every other module that requires 'app' gets reference to the same object.
It's not a factory, it's simply an initialized application object instance.
Related
I have a variable (a constructed filename) that I need to get from within an API in one file to be stored as a variable in another file.
The way my code is set up, there's not really a way (that I can think of) to get this variable from one file to another without using globals. I've been looking around at a few different methods and decided to create a globals module (globals.js):
var globals = {
'new_img': ''
}
module.exports = globals;
I've written:
var globals = require('./public/js/globals');
In my server.js and in my routes.js so that all of my API's and controllers have access to this module.
When I serve this web application and multiple people have their own instances of the webpage, will they all be using the same globals module? This is not my desired effect. What would be better ways of going about this?
yes they will be using the same instance.
That pattern is a singleton, you're exporting and making global a variable, the same spot in memory will be visibile by the whole app.
With the help of the debugger you can analyze the require code in depth and see that Nodejs will cache the result of that call and return the same instance everytime.
NodeJS source code:
if your desired result is to have different instances you can shallow clone the object.
var globals = _.extend({}, require('./public/js/globals')); //ecma5 + underscore.js
var globals = Object.assign({}, require('./public/js/globals')); //ecma6
In one of the rails app I am trying to use backbone with "rails-backbone" gem,
And I have created one model using scaffolding which is working fine.
but I have another model and I am trying to use different router for it, but when tries to instantiate that router from index.html.erb it fires,
"Uncaught TypeError: undefined is not a function" which clearly means there is no such router. But it is there and even in developer's tool it shows those JS files. I tried all different ways but it didn't work. Thanks in advance.
I'd guess that you're defining your router like this:
class SomeRouter extends Backbone.Router
# router code goes here
and then you're trying to create one with:
r = new SomeRouter
But CoffeeScript will wrap your files in a function to prevent scope creep:
Although suppressed within this documentation for clarity, all CoffeeScript output is wrapped in an anonymous function: (function(){ ... })(); This safety wrapper, combined with the automatic generation of the var keyword, make it exceedingly difficult to pollute the global namespace by accident.
If you'd like to create top-level variables for other scripts to use, attach them as properties on window, or on the exports object in CommonJS. The existential operator (covered below), gives you a reliable way to figure out where to add them; if you're targeting both CommonJS and the browser: exports ? this
That wrapper will hide SomeRouter inside a function so there will be no SomeRouter visible outside the file which defines it.
A common solution in Rails/Backbone apps is to manage the namespaces yourself. Set up your own namespace somewhere before any other (Java|Coffee)Script will be pulled in:
# AppName is just a placeholder, you'd use something more
# sensible in real life.
window.AppName =
Routers: { }
Views: { }
Models: { }
Collections: { }
and then define your router as:
class AppName.Routers.SomeRouter extends Backbone.Router
#...
and later:
r = new AppName.Routers.SomeRouter
similarly with models, collections, and views that need to be globally visible.
I scaffolded a simple Angular app using Yeoman, and I've been playing with it ever since.
Inside the file app.js, which is the first one listed as a <script> inside index.html, I define the main module as:
angular.module('myMod', [])
.config(...)
Note the empty array of dependencies.
Now, when I want to, say, add a filter to this module, I create a myFilter.js file (which I load after app.js inside index.html); myFilter.js consists of:
angular.module('myMod').filter(...)
Note there's just one parameter to the module() function. If I pass the empty array of dependencies as a parameter to this module() function, really nothing appears on screen.
I've been playing with a bunch of other files which extended myMod with controllers, and passing [] as a parameter to the angular.module() function breaks my app every time.
It seems to me like I can only call angular.module() once using the second parameter, which may have some sense (how many times do I want to list my dependencies? What about consistency?). Is it that way?
If it is, is there some standard place where to list dependencies for a module?
angular.module("myModule",["dependencyA"]) will create a new module (this will crash if module allready exists.)
angular.module("myModule") uses an already known module.
This will also affect how you need to load the scripts in the index.html
You should declare your dependencies only once. In addition, it's best practice to keep all of your filters as a separate module that your app depends on, for example:
var myApp = angular.module('myApp', ['myApp.filters', 'myApp.directives', 'myApp.someOtherDependency']);
then, you would define your filters as a module that your app is dependant on:
angular.module('myApp.filters', []).filter(...)
I am learning the source code of hexo, a project based on node.js.
And there is a file init.js:
if (results.config){
require('./plugins/tag');
require('./plugins/deployer');
require('./plugins/processor');
require('./plugins/helper');
require('./plugins/filter');
require('./plugins/generator');
}
why these require statements have no reference? So I checked each index.js under these folder(e.g. tag), the index.js is looking like:
require('./init');
require('./config');
require('./generate');
require('./server');
require('./deploy');
require('./migrate');
require('./new');
require('./routes');
require('./version');
require('./render');
No exports found. I am wondering how these requires work.
I looked at the source you're talking about, and the basic answer to your question is that the code in those requires gets run. Normally, you're right that you need to have some kind of export to make use of objects inside those files, but hexo is being a bit nonstandard.
Instead of having each module be independent and fairly agnostic (except via requires), what they're doing is creating an object called 'extend' (look in extend.js) then each of those individual files (e.g. ./init, ./migrate, etc) require extend.js and hang new objects and functions on it in a sort of namespaced fashion.
If you look at the end of those files you'll see something calls to extend.tag.register and others. Modules are cached when required, so in practice it acts something like a singleton in other languages the way they're doing it.
As Paul points out, the requires you see should be considered as functional units themselves, rather than returning any useful values. Each of the files calls an function to modify an internal state.
My application has a View() model that fetches HTML, CSS, etc. with a simple call to a view path. As many of these views and viewlets are shared or required multiple times I'd like to maintain a 'cache' object of loaded views that any new instance of a View() can check and read from if that particular view has been loaded.
In a requireJS implementation, any ideas on where is best to put this view 'cache' object? Ideally I'd like to have something like a Session() object that contains it, and I'd be able to reference a single instance of Session() from anywhere in my app.
Any thoughts on best practices for this?
Many thanks!
I suggest you to use a Singleton approach creating a simple module for this case. For instance, you could create a module like this:
define(["mydep","myotherdep"], function(dep1,dep2){
var Hellovariable = {
"attr1": ...,
"attr2": ...,
...
"attrN": ...
}
return Hellovariable;
});
When you call this module using AMD you will only have an unique instance for this variable and its attributes.