* 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

@ -0,0 +1,13 @@
module.exports = function(grunt) {
"use strict";
// Concat and Minify the src directory into dist
grunt.registerTask('build', [
'clean:release',
'clean:build',
'phantomjs',
'webpack:prod',
]);
};

View File

@ -0,0 +1,34 @@
// Lint and build CSS
module.exports = function(grunt) {
'use strict';
grunt.registerTask('default', [
'clean:build',
'phantomjs',
'webpack:dev',
]);
grunt.registerTask('test', [
'clean:build',
'jscs',
'jshint',
'sasslint',
'exec:tslint',
'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

@ -0,0 +1,11 @@
module.exports = function(config) {
'use strict';
return {
release: ['<%= destDir %>', '<%= tempDir %>', '<%= genDir %>'],
build: ['<%= srcDir %>/build'],
temp: ['<%= tempDir %>'],
packaging: [
],
};
};

View File

@ -0,0 +1,30 @@
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

@ -0,0 +1,6 @@
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",
};
};

View File

@ -0,0 +1,22 @@
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

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

View File

@ -0,0 +1,20 @@
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

@ -0,0 +1,37 @@
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

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

View File

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

View File

@ -0,0 +1,13 @@
const dev = require('../../webpack/webpack.dev.js');
const prod = require('../../webpack/webpack.prod.js');
module.exports = function() {
'use strict';
return {
options: {
stats: !process.env.NODE_ENV || process.env.NODE_ENV === 'development'
},
dev: dev,
prod: prod
};
};

View File

@ -0,0 +1,41 @@
var path = require('path');
module.exports = function(grunt) {
"use strict";
// build, then zip and upload to s3
grunt.registerTask('release', [
'build',
'build-post-process',
'compress:release'
]);
grunt.registerTask('build-post-process', function() {
grunt.config('copy.public_to_temp', {
expand: true,
cwd: '<%= srcDir %>',
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_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

@ -0,0 +1,47 @@
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().srcDir + '/build/styleguide.json';
grunt.file.write(styleGuideJson, JSON.stringify(data, null, 4));
});
};

View File

@ -0,0 +1,7 @@
module.exports = {
plugins: {
'autoprefixer': {},
'postcss-reporter': {},
'postcss-browser-reporter': {},
}
}

View File

@ -0,0 +1,31 @@
'use strict';
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = function(options) {
return {
test: /\.scss$/,
use: ExtractTextPlugin.extract({
use: [
{
loader: 'css-loader',
options: {
importLoaders: 2,
url: false,
sourceMap: options.sourceMap,
minimize: options.minimize,
}
},
{
loader: 'postcss-loader',
options: {
sourceMap: options.sourceMap,
config: { path: __dirname + '/postcss.config.js' }
}
},
{ loader:'sass-loader', options: { sourceMap: options.sourceMap } }
],
})
};
}

View File

@ -0,0 +1,87 @@
const path = require('path');
const {CheckerPlugin} = require('awesome-typescript-loader')
module.exports = {
target: 'web',
stats: {
children: false
},
entry: {
app: './public/app/index.ts',
},
output: {
path: path.resolve(__dirname, '../../public/build'),
filename: '[name].[chunkhash].js',
publicPath: "public/build/",
},
resolve: {
extensions: ['.ts', '.tsx', '.es6', '.js', '.json'],
alias: {
},
modules: [
path.resolve('public'),
path.resolve('node_modules')
],
},
node: {
fs: 'empty',
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
enforce: 'pre',
exclude: /node_modules/,
use: {
loader: 'tslint-loader',
options: {
emitErrors: true
}
}
},
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: [
{ loader: "awesome-typescript-loader" }
]
},
{
test: require.resolve('jquery'),
use: [
{
loader: 'expose-loader',
query: 'jQuery'
},
{
loader: 'expose-loader',
query: '$'
}
]
},
// {
// test : /\.(ico|png|cur|jpg|ttf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
// loader : 'file-loader',
// },
{
test: /\.html$/,
exclude: /index\.template.html/,
use: [
{ loader:'ngtemplate-loader?relativeTo=' + (path.resolve(__dirname, '../../public')) + '&prefix=public'},
{
loader: 'html-loader',
options: {
attrs: [],
minimize: true,
removeComments: false,
collapseWhitespace: false
}
}
]
}
]
},
plugins: [
new CheckerPlugin(),
]
};

View File

@ -0,0 +1,54 @@
'use strict';
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const WebpackCleanupPlugin = require('webpack-cleanup-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const pkg = require('../../package.json');
let dependencies = Object.keys(pkg.dependencies);
module.exports = merge(common, {
devtool: "source-map",
entry: {
dark: './public/sass/grafana.dark.scss',
light: './public/sass/grafana.light.scss',
vendor: dependencies,
},
module: {
rules: [
require('./sass.rule.js')({
sourceMap: true, minimize: false
})
]
},
plugins: [
new ExtractTextPlugin({ // define where to save the file
filename: 'grafana.[name].css',
}),
new HtmlWebpackPlugin({
filename: path.resolve(__dirname, '../../public/views/index.html'),
template: path.resolve(__dirname, '../../public/views/index.template.html'),
inject: 'body',
chunks: ['manifest', 'vendor', 'app'],
}),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('development')
}
}),
new webpack.optimize.CommonsChunkPlugin({
names: ['vendor', 'manifest'],
}),
new WebpackCleanupPlugin(),
// new BundleAnalyzerPlugin({
// analyzerPort: 8889
// })
]
});

View File

@ -0,0 +1,62 @@
'use strict';
const merge = require('webpack-merge');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const common = require('./webpack.common.js');
const webpack = require('webpack');
const path = require('path');
const ngAnnotatePlugin = require('ng-annotate-webpack-plugin');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const pkg = require('../../package.json');
let dependencies = Object.keys(pkg.dependencies);
module.exports = merge(common, {
devtool: "source-map",
entry: {
dark: './public/sass/grafana.dark.scss',
light: './public/sass/grafana.light.scss',
vendor: dependencies,
},
module: {
rules: [
require('./sass.rule.js')({
sourceMap: false, minimize: true
})
]
},
plugins: [
new ExtractTextPlugin({
filename: 'grafana.[name].css',
}),
new ngAnnotatePlugin(),
new UglifyJSPlugin({
sourceMap: true,
}),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
}),
new HtmlWebpackPlugin({
filename: path.resolve(__dirname, '../../public/views/index.html'),
template: path.resolve(__dirname, '../../public/views/index.template.html'),
inject: 'body',
chunks: ['manifest', 'vendor', 'app'],
}),
new webpack.optimize.CommonsChunkPlugin({
names: ['vendor', 'manifest'],
}),
function() {
this.plugin("done", function(stats) {
if (stats.compilation.errors && stats.compilation.errors.length) {
console.log(stats.compilation.errors);
process.exit(1);
}
});
}
]
});

View File

@ -0,0 +1,23 @@
const webpack = require('webpack');
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
config = merge(common, {
devtool: 'inline-source-map',
externals: {
'react/addons': true,
'react/lib/ExecutionEnvironment': true,
'react/lib/ReactContext': true,
},
node: {
fs: 'empty'
},
plugins: [
new webpack.SourceMapDevToolPlugin({
filename: null, // if no value is provided the sourcemap is inlined
test: /\.(ts|js)($|\?)/i // process .js and .ts files only
})
]
});
module.exports = config;