Skip to content

Commit a9622da

Browse files
author
Alexandru Vladutu
committed
Made build script, updated README
1 parent 9f2d262 commit a9622da

22 files changed

+12104
-127
lines changed

Jakefile.js

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@
1212
* To run a task with params do:
1313
* jake db:populate[20]
1414
*/
15-
var mongoose = require('mongoose'),
16-
colors = require('colors'),
17-
faker = require('./vendor/faker'),
18-
log = console.log,
19-
ENV = process.env.NODE_ENV || 'development';
20-
JK = {};
15+
var mongoose = require('mongoose'),
16+
colors = require('colors'),
17+
faker = require('./vendor/faker'),
18+
assetBuilder = require('./lib/assetBuilder'),
19+
log = console.log,
20+
ENV = process.env.NODE_ENV || 'development';
21+
JK = {};
2122

2223
JK.abortIfProduction = function() {
2324
if (ENV === 'production') {
@@ -37,6 +38,18 @@ task('init', [], function() {
3738
}
3839
}, { async: true });
3940

41+
namespace('app', function() {
42+
43+
desc('Compress JS & CSS and make 1 JS && 1 CSS file. Run this before deploying to production.');
44+
task('assets', [], function(done) {
45+
assetBuilder(function() {
46+
log('- packed up JS & CSS files'.yellow);
47+
complete();
48+
});
49+
}, { async: true });
50+
51+
});
52+
4053
namespace('db', function() {
4154

4255
// desc('Connect to database');

README.md

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
11
## Quick start
22

33
- Make sure Node.js and NPM should be installed (I prefer to do it using NVM). This project was developed on Node 0.6.x.
4-
- Install dependencies with NPM: "npm install ." in the project root
4+
- Install project dependencies with NPM by running the following command in the terminal (project root):
5+
6+
npm install .
7+
58
- Configure the ports for the application (for multiple environments: dev, test, production) and also the settings for the MongoDB connection (you can either host MongoDB locally or try a free hosting provider such as MongoLab). The config data is in /config
6-
- Run 'npm start' or 'NODE_ENV=production node app.js' to start the server
9+
- Start the server:
10+
11+
a) Production
12+
13+
npm start
14+
15+
b) Development (note that if you want to load all the files uncompressed you should visit http://<server>:<port>/dev.html):
16+
17+
node app.js
18+
719

820
## App structure
921

@@ -23,20 +35,35 @@ Frontend:
2335
- '/css' and '/img' stores the static stylesheets and images needed
2436
- '/test' has the logic for the test runner (with Mocha), and specs
2537

26-
## Dev gotchas with Jake
38+
## Dev gotchas with Jake (in the terminal)
2739

28-
You can empty the database by running 'jake db:empty' and populate it with data by running 'jake db:populate[20]' for ex (that will empty db and insert 20 new records).
40+
Empty the database:
41+
42+
jake db:empty
43+
44+
Populate database with data:
45+
46+
jake db:populate[20]
47+
48+
That will empty db and insert 20 new records).
49+
50+
Compress & concatenate assets (one file for JS & one file for CSS):
51+
52+
jake app:assets
2953

3054
## Testing
3155

3256
I've chosen Mocha for all tests in this project. To run unit tests & function tests use 'npm test' in the application root (make sure things are setup properly -> the app can connect to MongoDB, can bind to the specified port).
33-
If you're testing on Windows, install Mocha globally: 'npm install [email protected] -g' and run 'mocha --ui bdd --recursive --reporter spec --timeout 10000 --slow 300' instead.
34-
For client side tests, open 'http://server:port/test'.
57+
If you're testing on Windows, run the following commands in the terminal:
58+
59+
npm install [email protected] -g
60+
mocha --ui bdd --recursive --reporter spec --timeout 10000 --slow 300
61+
62+
The first command installs mocha globally and the second one runs the test suite.
3563

36-
## Build
64+
For client side tests, open the browser
3765

38-
I've concatenated and minified the css into a single file and the JS into 2 files: one file that contains libraries (such as jQuery, underscore etc.. including RequireJS) and another file that includes all the RequireJS modules (minified and concatenated with r.js, the RequireJS optimizer).
39-
To see all the original files during development, use http://host:port/development.html.
66+
http://<server>:<port>/test
4067

4168
## Small JS styleguide for the project
4269

@@ -49,15 +76,13 @@ To see all the original files during development, use http://host:port/developme
4976

5077
## Browser compatibility
5178

52-
I haven't had time to properly test the app, but it should work fine in modern browsers.
79+
I haven't had time to properly test the app, but it *should* work fine in modern browsers.
5380

5481
## TODO / Improvements:
5582

5683
Client-side:
5784

58-
- Compress & concatenate JS & CSS (each into single file, using build script)
5985
- Add popups after deleting / saving client
60-
- Put each template into an element with an id, concatenate them (using a build script) into a single HTML file which is fetched at startup and export the object containing them (this way there's only 1 request instead of <number of templates> requests, they are kept out of the main html file and each into their own files during development).
6186
- More tests
6287

6388
Server-side:
@@ -66,7 +91,7 @@ Server-side:
6691
- Split contents of utils.js into multiple files (more specific categories)
6792
- Implement content-negotiation (return 406 Not Acceptable where needed)
6893
[this is present by default in Express 3.x, upgrade when it is stable enough]
69-
- Implement authentication and check authorization when modifying resources
94+
- Implement authentication and check authorization when modifying resources (OAuth maybe?)
7095
- Implement ETags properly for the /clients and /clients/:id GET routes
7196

7297
## Useful links that helped me while developing this app

app.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@ utils.loadConfig(__dirname + '/config', function(config) {
2222
app.use(gzippo.compress());
2323
});
2424
app.use(express.favicon());
25-
utils.ifEnv('production', function() {
26-
app.use(express.staticCache());
27-
});
2825
app.use(express['static'](__dirname + '/public'));
2926
app.use(express.bodyParser());
3027
app.use(express.methodOverride());

lib/assetBuilder.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
var async = require('async'),
2+
cssMin = require('./cssmin'),
3+
fs = require('fs'),
4+
requirejs = require('requirejs'),
5+
jsConfig, cssConfig, filePaths, actionsLeft, assetBuilder;
6+
7+
actionsLeft = 2;
8+
9+
jsConfig = {
10+
baseUrl : __dirname + '/../public/js',
11+
name : 'main',
12+
out : __dirname + '/../public/build/main-built.js',
13+
paths: {
14+
'text' : 'lib/text',
15+
'jquery' : 'lib/jquery',
16+
'underscore' : 'lib/underscore-amd',
17+
'backbone' : 'lib/backbone-amd',
18+
'bootstrap' : 'lib/bootstrap',
19+
'moment' : 'lib/moment',
20+
'ClientModel' : 'models/client',
21+
'ClientCollection' : 'collections/clients',
22+
'HomeView' : 'views/home',
23+
'HeaderView' : 'views/header',
24+
'ClientListView' : 'views/clients/index',
25+
'ClientEditView' : 'views/clients/edit',
26+
'ClientView' : 'views/clients/show'
27+
}
28+
};
29+
30+
// cssConfig a la RequireJS optimizer
31+
cssConfig = {
32+
baseUrl : '../public/css',
33+
files : ['bootstrap', 'style'],
34+
out : '../public/build/main-built.css'
35+
};
36+
37+
assetBuilder = function(callback) {
38+
requirejs.optimize(jsConfig, function (buildResponse) {
39+
// buildResponse is just a text output of the modules
40+
// included. Load the built file for the contents.
41+
// Use config.out to get the optimized file contents.
42+
// var contents = fs.readFileSync(jsConfig.out, 'utf8');
43+
// console.log(contents);
44+
if (!--actionsLeft) {
45+
callback();
46+
}
47+
});
48+
49+
// construct the file paths
50+
filePaths = [];
51+
cssConfig.files.forEach(function(file) {
52+
filePaths.push(__dirname + '/' + cssConfig.baseUrl + '/' + file + '.css');
53+
});
54+
55+
async.map(filePaths, function minimizeCss(item, callback) {
56+
fs.readFile(item, 'UTF-8', function(err, contents) {
57+
if (err) {
58+
callback(err, null);
59+
} else {
60+
// return minified contents
61+
callback(null, cssMin(contents));
62+
}
63+
});
64+
}, function writeToFile(err, results) {
65+
var filePath;
66+
67+
if (err) { throw err; }
68+
69+
filePath = __dirname + '/' + cssConfig.out;
70+
fs.writeFile(filePath, results.join('\n'), 'UTF-8', function(err) {
71+
if (err) { throw err; }
72+
73+
// execute callback only when both actions have finished
74+
if (!--actionsLeft) {
75+
callback();
76+
}
77+
});
78+
});
79+
};
80+
81+
module.exports = assetBuilder;

0 commit comments

Comments
 (0)