diff --git a/.gitignore b/.gitignore index 85eda7e..6fe25bb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ node_modules bower_components -tmp +.tmp .vagrant results/* coverage diff --git a/Gruntfile.js b/Gruntfile.js index 9fd6597..9bcaea3 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,5 +1,8 @@ module.exports = function(grunt) { + // Load all grunt modules + require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks); + // Tell our Express server that Grunt launched it process.env.GRUNTED = true; @@ -18,7 +21,7 @@ module.exports = function(grunt) { cssRouter: function (fontpath) { var pathArray = fontpath.split('/'); var fileName = pathArray[pathArray.length - 1]; - return '/front/fonts/' + fileName; + return '/fonts/' + fileName; } } }, @@ -69,19 +72,22 @@ module.exports = function(grunt) { }, clean: { tmp: { - src: ['tmp'] + src: ['.tmp'] }, dev: { src: ['front/src/css'] }, coverage: { - src: ['tmp', 'coverage/'] + src: ['.tmp', 'coverage/'] + }, + build: { + src: ['front/build'] } }, copy: { beforeCoverage: { files: [ - {src: ['bin/server.js'], dest: 'tmp/'} + {src: ['bin/server.js'], dest: '.tmp/'} ] }, coverage: { @@ -89,12 +95,18 @@ module.exports = function(grunt) { {src: ['test/**'], dest: 'coverage/'}, {src: ['lib/metadata/**'], dest: 'coverage/'} ] + }, + build: { + files: [ + {src: ['./front/src/fonts/icons.woff'], dest: './front/build/fonts/icons.woff'}, + {src: ['./front/src/img/favicon.png'], dest: './front/build/img/favicon.png'}, + ] } }, lineremover: { beforeCoverage: { files: { - 'tmp/bin/cli.js': 'bin/cli.js' + '.tmp/bin/cli.js': 'bin/cli.js' }, options: { exclusionPattern: /#!\/usr\/bin\/env node/ @@ -111,7 +123,7 @@ module.exports = function(grunt) { dest: 'coverage/lib/' }, coverageBin: { - src: ['tmp/bin/'], + src: ['.tmp/bin/'], dest: 'coverage/bin/' } }, @@ -137,6 +149,14 @@ module.exports = function(grunt) { src: ['coverage/test/core/*.js', 'coverage/test/api/*.js'] } }, + env: { + dev: { + NODE_ENV: 'development' + }, + builded: { + NODE_ENV: 'production' + } + }, express: { dev: { options: { @@ -146,6 +166,14 @@ module.exports = function(grunt) { showStack: true } }, + builded: { + options: { + port: 8383, + server: './bin/server.js', + serverreload: true, + showStack: true + } + }, test: { options: { port: 8387, @@ -159,6 +187,67 @@ module.exports = function(grunt) { bases: 'test/www' } } + }, + useminPrepare: { + html: './front/src/main.html', + options: { + dest: './front/build', + root: ['./', './front/src'] + } + }, + usemin: { + html: './front/build/main.html', + css: './front/build/css/*.css', + options: { + assetsDirs: ['front/build'], + patterns: { + css: [[/(\/fonts\/icons\.woff)/gm, 'Replacing reference to icons.woff']] + } + } + }, + htmlmin: { + options: { + removeComments: true, + collapseWhitespace: true + }, + main: { + files: [{ + expand: true, + cwd: './front/build/', + src: 'main.html', + flatten: true, + dest: './front/build' + }] + }, + views: { + files: [{ + expand: true, + cwd: './front/src/views', + src: '*.html', + flatten: true, + dest: '.tmp/views/' + }] + } + }, + inline_angular_templates: { + build: { + options: { + base: '.tmp', + method: 'append' + }, + files: { + './front/build/main.html': ['.tmp/views/*.html'] + } + } + }, + filerev: { + options: { + algorithm: 'md5', + length: 8 + }, + assets: { + src: './front/build/*/*.*' + } } }); @@ -191,10 +280,6 @@ module.exports = function(grunt) { }); - - - require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks); - grunt.registerTask('icons', [ 'font:icons', 'less', @@ -202,8 +287,20 @@ module.exports = function(grunt) { ]); grunt.registerTask('build', [ + 'clean:build', + 'copy:build', 'less', - 'replace' + 'useminPrepare', + 'concat', + 'uglify', + 'cssmin', + 'replace', + 'htmlmin:views', + 'inline_angular_templates', + 'filerev', + 'usemin', + 'htmlmin:main', + 'clean:tmp' ]); grunt.registerTask('hint', [ @@ -211,9 +308,15 @@ module.exports = function(grunt) { ]); grunt.registerTask('dev', [ + 'env:dev', 'express:dev' ]); + grunt.registerTask('builded', [ + 'env:builded', + 'express:builded' + ]); + grunt.registerTask('test', [ 'build', 'jshint', diff --git a/front/src/css/icons.css b/front/src/css/icons.css index 6ebf26b..ac51e0c 100644 --- a/front/src/css/icons.css +++ b/front/src/css/icons.css @@ -1,6 +1,6 @@ @font-face { font-family: "fontsmith-icons"; - src: url("/front/fonts/icons.woff") format("woff"); + src: url("/fonts/icons.woff") format("woff"); font-weight: normal; font-style: normal; } diff --git a/front/src/css/main.css b/front/src/css/main.css index 9ff35ad..8cab1bf 100644 --- a/front/src/css/main.css +++ b/front/src/css/main.css @@ -1,6 +1,6 @@ @font-face { font-family: "fontsmith-icons"; - src: url("/front/fonts/icons.woff") format("woff"); + src: url("/fonts/icons.woff") format("woff"); font-weight: normal; font-style: normal; } diff --git a/front/src/fonts/icons.woff b/front/src/fonts/icons.woff index 196e556..9611c2f 100644 Binary files a/front/src/fonts/icons.woff and b/front/src/fonts/icons.woff differ diff --git a/front/src/js/app.js b/front/src/js/app.js index 445c20c..a7f73d3 100644 --- a/front/src/js/app.js +++ b/front/src/js/app.js @@ -25,27 +25,27 @@ yltApp.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) { $routeProvider. when('/', { - templateUrl: 'front/views/index.html', + templateUrl: 'views/index.html', controller: 'IndexCtrl' }). when('/queue/:runId', { - templateUrl: 'front/views/queue.html', + templateUrl: 'views/queue.html', controller: 'QueueCtrl' }). when('/about', { - templateUrl: 'front/views/about.html', + templateUrl: 'views/about.html', controller: 'AboutCtrl' }). when('/result/:runId', { - templateUrl: 'front/views/dashboard.html', + templateUrl: 'views/dashboard.html', controller: 'DashboardCtrl' }). when('/result/:runId/timeline', { - templateUrl: 'front/views/timeline.html', + templateUrl: 'views/timeline.html', controller: 'TimelineCtrl' }). when('/result/:runId/rule/:policy', { - templateUrl: 'front/views/rule.html', + templateUrl: 'views/rule.html', controller: 'RuleCtrl' }). otherwise({ diff --git a/front/src/less/icons.less b/front/src/less/icons.less index f02dcbc..7603317 100644 --- a/front/src/less/icons.less +++ b/front/src/less/icons.less @@ -1,24 +1,24 @@ -@lab-font-family: "fontsmith-icons"; -@lab-value: "\e004"; -@lab: '"fontsmith-icons"' '"\\e004"'; -@list-font-family: "fontsmith-icons"; -@list-value: "\e003"; -@list: '"fontsmith-icons"' '"\\e003"'; -@loop-font-family: "fontsmith-icons"; -@loop-value: "\e002"; -@loop: '"fontsmith-icons"' '"\\e002"'; @warning-font-family: "fontsmith-icons"; @warning-value: "\e000"; @warning: '"fontsmith-icons"' '"\\e000"'; @question-font-family: "fontsmith-icons"; @question-value: "\e001"; @question: '"fontsmith-icons"' '"\\e001"'; +@lab-font-family: "fontsmith-icons"; +@lab-value: "\e004"; +@lab: '"fontsmith-icons"' '"\\e004"'; +@list-font-family: "fontsmith-icons"; +@list-value: "\e003"; +@list: '"fontsmith-icons"' '"\\e003"'; @bars-font-family: "fontsmith-icons"; @bars-value: "\e005"; @bars: '"fontsmith-icons"' '"\\e005"'; @arrow-left3-font-family: "fontsmith-icons"; @arrow-left3-value: "\e006"; @arrow-left3: '"fontsmith-icons"' '"\\e006"'; +@loop-font-family: "fontsmith-icons"; +@loop-value: "\e002"; +@loop: '"fontsmith-icons"' '"\\e002"'; .icon-font-family(@char) { font-family: ~`@{char}[0]`; @@ -49,7 +49,7 @@ @font-face { font-family: "fontsmith-icons"; - src:url("/front/fonts/icons.woff") format("woff"), + src:url("/fonts/icons.woff") format("woff"), ; font-weight: normal; font-style: normal; diff --git a/front/src/main.html b/front/src/main.html index 53ccfc5..508841a 100644 --- a/front/src/main.html +++ b/front/src/main.html @@ -3,30 +3,34 @@ Yellow Lab Tools - + - - - - - - - + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + @@ -38,13 +42,7 @@ \ No newline at end of file diff --git a/front/src/views/dashboard.html b/front/src/views/dashboard.html index 0fba7bc..e95421d 100644 --- a/front/src/views/dashboard.html +++ b/front/src/views/dashboard.html @@ -1,4 +1,4 @@ -
+
@@ -16,11 +16,8 @@
{{category.label}}
-
+
diff --git a/front/src/views/queue.html b/front/src/views/queue.html index 219d29f..c34d3b4 100644 --- a/front/src/views/queue.html +++ b/front/src/views/queue.html @@ -8,9 +8,7 @@
- +

(auto-refresh activated)

diff --git a/front/src/views/rule.html b/front/src/views/rule.html index 36b6cfc..ee540ce 100644 --- a/front/src/views/rule.html +++ b/front/src/views/rule.html @@ -1,4 +1,4 @@ -
+
@@ -19,10 +19,7 @@

- +

diff --git a/front/src/views/timeline.html b/front/src/views/timeline.html index de7894f..71210ab 100644 --- a/front/src/views/timeline.html +++ b/front/src/views/timeline.html @@ -1,4 +1,4 @@ -
+

Javascript Timeline

This graph gives a quick view of when the Javascript interactions with the DOM occur during the loading of the page.

@@ -9,14 +9,14 @@
@@ -70,14 +70,12 @@
Timestamp
-
+
{{$index + 1}}
{{node.data.type}}
@@ -90,10 +88,7 @@
-
diff --git a/lib/server/controllers/frontController.js b/lib/server/controllers/frontController.js index ebcf139..9a19a67 100644 --- a/lib/server/controllers/frontController.js +++ b/lib/server/controllers/frontController.js @@ -1,19 +1,26 @@ -var path = require('path'); -var express = require('express'); +var path = require('path'); +var express = require('express'); var FrontController = function(app) { 'use strict'; + + var cacheDuration = 365 * 24 * 60 * 60 * 1000; // One year + var assetsPath = (app.get('env') === 'development') ? '../../../front/src' : '../../../front/build'; var routes = ['/', '/about', '/result/:runId', '/result/:runId/timeline', '/result/:runId/rule/:policy', '/queue/:runId']; - routes.forEach(function(route) { app.get(route, function(req, res) { - res.sendFile(path.join(__dirname, '../../../front/src/main.html')); + res.setHeader('Cache-Control', 'public, max-age=20'); + res.sendFile(path.join(__dirname, assetsPath, 'main.html')); }); }); - app.use('/front', express.static(path.join(__dirname, '../../../front/src'))); - app.use('/bower_components', express.static(path.join(__dirname, '../../../bower_components'))); + app.use('/css', express.static(path.join(__dirname, assetsPath, 'css'), { maxAge: cacheDuration })); + app.use('/fonts', express.static(path.join(__dirname, assetsPath, 'fonts'), { maxAge: cacheDuration })); + app.use('/img', express.static(path.join(__dirname, assetsPath, 'img'), { maxAge: cacheDuration })); + app.use('/js', express.static(path.join(__dirname, assetsPath, 'js'), { maxAge: cacheDuration })); + app.use('/views', express.static(path.join(__dirname, assetsPath, 'views'), { maxAge: cacheDuration })); + app.use('/bower_components', express.static(path.join(__dirname, '../../../bower_components'), { maxAge: cacheDuration })); }; module.exports = FrontController; \ No newline at end of file diff --git a/package.json b/package.json index 39a277d..fa04850 100644 --- a/package.json +++ b/package.json @@ -26,14 +26,22 @@ "grunt": "^0.4.5", "grunt-blanket": "^0.0.8", "grunt-contrib-clean": "^0.6.0", + "grunt-contrib-concat": "^0.5.0", "grunt-contrib-copy": "^0.7.0", + "grunt-contrib-cssmin": "^0.11.0", + "grunt-contrib-htmlmin": "^0.3.0", "grunt-contrib-jshint": "^0.10.0", "grunt-contrib-less": "^0.12.0", + "grunt-contrib-uglify": "^0.7.0", + "grunt-env": "^0.4.2", "grunt-express": "^1.4.1", + "grunt-filerev": "^2.1.2", "grunt-fontsmith": "^0.9.1", + "grunt-inline-angular-templates": "^0.1.5", "grunt-line-remover": "^0.0.2", "grunt-mocha-test": "^0.12.4", "grunt-replace": "^0.8.0", + "grunt-usemin": "^3.0.0", "matchdep": "^0.3.0", "mocha": "^2.1.0", "phantomjs": "^1.9.13", diff --git a/server_config/server_install.sh b/server_config/server_install.sh index cbdecae..f63294e 100644 --- a/server_config/server_install.sh +++ b/server_config/server_install.sh @@ -21,7 +21,7 @@ sudo chown $USER /space cd /space git clone https://github.com/gmetais/YellowLabTools.git --branch master cd YellowLabTools -npm install --production +npm install bower install --config.interactive=false --allow-root # Front-end compilation @@ -31,4 +31,4 @@ grunt build # Start the server rm server_config/settings.json cp server_config/settings-prod.json server_config/settings.json -forever start -c "node --stack-size=65500" bin/server.js \ No newline at end of file +NODE_ENV=production forever start -c "node --stack-size=65500" bin/server.js \ No newline at end of file diff --git a/server_config/server_update.sh b/server_config/server_update.sh index a294ffb..0cf1ee3 100755 --- a/server_config/server_update.sh +++ b/server_config/server_update.sh @@ -12,9 +12,14 @@ git stash pop # In case something was added in package.json or bower.json rm -rf node_modules -npm install --production +npm install rm -rf bower_components bower install --config.interactive=false --allow-root +# Front-end compilation +rm -rf front/build +npm install -g grunt +grunt build + # Restart the server -forever start -c "node --stack-size=65500" server.js \ No newline at end of file +NODE_ENV=production forever start -c "node --stack-size=65500" bin/server.js \ No newline at end of file