1 | #simple-app
|
2 |
|
3 | A simple module to kick-start your Node.js app development.
|
4 |
|
5 | npm install simple-app
|
6 |
|
7 | ![screenshot](http://i.imgur.com/ua90vzQ.png)
|
8 |
|
9 |
|
10 | It has all the Express, Mongoose, Socket.io, Jade, Passport, and all that stuff pre-configured for you.
|
11 |
|
12 | It assists you without getting in your way, or your style of doing things.
|
13 |
|
14 |
|
15 | ##Routing
|
16 |
|
17 | To configure routes, you can do
|
18 |
|
19 | var app = require('simple-app');
|
20 | app.get('/', function(req, res, next){
|
21 | res.render('index')
|
22 | });
|
23 |
|
24 | Since a module in Node.js is only loaded once, you can include it in any file and configure it there. For example a separate file for routes
|
25 |
|
26 | **index.js**
|
27 |
|
28 | require('simple-app');
|
29 | require(./routes/main);
|
30 |
|
31 | **routes/main.js**
|
32 |
|
33 | var app = require('simple-app');
|
34 | app.get('/myroute', function(req, res, next){
|
35 | res.render('myview')
|
36 | });
|
37 |
|
38 | Note, it's important to *first* require it in your *main* `index.js` (or `server.js`, or `app.js`) because that's the path relative to which it looks for `views` and `public` folders etc.
|
39 |
|
40 |
|
41 | ## Client-side
|
42 |
|
43 | It follows the widely accepted standard of having your views (Jade, HTML) in the `views` directory, and your images, CSS, client-javascripts in `public` and `client` directories.
|
44 |
|
45 | Anything in your `public` or `client` directory is available as a static resource.
|
46 |
|
47 | `public/vendor/some.css` `=>` `GET /vendor/some.css`
|
48 |
|
49 | `client/app.js` `=>` `GET /app.js`
|
50 |
|
51 |
|
52 | ## Minification
|
53 |
|
54 | Minify your resources! If you set an environment variable or config variable `minify`, it'll minify all the CSS and JS files when the app starts up.
|
55 | For Stylus styles, it'll also convert and minify it as CSS.
|
56 |
|
57 | It'll include jQuery, Angular, Bootstrap *before* any other files.
|
58 |
|
59 | For all CSS and JS files in `public` it'll create `public.css.min` and `public.js.min`
|
60 |
|
61 | For all CSS/Stylus and JS files in `client` it'll create `client.css.min` and `client.js.min`
|
62 |
|
63 | ## Configuration
|
64 |
|
65 | You can configure the app, like its name, IP address, port, external domain name that it's hosted on (for generating Sitemap), and whether the app is in development mode or production mode.
|
66 |
|
67 | There are two ways to configure these settings:
|
68 |
|
69 | 1. through environment variables.
|
70 |
|
71 | # defaults
|
72 | export app="SimpleApp"
|
73 | export IP="0.0.0.0"
|
74 | export PORT=80
|
75 | export NODE_ENV="production"
|
76 | export NODE_ENV="development"
|
77 | # default is development
|
78 |
|
79 | 2. through a `config.js` file
|
80 |
|
81 | var config = module.exports;
|
82 | config.name = 'TestApp';
|
83 | config.ip = "127.0.0.1"
|
84 | config.port = 10000;
|
85 | config.hostname="www.myapp.com"
|
86 |
|
87 | It tries to normalize all setting names to lowercase, and having several different aliases for same settings names like app/appname/name/APP_NAME etc.
|
88 | [More info in the source](https://github.com/simpleappcreator/simple-app/blob/master/lib/config.js)
|
89 |
|
90 | All these settings are in `app.config`
|
91 |
|
92 |
|
93 | ## Submodules
|
94 |
|
95 | It uses and makes available frequently used modules that you might need in your app.
|
96 |
|
97 | #### [Passport](https://github.com/jaredhanson/passport)
|
98 |
|
99 | Passport is available as `app.passport` and strategies as `app.passport.local/google/facebook`
|
100 |
|
101 | There's a wrapper to serialize/deserialize
|
102 |
|
103 | app.serializeUser(function(user, done){ done(null, user.id) });
|
104 | app.deserializeUser(function(id, done){ User.findById(id, done) });
|
105 |
|
106 | which handles errors and logs messages
|
107 |
|
108 | Serializing [user.user/name](54e8d8…cd1)
|
109 | POST [302] /login
|
110 | DeSerialized [user.user/name](54e8d8…cd1)
|
111 |
|
112 | And since `serializeUser` is the same in most cases, and doesn't require `User`, it's already pre-configured like that.
|
113 |
|
114 | Of course, you can still over-ride however you want, using either the wrappers or directly using `app.passport.de/serializeUser`
|
115 |
|
116 | ---
|
117 |
|
118 | There are also some helper middlewares
|
119 |
|
120 | `app.reqUser` which checks `if(req.user)` otherwise redirects to `/login`
|
121 |
|
122 | `app.reqAdmin` which checks `if(req.user.admin || req.user.group == 'admin')` or throws 401
|
123 |
|
124 | app.get('/secret', app.reqAdmin, function(req, res) {
|
125 | res.render('secret');
|
126 | });
|
127 |
|
128 | #### [Mongoose](https://github.com/Automattic/mongoose)
|
129 |
|
130 | Mongoose is available as `app.mongoose` which tries to connect to `mongodb://locahost/appname` by default, or if you configure a setting `mongodburl`
|
131 |
|
132 | It also tries to *guess* the URL if app is hosted on openshift or MONGOLAB etc.
|
133 |
|
134 | When defining databases in your app you should use
|
135 |
|
136 | var app = require('simple-app');
|
137 | var mongoose = app.mongoose;
|
138 | var User = mongoose.Schema({
|
139 | ...
|
140 |
|
141 | #### Mongo Session Store
|
142 |
|
143 | [Sessions](https://github.com/expressjs/session)
|
144 | are stored in the mongo database using
|
145 | [connect-mongo](https://github.com/kcbanner/connect-mongo).
|
146 |
|
147 |
|
148 | #### [Jade](https://github.com/jadejs/jade)
|
149 |
|
150 | Default view engine is set to Jade.
|
151 |
|
152 | As usual you can change to whatever `app.set('view engine', 'hbs')`
|
153 |
|
154 | #### [Jade-static](https://github.com/shovon/jade-static)
|
155 |
|
156 | Serves Jade files in `client` (or `public`) directory as HTMLs
|
157 |
|
158 | `/client/components/header-nav/header-nav.jade` `=>` `GET /components/header-nav/header-nav.html`
|
159 |
|
160 | Found it extremely useful in creating
|
161 | [AngularJS](http://angularjs.org/)
|
162 | [directive components](http://google.com/search?q=angular+directive+components)
|
163 | using [`templateUrl`](https://docs.angularjs.org/guide/directive#template-expanding-directive).
|
164 |
|
165 |
|
166 | #### [Stylus](https://github.com/learnboost/stylus)
|
167 |
|
168 | All `.styl` files (in `client`/`public`) are injected with [nib](https://github.com/tj/nib)
|
169 | and served as `.css` files.
|
170 |
|
171 |
|
172 | ## app.locals #todo
|
173 |
|
174 | res.locals #todo
|
175 |
|
176 |
|
177 | ## Development/Production mode #todo
|
178 |
|
179 | compress #todo
|
180 |
|
181 | no minificationin devel #todo
|
182 |
|
183 |
|
184 |
|
185 | ## Routes (revisited)
|
186 |
|
187 | The routes should be configured with `app.<verb>`. This is actually a wrapper for the original `app.<verb>` which would've been available if you were to configure Express manually. It's still available in `app._<verb>`. But the wrapper serves an important function.
|
188 |
|
189 | There are certain **default routes** and **middlewares**, like 404/500 error handler\*, and those should always be configured *after* ***your*** routes.
|
190 |
|
191 | Every time you add a route, it removes those previously added "default" routes and adds them back ***after*** *your* routes.
|
192 |
|
193 | \*The error handler serves the default view `error.jade` with the relevant error message.
|
194 |
|
195 | There's also a default `/` route which serves the default `index` view as seen in the screenshot above. If you configure your own `/` route, it is made to *precede* this default view as described above, effectively disabling it.
|
196 |
|
197 | Same could be done to disable the default error handlers if you wish to implement your own.
|
198 |
|
199 | #### middlewarres #todo
|
200 |
|
201 | Last page #todo
|
202 |
|
203 | Sitemap generator #todo
|
204 |
|
205 | catch404s #todo
|
206 |
|
207 | >First, check if there's a viewfile that exists with the corresponding req.path #todo
|
208 |
|
209 | catchErrors #todo
|
210 |
|
211 | >failed-lookup #todo
|
212 |
|
213 |
|
214 | #### routes #todo
|
215 |
|
216 | All can be removed `app.removeDefaultMiddlewares()` #todo
|
217 |
|
218 | #### views #todo
|
219 |
|
220 | Lot of commonly used views, like header/footer, error page, login/logout/register pages etc are included.
|
221 |
|
222 |
|
223 |
|
224 |
|
225 | ## Resources listing
|
226 |
|
227 | For convenience of including all the resources *programatically*, all the resources are enlisted in `app.config.resources`
|
228 |
|
229 | public: {
|
230 | js: ['jquery.js', 'angular.js', 'angular-animate.js', 'bootstrap.js', 'moment.js', ...
|
231 | fullpaths: ['C:\\TestApp\\node_modules\\simple-app\\lib\\public\\jquery.js', ... ]],
|
232 | min: 'public.min.js'
|
233 | css: ['bootstrap-theme.css', 'bootstrap.css' ...
|
234 | fullpaths: ['C:\\TestApp\\node_modules\\simple-app\\lib\\public\\bootstrap-theme.css', ...]],
|
235 | min: 'public.min.css'
|
236 | },
|
237 | client: {
|
238 | css: ['components/data/data.css', 'app.css' ...
|
239 | fullpaths: ['C:\\TestApp\\client\\components\\data\\data.css', ...]],
|
240 | min: 'client.min.css'
|
241 | js: ['components/data/data.js', 'app.js' ...
|
242 | fullpaths: ['C:\\TestApp\\client\\components\\data\\data.js' ...]]
|
243 | min: 'client.min.js'
|
244 | },
|
245 | angularApp: ['data', 'alertErr']
|
246 |
|
247 | `app.config.resources.public.js` would contain an array of *names* of all the JS files in `public` dir.
|
248 | `app.config.resources.public.js.fullpaths` would contain an array *full paths* of the same.
|
249 | `app.config.resources.public.js.min` would only be present if minification was done, and would contain just the string "public.min.css"
|
250 |
|
251 | Same everything goes for `app.config.resources.client`
|
252 |
|
253 | Note that `app.config.resources.public.js` is an Array and `app.config.resources.public.js.min` is a ***property*** which won't be enumerated when the array would be looped with `forEach`
|
254 |
|
255 | `app.config.resources.angularApp` contains the names of all the folders in the `client/components` dir that have a JS file.
|
256 |
|
257 | Useful for creating Angular directive components.
|
258 |
|
259 | client/components/header-nav
|
260 | header-nav.js
|
261 | header-nav.jade
|
262 |
|
263 | An Angular directive `header-nav` is available by default.
|
264 | This is what creates the top bar in the default view.
|
265 | You just include the tagname `header-nav` in your HTML and Angular injects this directive.
|
266 |
|
267 |
|
268 | ## Client-side (revisited)
|
269 |
|
270 | Lot of commonly needed client-side CSS and javascripts libraries are included.
|
271 | And this is where the resources listed in `app.config.resources` come in handy!
|
272 |
|
273 | Here's what the default (partial) header view that's included looks like:
|
274 |
|
275 | <!DOCTYPE html><html ng-app="app" ng-controller="app">
|
276 | <head>
|
277 | <div>Resources<div>public<div>CSS
|
278 | <link rel="stylesheet" href="/bootstrap-theme.css">
|
279 | <link rel="stylesheet" href="/bootstrap.css">
|
280 | </div><div>JS
|
281 | <script src="/jquery.js"></script>
|
282 | <script src="/angular.js"></script>
|
283 | </div></div><div>client<div>CSS
|
284 | <link rel="stylesheet" href="/misc.css">
|
285 | <link rel="stylesheet" href="/title.css">
|
286 | </div><div>JS
|
287 | <script src="/components/header-nav/header-nav.js"></script>
|
288 | <script src="/app.js"></script>
|
289 | </head><body>
|
290 | <header-nav></header-nav><main>
|
291 |
|
292 | Ignoring the bad practice of including all that in the `<head>`, what's to be noted here is that
|
293 | the Jade file `views/partials/header.jade` that generated it is included by default, but you'll probably use your own version of a header etc anyways, so the layout itself is not as important.
|
294 |
|
295 | What's more important is all those CSS and javascript libraries and other stuff is available on client-side without you having put anything in your app `public` or `client` folder. You can use them in your own layouts wherever you want.
|
296 |
|
297 | Furthermore, if you look at the actual jade file, you'll see that it includes all those script *programatically*.
|
298 | So that you don't have to change the file anytime you include more client-side files,
|
299 | restarting the app will automatically make them available as certain variables which can be looped through.
|
300 |
|
301 | div Resources
|
302 | each topdir in ['public', 'client']
|
303 | div= topdir
|
304 | div CSS
|
305 | if(dev && resources[topdir].css)
|
306 | each css in resources[topdir].css
|
307 | link(rel="stylesheet", href="/#{css}")
|
308 | else if(!dev && resources[topdir].css.min)
|
309 | link(rel="stylesheet", href="/#{resources[topdir].css.min}")
|
310 | div JS
|
311 | if(dev && resources[topdir].js)
|
312 | each js in resources[topdir].js
|
313 | script(src="/#{js}")
|
314 | else if(!dev && resources[topdir].js.min)
|
315 | script(src="/#{resources[topdir].js.min}")
|
316 |
|
317 | If this cup of tea tastes bad, you don't have to drink it. :) It's just an option.
|
318 |
|
319 |
|
320 |
|