patternjavascriptMinor
Structure a webapp using RequireJS
Viewed 0 times
webapprequirejsusingstructure
Problem
I've written a small webapp in JavaScript, and am now essentially rewriting it to use RequireJS. I'm doing this partly to get more familiar with RequireJS (which I have little experience with), as well as for ease of maintaining and upgrading the app.
I'm hoping to get feedback on whether the structure I'm looking at implementing is reasonable/useful/extensible/totally insane. I've been through the require docs, reading related SO posts and some samples on GitHub, but I'm not sure I'm totally 'getting' Require.
If there are fundamental flaws in the logic it'd be great to get some links to resources (either JS or RequireJS specific), and to get feedback about the overall structure of the app itself. Suggestions for design patterns also very much appreciated, there's some stuff in there that feels kind of counter intuitive.
main.js
app.js
reader.js (it's an online e-reader)
env.js
I'm hoping to get feedback on whether the structure I'm looking at implementing is reasonable/useful/extensible/totally insane. I've been through the require docs, reading related SO posts and some samples on GitHub, but I'm not sure I'm totally 'getting' Require.
If there are fundamental flaws in the logic it'd be great to get some links to resources (either JS or RequireJS specific), and to get feedback about the overall structure of the app itself. Suggestions for design patterns also very much appreciated, there's some stuff in there that feels kind of counter intuitive.
main.js
require({
paths: {
jquery: '../bower_components/jquery/jquery'
}
}, function() {
'use strict';
require(['jquery', 'app', 'reader', 'env'], function($, App, Reader, Env) {
$(document).ready(function() {
var app = new App(
new Reader(),
new Env()
);
});
})
});app.js
define(function() {
return function(reader, env) {
this.reader = reader,
this.env = env
};
});reader.js (it's an online e-reader)
define(['jquery'], function($) {
return function() {
this.components = [],
this.firstPage = null,
this.lastPage = null,
this.maxFontSize = function() {
return this.env.isIOS() ? 120 : 160;
}
};
});env.js
define(['jquery'], function($) {
return function() {
this.isIOS = function() {
return navigator.userAgent.match(/(iPad|iPhone|iPod)/i) ? true : false; // for example.
}
};
});Solution
This is honestly pretty good. I usually use
Next, I'll ask why bother injecting
app.js
Finally, a couple notes on your specific files - you probably want to name those top-level functions even when returning immediately
env.js
That both makes it clear from within what module you're in, the fact that you expect it to be used with
I'll also point out that - it's a matter of style but you're on CR so I consider it solicited - hardly ever is code made more bugproof or more legible by using constructor functions. reader.js could just as easily be the following and not depend on someone remembering to use
requirejs.config to set the paths and configurations on require (it's going to grow a lot as you add things like shims, urlArgs, etc). You will also probably want to reuse it in several places. See my blog article on how I recommend doing this. The general idea is that you don't use data-main to bootstrap things, you instead have a request for the configuration file and another to actually bootstrap the specific page of your application.Next, I'll ask why bother injecting
reader and env manually into application? Injecting dependencies is what RequireJs already does.app.js
define(['reader', 'env'], function(Reader, Env) {
return function() {
this.reader = new Reader(),
this.env = new Env()
};
});Finally, a couple notes on your specific files - you probably want to name those top-level functions even when returning immediately
env.js
define(['jquery'], function($) {
return function Env() {
...
};
});That both makes it clear from within what module you're in, the fact that you expect it to be used with
new, and will generate nicer stacktraces.I'll also point out that - it's a matter of style but you're on CR so I consider it solicited - hardly ever is code made more bugproof or more legible by using constructor functions. reader.js could just as easily be the following and not depend on someone remembering to use
new and always bind functions.var env = {
components: [],
firstPage: null,
lastPage: null,
maxFontSize: function() {
return this.env.isIOS() ? 120 : 160;
}
};
return env;Code Snippets
define(['reader', 'env'], function(Reader, Env) {
return function() {
this.reader = new Reader(),
this.env = new Env()
};
});define(['jquery'], function($) {
return function Env() {
...
};
});var env = {
components: [],
firstPage: null,
lastPage: null,
maxFontSize: function() {
return this.env.isIOS() ? 120 : 160;
}
};
return env;Context
StackExchange Code Review Q#45344, answer score: 2
Revisions (0)
No revisions yet.