* webpack poc, this is not going to work for plugins, dam

* tech: webpack and systemjs for plugins starting to work

* tech: webpack and systemjs combo starting to work

* tech: webpack + karma tests progress

* tech: webpack + karma progress

* tech: working on tests

* tech: webpack

* tech: webpack + karma, all tests pass

* tech: webpack + karma, all tests pass

* tech: webpack all tests pass

* webpack: getting closer

* tech: webpack progress

* webpack: further build refinements

* webpack: ng annotate fixes

* webpack: optimized build fix

* tech: minor fix for elasticsearch

* tech: webpack + ace editor

* tech: restored lodash move mixin compatability

* tech: added enzyme react test and upgraded to react v16

* tech: package version fix

* tech: added testdata to built in bundle

* webpack: sass progress

* tech: prod & dev build is working for the sass

* tech: clean up unused grunt stuff and moved to scripts folder

* tech: added vendor and manifest chunks, updated readme and docs

* tech: webpack finishing touches
This commit is contained in:
Torkel Ödegaard
2017-10-01 20:02:25 +02:00
committed by GitHub
parent f6cc741a6d
commit 0c86241c5b
139 changed files with 6186 additions and 15146 deletions

View File

@@ -1,77 +0,0 @@
var path = require('path');
module.exports = function(grunt) {
"use strict";
// Concat and Minify the src directory into dist
grunt.registerTask('build', [
'jshint:source',
'jshint:tests',
'jscs',
'clean:release',
'copy:node_modules',
'copy:public_to_gen',
'exec:tslint',
'exec:tscompile',
'karma:test',
'phantomjs',
'css',
'htmlmin:build',
'ngtemplates',
'cssmin:build',
'ngAnnotate:build',
'systemjs:build',
'concat:js',
'filerev',
'remapFilerev',
'usemin',
'uglify:genDir'
]);
// task to add [[.AppSubUrl]] to reved path
grunt.registerTask('remapFilerev', function() {
var root = grunt.config().genDir;
var summary = grunt.filerev.summary;
var fixed = {};
for(var key in summary){
if(summary.hasOwnProperty(key)){
var orig = key.replace(root, root+'/[[.AppSubUrl]]/public');
var revved = summary[key].replace(root, root+'/[[.AppSubUrl]]/public');
fixed[orig] = revved;
}
}
grunt.filerev.summary = fixed;
});
grunt.registerTask('build-post-process', function() {
grunt.config('copy.public_gen_to_temp', {
expand: true,
cwd: '<%= genDir %>',
src: '**/*',
dest: '<%= tempDir %>/public/',
});
grunt.config('copy.backend_bin', {
cwd: 'bin',
expand: true,
src: ['*'],
options: { mode: true},
dest: '<%= tempDir %>/bin/'
});
grunt.config('copy.backend_files', {
expand: true,
src: ['conf/*', 'vendor/phantomjs/*', 'scripts/*'],
options: { mode: true},
dest: '<%= tempDir %>'
});
grunt.task.run('copy:public_gen_to_temp');
grunt.task.run('copy:backend_bin');
grunt.task.run('copy:backend_files');
grunt.task.run('clean:packaging');
grunt.file.write(path.join(grunt.config('tempDir'), 'VERSION'), grunt.config('pkg.version'));
});
};

View File

@@ -1,43 +0,0 @@
// Lint and build CSS
module.exports = function(grunt) {
'use strict';
grunt.registerTask('css', [
'sass',
'concat:cssDark',
'concat:cssLight',
'concat:cssFonts',
'styleguide',
'sasslint',
'postcss',
]
);
grunt.registerTask('default', [
'clean:gen',
'jscs',
'jshint',
'copy:node_modules',
'copy:public_to_gen',
'exec:tslint',
'phantomjs',
'css',
'exec:tscompile'
]);
grunt.registerTask('test', ['default', 'karma:test', 'no-only-tests']);
grunt.registerTask('no-only-tests', function() {
var files = grunt.file.expand('public/**/*_specs\.ts', 'public/**/*_specs\.js');
files.forEach(function(spec) {
var rows = grunt.file.read(spec).split('\n');
rows.forEach(function(row) {
if (row.indexOf('.only(') > 0) {
grunt.log.errorlns(row);
grunt.fail.warn('found only statement in test: ' + spec)
}
});
});
});
};

View File

@@ -1,7 +0,0 @@
module.exports = function(grunt) {
"use strict";
// build, then zip and upload to s3
grunt.registerTask('release', ['build', 'build-post-process','compress:release']);
};

View File

@@ -1,17 +0,0 @@
module.exports = function(config) {
'use strict';
return {
release: ['<%= destDir %>', '<%= tempDir %>', '<%= genDir %>'],
gen: ['<%= genDir %>'],
temp: ['<%= tempDir %>'],
css: ['<%= genDir %>/css'],
packaging: [
'<%= tempDir %>/public/vendor/npm/rxjs',
'<%= tempDir %>/public/vendor/npm/tether',
'<%= tempDir %>/public/vendor/npm/tether-drop',
'<%= tempDir %>/public/**/*.map',
'<%= tempDir %>/public/**/*.ts',
],
};
};

View File

@@ -1,30 +0,0 @@
module.exports = function(config) {
'use strict';
var task = {
release: {
options: {
archive: '<%= destDir %>/<%= pkg.name %>-<%= pkg.version %>.<%= platform %>-<%= arch %>.tar.gz'
},
files : [
{
expand: true,
cwd: '<%= tempDir %>',
src: ['**/*'],
dest: '<%= pkg.name %>-<%= pkg.version %>/',
},
{
expand: true,
src: ['LICENSE.md', 'README.md', 'NOTICE.md'],
dest: '<%= pkg.name %>-<%= pkg.version %>/',
}
]
}
};
if (config.platform === 'windows') {
task.release.options.archive = '<%= destDir %>/<%= pkg.name %>-<%= pkg.version %>.<%= platform %>-<%= arch %>.zip';
}
return task;
};

View File

@@ -1,50 +0,0 @@
module.exports = function(config) {
"use strict";
return {
cssDark: {
src: [
'<%= genDir %>/vendor/css/timepicker.css',
'<%= genDir %>/vendor/css/spectrum.css',
'<%= genDir %>/css/grafana.dark.css',
'<%= genDir %>/vendor/css/font-awesome.min.css'
],
dest: '<%= genDir %>/css/grafana.dark.min.css'
},
cssLight: {
src: [
'<%= genDir %>/vendor/css/timepicker.css',
'<%= genDir %>/vendor/css/spectrum.css',
'<%= genDir %>/css/grafana.light.css',
'<%= genDir %>/vendor/css/font-awesome.min.css'
],
dest: '<%= genDir %>/css/grafana.light.min.css'
},
cssFonts: {
src: [ '<%= genDir %>/css/fonts.css' ],
dest: '<%= genDir %>/css/fonts.min.css'
},
js: {
src: [
'<%= genDir %>/vendor/npm/es6-shim/es6-shim.js',
'<%= genDir %>/vendor/npm/es6-promise/dist/es6-promise.js',
'<%= genDir %>/vendor/npm/systemjs/dist/system-polyfills.js',
'<%= genDir %>/vendor/npm/systemjs/dist/system.js',
'<%= genDir %>/app/system.conf.js',
'<%= genDir %>/app/boot.js',
],
dest: '<%= genDir %>/app/boot.js'
},
bundle_and_boot: {
src: [
'<%= genDir %>/app/app_bundle.js',
'<%= genDir %>/app/boot.js',
],
dest: '<%= genDir %>/app/boot.js'
},
};
};

View File

@@ -1,20 +0,0 @@
module.exports = function(config) {
return {
dev: {
options: {
port: 5601,
hostname: '*',
base: config.srcDir,
keepalive: true
}
},
dist: {
options: {
port: 5605,
hostname: '*',
base: config.destDir,
keepalive: true
}
},
}
};

View File

@@ -1,56 +0,0 @@
module.exports = function(config) {
return {
// copy source to temp, we will minify in place for the dist build
everything_but_less_to_temp: {
cwd: '<%= srcDir %>',
expand: true,
src: ['**/*', '!**/*.less'],
dest: '<%= tempDir %>'
},
public_to_gen: {
cwd: '<%= srcDir %>',
expand: true,
src: ['**/*', '!**/*.less'],
dest: '<%= genDir %>'
},
node_modules: {
cwd: './node_modules',
expand: true,
src: [
'angular/angular.js',
'angular-mocks/angular-mocks.js',
'angular-route/angular-route.js',
'angular-sanitize/angular-sanitize.js',
'jquery/dist/jquery.js',
'lodash/lodash.js',
'ace-builds/src-noconflict/ace.js',
'ace-builds/src-noconflict/ext-language_tools.js',
'eventemitter3/*.js',
'systemjs/dist/*.js',
'es6-promise/**/*',
'es6-shim/*.js',
'reflect-metadata/*.js',
'reflect-metadata/*.ts',
'reflect-metadata/*.d.ts',
'rxjs/**/*',
'tether/**/*',
'tether-drop/**/*',
'tether-drop/**/*',
'remarkable/dist/*',
'remarkable/dist/*',
'virtual-scroll/**/*',
'mousetrap/**/*',
'react/dist/*.js',
'react-dom/dist/*.js',
'ngreact/ngReact.js',
'angular-bindonce/bindonce.js',
'angular-native-dragdrop/draganddrop.js',
'clipboard/dist/clipboard.js',
],
dest: '<%= srcDir %>/vendor/npm'
}
};
};

View File

@@ -1,13 +0,0 @@
module.exports = function(config) {
return {
options: {
restructuring: false,
},
build: {
expand: true,
cwd: '<%= genDir %>',
src: ['css/*.css', 'vendor/css/*.css'],
dest: '<%= genDir %>'
}
};
};

View File

@@ -1,9 +0,0 @@
module.exports = function(config, grunt) {
'use strict'
return {
tslint : "node ./node_modules/tslint/lib/tslint-cli.js -c tslint.json --project ./tsconfig.json --type-check",
tslintfile : "node ./node_modules/tslint/lib/tslint-cli.js -c tslint.json --project ./tsconfig.json --type-check <%= tslint.source.files.src %>",
tscompile: "node ./node_modules/typescript/lib/tsc.js -p tsconfig.json --diagnostics",
tswatch: "node ./node_modules/typescript/lib/tsc.js -p tsconfig.json --diagnostics --watch",
};
};

View File

@@ -1,21 +0,0 @@
module.exports = function(config) {
return {
options: {
encoding: 'utf8',
algorithm: 'md5',
length: 8,
},
cssDark: {
src: '<%= genDir %>/css/grafana.dark.min.css',
dest: '<%= genDir %>/css'
},
cssLight: {
src: '<%= genDir %>/css/grafana.light.min.css',
dest: '<%= genDir %>/css'
},
js: {
src: '<%= genDir %>/app/boot.js',
dest: '<%= genDir %>/app'
}
};
};

View File

@@ -1,16 +0,0 @@
module.exports = function(config) {
return {
build: {
options:{
removeComments: true,
collapseWhitespace: true
},
expand: true,
cwd: '<%= genDir %>',
src: [
'app/**/*.html',
],
dest: '<%= genDir %>'
}
};
};

View File

@@ -1,22 +0,0 @@
module.exports = function(config) {
return {
src: [
'Gruntfile.js',
'<%= srcDir %>/app/**/*.js',
'<%= srcDir %>/plugin/**/*.js',
'!<%= srcDir %>/app/dashboards/*'
],
options: {
config: ".jscs.json",
},
};
};
/*
"requireCurlyBraces": ["if", "else", "for", "while", "do", "try", "catch"],
"requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch"],
"disallowLeftStickedOperators": ["?", "+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<="],
"disallowRightStickedOperators": ["?", "+", "/", "*", ":", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<="],
"requireRightStickedOperators": ["!"],
"requireLeftStickedOperators": [","],
*/

View File

@@ -1,25 +0,0 @@
module.exports = function(config) {
return {
source: {
files: {
src: ['Gruntfile.js', '<%= srcDir %>/app/**/*.js'],
}
},
tests: {
files: {
src: ['<%= srcDir %>/test/**/*.js'],
}
},
options: {
jshintrc: true,
reporter: require('jshint-stylish'),
ignores: [
'node_modules/*',
'dist/*',
'sample/*',
'<%= srcDir %>/vendor/*',
'<%= srcDir %>/app/dashboards/*'
]
}
};
};

View File

@@ -1,20 +0,0 @@
module.exports = function(config) {
'use strict';
return {
dev: {
configFile: 'karma.conf.js',
singleRun: false,
},
debug: {
configFile: 'karma.conf.js',
singleRun: false,
browsers: ['Chrome']
},
test: {
configFile: 'karma.conf.js',
}
};
};

View File

@@ -1,16 +0,0 @@
module.exports = function(config) {
return {
src:{
options: {
paths: ["<%= srcDir %>/less"],
yuicompress: true
},
files: {
"<%= genDir %>/css/bootstrap.dark.min.css": "<%= srcDir %>/less/grafana.dark.less",
"<%= genDir %>/css/bootstrap.light.min.css": "<%= srcDir %>/less/grafana.light.less",
"<%= genDir %>/css/bootstrap-responsive.min.css": "<%= srcDir %>/less/grafana-responsive.less"
}
}
};
};

View File

@@ -1,9 +0,0 @@
module.exports = function(config) {
return {
banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
'<%= grunt.template.today("yyyy-mm-dd") %>\n' +
'<%= pkg.homepage ? " * " + pkg.homepage + "\\n" : "" %>' +
' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
' Licensed <%= pkg.license %> */\n\n'
};
};

View File

@@ -1,12 +0,0 @@
module.exports = function(config) {
return {
build: {
expand: true,
cwd:'<%= genDir %>',
src: [
'app/**/*.js',
],
dest: '<%= genDir %>'
}
};
};

View File

@@ -1,19 +0,0 @@
module.exports = function(config) {
return {
grafana: {
cwd: '<%= genDir %>',
src: ['app/**/*.html'],
dest: '<%= genDir %>/app/core/partials.js',
options: {
prefix: 'public/',
bootstrap: function(module, script) {
return "define('app/core/partials', ['app/core/core_module'], function(coreModule) { \n" +
"coreModule.default.run(['$templateCache', function($templateCache) { \n" +
script +
'\n}]);' +
'\n});';
}
}
}
};
};

View File

@@ -1,37 +0,0 @@
module.exports = function(config,grunt) {
'use strict';
grunt.registerTask('phantomjs', 'Copy phantomjs binary to vendor/', function() {
var dest = './vendor/phantomjs/phantomjs';
var confDir = './node_modules/phantomjs-prebuilt/lib/';
if (process.platform === "win32") {
dest += ".exe";
}
src = config.phjs
if (!src){
var m=grunt.file.read(confDir+"location.js")
var src=/= \"([^\"]*)\"/.exec(m)[1];
if (!grunt.file.isPathAbsolute(src)) {
src = confDir+src;
}
}
try {
grunt.config('copy.phantom_bin', {
src: src,
dest: dest,
options: { mode: true},
});
grunt.task.run('copy:phantom_bin');
} catch (err) {
grunt.verbose.writeln(err);
grunt.fail.warn('No working Phantomjs binary available')
}
});
};

View File

@@ -1,21 +0,0 @@
module.exports = function(config) {
return {
options: {
map: true, // inline sourcemaps
// or
map: {
inline: false, // save all sourcemaps as separate files...
annotation: '<%= genDir %>/css' // ...to the specified directory
},
processors: [
require('autoprefixer')({browsers: 'last 3 versions'}), // add vendor prefixes
]
},
dist: {
src: '<%= genDir %>/css/*.css'
}
}
};

View File

@@ -1,76 +0,0 @@
module.exports = function(config,grunt) {
'use strict';
function buildRequireJsOptions() {
var options = {
appDir: '<%= genDir %>',
dir: '<%= tempDir %>',
mainConfigFile: '<%= genDir %>/app/require_config.js',
baseUrl: './',
waitSeconds: 0,
modules: [], // populated below,
optimize: 'none',
optimizeCss: 'none',
optimizeAllPluginResources: false,
removeCombined: true,
findNestedDependencies: true,
normalizeDirDefines: 'all',
inlineText: true,
skipPragmas: true,
done: function (done, output) {
var duplicates = require('rjs-build-analysis').duplicates(output);
if (duplicates.length > 0) {
grunt.log.subhead('Duplicates found in requirejs build:');
grunt.log.warn(duplicates);
done(new Error('r.js built duplicate modules, please check the excludes option.'));
}
done();
}
};
// setup the modules require will build
var requireModules = options.modules = [
{
// main/common module
name: 'app/app',
include: [
'text',
'jquery',
'bootstrap',
'modernizr',
'timepicker',
'datepicker',
'jquery.flot',
'angular-strap',
'angular-dragdrop',
'app/core/core',
'app/features/all',
// bundle the datasources
'app/plugins/datasource/grafana/datasource',
'app/plugins/datasource/graphite/datasource',
'app/plugins/datasource/elasticsearch/datasource',
'app/plugins/datasource/influxdb/datasource',
]
},
];
var fs = require('fs');
var panelPath = config.srcDir + '/app/plugins/panel';
// create a module for each directory in public/app/panel/
fs.readdirSync(panelPath).forEach(function (panelName) {
requireModules[0].include.push('app/plugins/panel/'+panelName+'/module');
});
return { options: options };
}
return { build: buildRequireJsOptions() };
};

View File

@@ -1,13 +0,0 @@
module.exports = function(config) {
return {
src:{
options: {},
files: {
"<%= genDir %>/css/grafana.dark.css": "<%= srcDir %>/sass/grafana.dark.scss",
"<%= genDir %>/css/grafana.light.css": "<%= srcDir %>/sass/grafana.light.scss",
"<%= genDir %>/css/fonts.css": "<%= srcDir %>/sass/fonts.scss",
}
}
};
};

View File

@@ -1,12 +0,0 @@
module.exports = function(config) {
'use strict';
return {
options: {
configFile: 'public/sass/.sass-lint.yml',
},
target: [
'public/sass/*.scss',
'public/sass/components/*.scss',
]
};
};

View File

@@ -1,11 +0,0 @@
module.exports = function(config, grunt) {
'use strict'
// dummy to avoid template compile error
return {
source: {
files: {
src: ""
}
}
};
};

View File

@@ -1,16 +0,0 @@
module.exports = function(config) {
return {
genDir: {
expand: true,
src: ['**/*.js', '!dashboards/*.js', '!vendor/**/*.js'],
dest: '<%= genDir %>',
cwd: '<%= genDir %>',
options: {
quite: true,
compress: {},
preserveComments: false,
banner: '<%= meta.banner %>'
}
}
};
};

View File

@@ -1,30 +0,0 @@
module.exports = function() {
'use strict';
return {
html: [
'<%= genDir %>/views/index.html',
'<%= genDir %>/views/500.html',
],
options: {
assetsDirs: ['<%= genDir %>'],
patterns: {
css: [
[/(\.css)/, 'Replacing reference to image.png']
]
}
// blockReplacements: {
// css: function (block) {
// console.log('aaaaaaaaaaaaa', block);
// return '<link rel="stylesheet" href="aaaa' + block.dest + '">';
// }
// }
// css: [
// [/(grafana\.light\.min\.css)/, 'Replacing reference to light css', function(asd) {
// console.log("Match", asd);
// return 'css/grafana.light.min.css';
// }]
// ]
}
};
};

View File

@@ -1,86 +0,0 @@
module.exports = function(config, grunt) {
'use strict';
var gaze = require('gaze');
var path = require('path');
var firstRun = true;
var done;
var lastTime;
grunt.registerTask('watch', function() {
if (!grunt.option('skip-ts-compile')) {
grunt.log.writeln('We recommoned starting with: grunt watch --force --skip-ts-compile')
grunt.log.writeln('Then do incremental typescript builds with: grunt exec:tswatch')
}
done = this.async();
lastTime = new Date().getTime();
if (firstRun === false) {
grunt.log.writeln('Watch resuming');
return;
}
gaze([
config.srcDir + '/app/**/*',
config.srcDir + '/test/**/*',
config.srcDir + '/sass/**/*',
], function(err, watcher) {
console.log('Gaze watchers setup');
watcher.on('all', function(evtName, filepath) {
filepath = path.relative(process.cwd(), filepath);
// ignore multiple changes at once
var now = new Date().getTime();
if (now - lastTime < 100) {
return;
}
lastTime = now;
var newPath;
grunt.log.writeln('File Changed: ', filepath);
if (/(\.html)|(\.json)$/.test(filepath)) {
newPath = filepath.replace(/^public/, 'public_gen');
grunt.log.writeln('Copying to ' + newPath);
grunt.file.copy(filepath, newPath);
}
if (/(\.js)$/.test(filepath)) {
newPath = filepath.replace(/^public/, 'public_gen');
grunt.log.writeln('Copying to ' + newPath);
grunt.file.copy(filepath, newPath);
grunt.task.run('jshint');
grunt.task.run('jscs');
}
if (/(\.scss)$/.test(filepath)) {
grunt.task.run('clean:css');
grunt.task.run('css');
}
if (/(\.ts)$/.test(filepath)) {
newPath = filepath.replace(/^public/, 'public_gen');
grunt.log.writeln('Copying to ' + newPath);
grunt.file.copy(filepath, newPath);
if (grunt.option('skip-ts-compile')) {
grunt.log.writeln('Skipping ts compile, run grunt exec:tswatch to start typescript watcher')
} else {
grunt.task.run('exec:tscompile');
}
grunt.config('tslint.source.files.src', filepath);
grunt.task.run('exec:tslintfile');
}
done();
firstRun = false;
grunt.task.run('watch');
});
});
});
};

View File

@@ -1,3 +0,0 @@
module.exports = function(grunt) {
grunt.registerTask('server', ['connect:dev']);
};

View File

@@ -1,47 +0,0 @@
module.exports = function(grunt) {
"use strict";
function escapeRegExp(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}
function extractColour(line) {
var regex = /\s*:\s*(#[a-fA-F0-9]{3,6})\s*(!default|!default;)?/;
var matches = line.match(regex);
return matches ? matches[1] : matches;
}
function extractVariable(line) {
var matches = line.match(/(\$[0-9a-zA-Z_-]+)\s*(!default|!default;)?/)
return matches ? matches[1] : matches
}
function readVars(file, obj) {
var content = grunt.file.read(file);
var lines = content.split('\n');
lines.forEach(function(line) {
var variable = extractVariable(line);
if (variable) {
var color = extractColour(line, variable);
if (color) {
obj[variable] = color;
}
}
});
}
grunt.registerTask('styleguide', function() {
var data = {
dark: {}, light: {}
};
readVars('public/sass/_variables.dark.scss', data.dark);
readVars('public/sass/_variables.light.scss', data.light);
var styleGuideJson = grunt.config().genDir + '/sass/styleguide.json';
grunt.file.write(styleGuideJson, JSON.stringify(data, null, 4));
});
};

View File

@@ -1,37 +0,0 @@
module.exports = function(grunt) {
"use strict";
grunt.registerTask('systemjs:build', function() {
var path = require('path');
var Builder = require('systemjs-builder');
var done = this.async();
// optional constructor options
// sets the baseURL and loads the configuration file
var builder = new Builder('public_gen', 'public_gen/app/system.conf.js');
console.log('Starting systemjs-builder');
var modules = [
'app/app',
'app/features/all',
'app/plugins/panel/**/module',
'app/plugins/datasource/graphite/module',
'app/plugins/datasource/influxdb/module',
'app/plugins/datasource/elasticsearch/module',
];
var expression = modules.join(' + ');
builder
.bundle(expression, 'public_gen/app/app_bundle.js')
.then(function(res) {
done();
grunt.task.run('concat:bundle_and_boot');
})
.catch(function(err) {
console.log('Build error');
console.log(err);
done(false);
});
});
};

View File