Front-end build for perfs - #11

This commit is contained in:
Gaël Métais
2015-01-09 13:54:00 +01:00
parent 7c8ffec254
commit db39e79cf7
16 changed files with 209 additions and 101 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
node_modules
bower_components
tmp
.tmp
.vagrant
results/*
coverage
+114 -11
View File
@@ -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',
+1 -1
View File
@@ -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;
}
+1 -1
View File
@@ -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;
}
Binary file not shown.
+6 -6
View File
@@ -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({
+10 -10
View File
@@ -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;
+24 -26
View File
@@ -3,30 +3,34 @@
<meta charset="utf-8">
<title>Yellow Lab Tools</title>
<base href="/">
<link rel="icon" type="image/png" href="/public/img/favicon.png">
<link rel="icon" type="image/png" href="/img/favicon.png">
<link rel="stylesheet" type="text/css" href="/front/css/main.css">
<link rel="stylesheet" type="text/css" href="/front/css/index.css">
<link rel="stylesheet" type="text/css" href="/front/css/dashboard.css">
<link rel="stylesheet" type="text/css" href="/front/css/queue.css">
<link rel="stylesheet" type="text/css" href="/front/css/rule.css">
<link rel="stylesheet" type="text/css" href="/front/css/timeline.css">
<link rel="stylesheet" type="text/css" href="/front/css/about.css">
<!-- build:css /css/styles.css-->
<link rel="stylesheet" type="text/css" href="/css/main.css">
<link rel="stylesheet" type="text/css" href="/css/index.css">
<link rel="stylesheet" type="text/css" href="/css/dashboard.css">
<link rel="stylesheet" type="text/css" href="/css/queue.css">
<link rel="stylesheet" type="text/css" href="/css/rule.css">
<link rel="stylesheet" type="text/css" href="/css/timeline.css">
<link rel="stylesheet" type="text/css" href="/css/about.css">
<!-- endbuild -->
<!-- build:js /js/all.js -->
<script src="/bower_components/angular/angular.min.js"></script>
<script src="/bower_components/angular-route/angular-route.min.js"></script>
<script src="/bower_components/angular-resource/angular-resource.min.js"></script>
<script src="/front/js/app.js"></script>
<script src="/front/js/controllers/indexCtrl.js"></script>
<script src="/front/js/controllers/aboutCtrl.js"></script>
<script src="/front/js/controllers/dashboardCtrl.js"></script>
<script src="/front/js/controllers/queueCtrl.js"></script>
<script src="/front/js/controllers/ruleCtrl.js"></script>
<script src="/front/js/controllers/timelineCtrl.js"></script>
<script src="/front/js/models/resultsFactory.js"></script>
<script src="/front/js/models/runsFactory.js"></script>
<script src="/front/js/services/menuService.js"></script>
<script src="/front/js/directives/gradeDirective.js"></script>
<script src="/js/app.js"></script>
<script src="/js/controllers/indexCtrl.js"></script>
<script src="/js/controllers/aboutCtrl.js"></script>
<script src="/js/controllers/dashboardCtrl.js"></script>
<script src="/js/controllers/queueCtrl.js"></script>
<script src="/js/controllers/ruleCtrl.js"></script>
<script src="/js/controllers/timelineCtrl.js"></script>
<script src="/js/models/resultsFactory.js"></script>
<script src="/js/models/runsFactory.js"></script>
<script src="/js/services/menuService.js"></script>
<script src="/js/directives/gradeDirective.js"></script>
<!-- endbuild -->
<head>
<body ng-app="YellowLabTools">
@@ -38,13 +42,7 @@
</div>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
if ('@@googleAnalyticsId'.indexOf('UA-') === 0) {
ga('create', '@@googleAnalyticsId', 'auto');
}
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)})(window,document,'script','//www.google-analytics.com/analytics.js','ga');if('@@googleAnalyticsId'.indexOf('UA-')===0){ga('create','@@googleAnalyticsId','auto');}
</script>
</body>
</html>
+3 -6
View File
@@ -1,4 +1,4 @@
<div ng-include="'/front/views/resultSubHeader.html'"></div>
<div ng-include="'views/resultSubHeader.html'"></div>
<div class="summary board">
<div class="globalScore" ng-if="globalScore === 0 || globalScore > 0">
@@ -16,11 +16,8 @@
<div class="category">{{category.label}}</div>
<div class="criteria">
<div class="table" title="Click to see details">
<div ng-repeat="ruleName in category.rules"
ng-if="result.rules[ruleName]"
ng-init="rule = result.rules[ruleName]"
ng-class="{'warning': rule.abnormal}"
ng-click="showRulePage(ruleName)">
<div ng-repeat="ruleName in category.rules" ng-if="result.rules[ruleName]" ng-init="rule = result.rules[ruleName]"
ng-class="{'warning': rule.abnormal}" ng-click="showRulePage(ruleName)">
<div class="grade">
<grade score="rule.score"></grade>
</div>
+1 -3
View File
@@ -8,9 +8,7 @@
</div>
<div ng-if="status.statusCode == 'awaiting'">
<div class="status">
<ng-pluralize count="status.position" when="{
'one': 'Waiting behind 1 other test',
'other': 'Waiting behind {} other tests'}">
<ng-pluralize count="status.position" when="{'one': 'Waiting behind 1 other test', 'other': 'Waiting behind {} other tests'}">
</ng-pluralize>
</div>
<p class="statusSubMessage">(auto-refresh activated)</p>
+2 -5
View File
@@ -1,4 +1,4 @@
<div ng-include="'/front/views/resultSubHeader.html'"></div>
<div ng-include="'views/resultSubHeader.html'"></div>
<div class="rule board">
<div class="backToDashboard"><a href="#" ng-click="backToDashboard()">Back to dashboard</a></div>
@@ -19,10 +19,7 @@
</div>
<div class="offenders">
<h3>
<ng-pluralize count="rule.offenders.length || 0"
when="{'0': 'No offenders',
'one': '1 offender',
'other': '{} offenders'}">
<ng-pluralize count="rule.offenders.length || 0" when="{'0': 'No offenders', 'one': '1 offender', 'other': '{} offenders'}">
</ng-pluralize>
</h3>
<div class="offendersTable">
+16 -21
View File
@@ -1,4 +1,4 @@
<div ng-include="'/front/views/resultSubHeader.html'"></div>
<div ng-include="'views/resultSubHeader.html'"></div>
<div class="execution board">
<h2>Javascript Timeline</h2>
<p>This graph gives a quick view of when the Javascript interactions with the DOM occur during the loading of the page.</p>
@@ -9,14 +9,14 @@
<div ng-repeat="duration in timeline track by $index"
class="interval"
ng-class="{
domCreation: $index * timelineIntervalDuration < result.toolsResults.phantomas.metrics.domInteractive,
domInteractive: $index * timelineIntervalDuration >= result.toolsResults.phantomas.metrics.domInteractive
&& $index * timelineIntervalDuration < result.toolsResults.phantomas.metrics.domContentLoaded,
domContentLoaded: $index * timelineIntervalDuration >= result.toolsResults.phantomas.metrics.domContentLoaded
&& $index * timelineIntervalDuration < result.toolsResults.phantomas.metrics.domContentLoadedEnd,
domContentLoadedEnd: $index * timelineIntervalDuration >= result.toolsResults.phantomas.metrics.domContentLoadedEnd
&& $index * timelineIntervalDuration < result.toolsResults.phantomas.metrics.domComplete,
domComplete: $index * timelineIntervalDuration >= result.toolsResults.phantomas.metrics.domComplete
domCreation: $index * timelineIntervalDuration < result.toolsResults.phantomas.metrics.domInteractive,
domInteractive: $index * timelineIntervalDuration >= result.toolsResults.phantomas.metrics.domInteractive
&& $index * timelineIntervalDuration < result.toolsResults.phantomas.metrics.domContentLoaded,
domContentLoaded: $index * timelineIntervalDuration >= result.toolsResults.phantomas.metrics.domContentLoaded
&& $index * timelineIntervalDuration < result.toolsResults.phantomas.metrics.domContentLoadedEnd,
domContentLoadedEnd: $index * timelineIntervalDuration >= result.toolsResults.phantomas.metrics.domContentLoadedEnd
&& $index * timelineIntervalDuration < result.toolsResults.phantomas.metrics.domComplete,
domComplete: $index * timelineIntervalDuration >= result.toolsResults.phantomas.metrics.domComplete
}">
<div style="height: {{100 * duration / timelineMax | number: 0}}px" class="color"></div>
<div class="tooltip detailsOverlay">
@@ -70,14 +70,12 @@
<div><!-- details --></div>
<div>Timestamp</div>
</div>
<div ng-repeat="node in profilerData"
ng-if="(!warningsFilterOn || node.warning || node.error)
&& (!textFilterOn || !textFilter.length || node.searchIndex.indexOf(textFilter) >= 0)"
ng-class="{
showingDetails: node.showDetails,
jsError: node.error,
windowPerformance: node.windowPerformance
}">
<div ng-if="(!warningsFilterOn || node.warning || node.error) && (!textFilterOn || !textFilter.length || node.searchIndex.indexOf(textFilter) >= 0)"
ng-repeat="node in profilerData" ng-class="{
showingDetails: node.showDetails,
jsError: node.error,
windowPerformance: node.windowPerformance
}">
<div class="index">{{$index + 1}}</div>
<div class="type">{{node.data.type}}</div>
@@ -90,10 +88,7 @@
</div>
<div class="details">
<div ng-class="{
'icon-question': !node.warning && !node.error,
'icon-warning': node.warning || node.error
}"
<div ng-class="{'icon-question': !node.warning && !node.error, 'icon-warning': node.warning || node.error}"
ng-click="onNodeDetailsClick(node)"
ng-if="node.data.type != 'jQuery loaded' && node.data.type != 'jQuery version change' && !node.windowPerformance"></div>
+13 -6
View File
@@ -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;
+8
View File
@@ -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",
+2 -2
View File
@@ -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
NODE_ENV=production forever start -c "node --stack-size=65500" bin/server.js
+7 -2
View File
@@ -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
NODE_ENV=production forever start -c "node --stack-size=65500" bin/server.js