@@ -12,6 +12,7 @@ npm.tar.gz | |||
build/ | |||
src/main/webapp/js/ | |||
src/main/webapp/css/ | |||
src/main/webapp/index.html | |||
src/main/webapp/WEB-INF/lib/*.jar | |||
# tests |
@@ -45,10 +45,14 @@ var nodePaths = (process.env.NODE_PATH || '') | |||
// config after eject: we're in ./config/ | |||
module.exports = { | |||
appBuild: resolveApp('src/main/webapp/js/bundles'), | |||
appBuild: resolveApp('src/main/webapp'), | |||
appPublic: resolveApp('public'), | |||
appHtml: resolveApp('public/index.html'), | |||
appPackageJson: resolveApp('package.json'), | |||
appSrc: resolveApp('src/main/js'), | |||
jsBuild: resolveApp('src/main/webapp/js'), | |||
cssBuild: resolveApp('src/main/webapp/css'), | |||
htmlBuild: resolveApp('src/main/webapp/index.html'), | |||
appNodeModules: resolveApp('node_modules'), | |||
ownNodeModules: resolveApp('node_modules'), | |||
nodePaths: nodePaths |
@@ -1,10 +1,7 @@ | |||
/* eslint no-var: 0 */ | |||
var path = require('path'); | |||
var autoprefixer = require('autoprefixer'); | |||
var webpack = require('webpack'); | |||
var ExtractTextPlugin = require('extract-text-webpack-plugin'); | |||
var InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin'); | |||
var url = require('url'); | |||
var paths = require('../paths'); | |||
var autoprefixerOptions = require('../autoprefixer'); | |||
@@ -25,19 +22,13 @@ module.exports = { | |||
'sonar': './src/main/js/libs/sonar.js', | |||
'app': './src/main/js/app/index.js', | |||
// not unique url | |||
'source-viewer': './src/main/js/apps/source-viewer/app.js' | |||
'app': './src/main/js/app/index.js' | |||
}, | |||
output: { | |||
path: paths.appBuild, | |||
filename: '[name].js' | |||
filename: 'js/[name].[chunkhash:8].js', | |||
chunkFilename: 'js/[name].[chunkhash:8].chunk.js', | |||
}, | |||
plugins: [ | |||
new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.js'), | |||
new ExtractTextPlugin('../../css/sonar.css', { allChunks: true }) | |||
], | |||
resolve: { | |||
// This allows you to set a fallback for where Webpack should look for modules. | |||
// We read `NODE_PATH` environment variable in `paths.js` and pass paths here. |
@@ -18,16 +18,17 @@ | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
var webpack = require('webpack'); | |||
var HtmlWebpackPlugin = require('html-webpack-plugin'); | |||
var ExtractTextPlugin = require('extract-text-webpack-plugin'); | |||
var InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin'); | |||
var CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin'); | |||
var WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin'); | |||
var paths = require('../paths'); | |||
var config = require('./webpack.config.base'); | |||
var getClientEnvironment = require('../env'); | |||
// Webpack uses `publicPath` to determine where the app is being served from. | |||
var publicPath = '/js/bundles/'; | |||
// Get environment variables to inject into our app. | |||
var publicPath = ''; | |||
var webContext = ''; | |||
var env = getClientEnvironment(); | |||
// This makes the bundle appear split into separate modules in the devtools. | |||
@@ -53,22 +54,44 @@ config.output.pathinfo = true; | |||
// This is the URL that app is served from. | |||
config.output.publicPath = publicPath; | |||
config.output.filename = 'js/[name].js'; | |||
config.output.chunkFilename = 'js/[name].chunk.js'; | |||
config.plugins = [ | |||
new webpack.optimize.CommonsChunkPlugin('vendor', 'js/vendor.js'), | |||
new ExtractTextPlugin('css/sonar.css', { allChunks: true }), | |||
// Makes the web context available as %WEB_CONTEXT% in index.html, e.g.: | |||
// <link rel="shortcut icon" href="%WEB_CONTEXT%/favicon.ico"> | |||
// In development, this will be an empty string. | |||
new InterpolateHtmlPlugin({ | |||
WEB_CONTEXT: webContext | |||
}), | |||
// Generates an `index.html` file with the <script> injected. | |||
new HtmlWebpackPlugin({ | |||
inject: false, | |||
template: paths.appHtml, | |||
}), | |||
config.plugins = [].concat(config.plugins, [ | |||
// Makes some environment variables available to the JS code, for example: | |||
// if (process.env.NODE_ENV === 'development') { ... }. See `./env.js`. | |||
new webpack.DefinePlugin(env), | |||
// This is necessary to emit hot updates (currently CSS only): | |||
new webpack.HotModuleReplacementPlugin(), | |||
// Watcher doesn't work well if you mistype casing in a path so we use | |||
// a plugin that prints an error when you attempt to do this. | |||
// See https://github.com/facebookincubator/create-react-app/issues/240 | |||
new CaseSensitivePathsPlugin(), | |||
// If you require a missing module and then `npm install` it, you still have | |||
// to restart the development server for Webpack to discover it. This plugin | |||
// makes the discovery automatic so you don't have to restart. | |||
// See https://github.com/facebookincubator/create-react-app/issues/186 | |||
new WatchMissingNodeModulesPlugin(paths.appNodeModules) | |||
]); | |||
]; | |||
module.exports = config; |
@@ -17,9 +17,31 @@ | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
var webpack = require('webpack'); | |||
var ExtractTextPlugin = require('extract-text-webpack-plugin'); | |||
var HtmlWebpackPlugin = require('html-webpack-plugin'); | |||
var config = require('./webpack.config.base'); | |||
var getClientEnvironment = require('../env'); | |||
var paths = require('../paths'); | |||
// Get environment variables to inject into our app. | |||
var env = getClientEnvironment(); | |||
// disable eslint loader | |||
config.module.preLoaders = []; | |||
// Don't attempt to continue if there are any errors. | |||
config.bail = true; | |||
config.plugins = [ | |||
new webpack.optimize.CommonsChunkPlugin('vendor', 'js/vendor.[chunkhash:8].js'), | |||
new ExtractTextPlugin('css/sonar.[chunkhash:8].css', { allChunks: true }), | |||
new HtmlWebpackPlugin({ | |||
inject: false, | |||
template: paths.appHtml | |||
}) | |||
]; | |||
module.exports = config; |
@@ -18,8 +18,11 @@ | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
var webpack = require('webpack'); | |||
var ExtractTextPlugin = require('extract-text-webpack-plugin'); | |||
var HtmlWebpackPlugin = require('html-webpack-plugin'); | |||
var config = require('./webpack.config.base'); | |||
var getClientEnvironment = require('../env'); | |||
var paths = require('../paths'); | |||
// Get environment variables to inject into our app. | |||
var env = getClientEnvironment(); | |||
@@ -33,16 +36,40 @@ if (env['process.env.NODE_ENV'] !== '"production"') { | |||
// Don't attempt to continue if there are any errors. | |||
config.bail = true; | |||
config.plugins = [].concat(config.plugins, [ | |||
config.plugins = [ | |||
new webpack.optimize.CommonsChunkPlugin('vendor', 'js/vendor.[chunkhash:8].js'), | |||
new ExtractTextPlugin('css/sonar.[chunkhash:8].css', { allChunks: true }), | |||
new HtmlWebpackPlugin({ | |||
inject: false, | |||
template: paths.appHtml, | |||
minify: { | |||
removeComments: true, | |||
collapseWhitespace: true, | |||
removeRedundantAttributes: true, | |||
useShortDoctype: true, | |||
removeEmptyAttributes: true, | |||
removeStyleLinkTypeAttributes: true, | |||
keepClosingSlash: true, | |||
minifyJS: true, | |||
minifyCSS: true, | |||
minifyURLs: true | |||
} | |||
}), | |||
// Makes some environment variables available to the JS code, for example: | |||
// if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`. | |||
// It is absolutely essential that NODE_ENV was set to production here. | |||
// Otherwise React will be compiled in the very slow development mode. | |||
new webpack.DefinePlugin(env), | |||
// This helps ensure the builds are consistent if source hasn't changed: | |||
new webpack.optimize.OccurrenceOrderPlugin(), | |||
// Try to dedupe duplicated modules, if any: | |||
new webpack.optimize.DedupePlugin(), | |||
// Minify the code. | |||
new webpack.optimize.UglifyJsPlugin({ | |||
compress: { | |||
@@ -56,7 +83,7 @@ config.plugins = [].concat(config.plugins, [ | |||
comments: false, | |||
screw_ie8: true | |||
} | |||
}), | |||
]); | |||
}) | |||
]; | |||
module.exports = config; |
@@ -48,6 +48,7 @@ | |||
"handlebars": "2.0.0", | |||
"handlebars-loader": "1.1.4", | |||
"history": "2.0.0", | |||
"html-webpack-plugin": "2.24.1", | |||
"imports-loader": "0.6.5", | |||
"jest": "15.1.1", | |||
"jquery": "2.2.0", |
@@ -0,0 +1,18 @@ | |||
<!DOCTYPE html> | |||
<html lang="en"> | |||
<head> | |||
<meta charset="UTF-8"> | |||
<link href="%WEB_CONTEXT%/favicon.ico" rel="shortcut icon" type="image/x-icon"> | |||
<% for (var css in htmlWebpackPlugin.files.css) { %> | |||
<link href="%WEB_CONTEXT%/<%= htmlWebpackPlugin.files.css[css] %>" rel="stylesheet"> | |||
<% } %> | |||
<title>SonarQube</title> | |||
</head> | |||
<body> | |||
<div id="content"></div> | |||
<script>window.baseUrl = '%WEB_CONTEXT%';</script> | |||
<% for (var chunk in htmlWebpackPlugin.files.chunks) { %> | |||
<script src="%WEB_CONTEXT%/<%= htmlWebpackPlugin.files.chunks[chunk].entry %>"></script> | |||
<% } %> | |||
</body> | |||
</html> |
@@ -20,7 +20,7 @@ | |||
process.env.NODE_ENV = 'production'; | |||
var chalk = require('chalk'); | |||
var fs = require('fs'); | |||
var fs = require('fs-extra'); | |||
var path = require('path'); | |||
var rimrafSync = require('rimraf').sync; | |||
var webpack = require('webpack'); | |||
@@ -33,54 +33,73 @@ var config = isFastBuild ? | |||
require('../config/webpack/webpack.config.fast') : | |||
require('../config/webpack/webpack.config.prod'); | |||
function clean () { | |||
// Remove all content but keep the directory so that | |||
// if you're in it, you don't end up in Trash | |||
console.log(chalk.cyan.bold('Cleaning output directories...')); | |||
console.log(chalk.cyan.bold('Cleaning output directories and files...')); | |||
console.log(paths.appBuild + '/*'); | |||
rimrafSync(paths.appBuild + '/*'); | |||
console.log(paths.jsBuild + '/*'); | |||
rimrafSync(paths.jsBuild + '/*'); | |||
console.log(paths.cssBuild + '/*'); | |||
rimrafSync(paths.cssBuild + '/*'); | |||
console.log(paths.cssBuild + '/*'); | |||
rimrafSync(paths.cssBuild + '/*'); | |||
console.log(); | |||
console.log(paths.htmlBuild); | |||
rimrafSync(paths.htmlBuild); | |||
if (isFastBuild) { | |||
console.log(chalk.magenta.bold('Running fast build...')); | |||
} else { | |||
console.log(chalk.cyan.bold('Creating optimized production build...')); | |||
console.log(); | |||
} | |||
console.log(); | |||
webpack(config, (err, stats) => { | |||
if (err) { | |||
console.log(chalk.red.bold('Failed to create a production build!')); | |||
console.log(chalk.red(err.message || err)); | |||
process.exit(1); | |||
function build () { | |||
if (isFastBuild) { | |||
console.log(chalk.magenta.bold('Running fast build...')); | |||
} else { | |||
console.log(chalk.cyan.bold('Creating optimized production build...')); | |||
} | |||
console.log(); | |||
if (stats.compilation.errors && stats.compilation.errors.length) { | |||
console.log(chalk.red.bold('Failed to create a production build!')); | |||
stats.compilation.errors.forEach(err => console.log(chalk.red(err.message || err))); | |||
process.exit(1); | |||
} | |||
webpack(config, (err, stats) => { | |||
if (err) { | |||
console.log(chalk.red.bold('Failed to create a production build!')); | |||
console.log(chalk.red(err.message || err)); | |||
process.exit(1); | |||
} | |||
if (stats.compilation.errors && stats.compilation.errors.length) { | |||
console.log(chalk.red.bold('Failed to create a production build!')); | |||
stats.compilation.errors.forEach(err => console.log(chalk.red(err.message || err))); | |||
process.exit(1); | |||
} | |||
var jsonStats = stats.toJson(); | |||
console.log('Assets:'); | |||
var assets = jsonStats.assets.slice(); | |||
assets.sort((a, b) => b.size - a.size); | |||
assets.forEach(asset => { | |||
var sizeLabel = formatSize(asset.size); | |||
var leftPadding = ' '.repeat(Math.max(0, 8 - sizeLabel.length)); | |||
sizeLabel = leftPadding + sizeLabel; | |||
console.log('', chalk.yellow(sizeLabel), asset.name); | |||
}); | |||
console.log(); | |||
var jsonStats = stats.toJson(); | |||
var seconds = jsonStats.time / 1000; | |||
console.log('Duration: ' + seconds.toFixed(2) + 's'); | |||
console.log(); | |||
console.log('Assets:'); | |||
var assets = jsonStats.assets.slice(); | |||
assets.sort((a, b) => b.size - a.size); | |||
assets.forEach(asset => { | |||
var sizeLabel = formatSize(asset.size); | |||
var leftPadding = ' '.repeat(8 - sizeLabel.length); | |||
sizeLabel = leftPadding + sizeLabel; | |||
console.log('', chalk.yellow(sizeLabel), asset.name); | |||
console.log(chalk.green.bold('Compiled successfully!')); | |||
}); | |||
console.log(); | |||
} | |||
function copyPublicFolder () { | |||
fs.copySync(paths.appPublic, paths.appBuild, { | |||
dereference: true, | |||
filter: file => file !== paths.appHtml | |||
}); | |||
} | |||
var seconds = jsonStats.time / 1000; | |||
console.log('Duration: ' + seconds.toFixed(2) + 's'); | |||
console.log(); | |||
console.log(chalk.green.bold('Compiled successfully!')); | |||
}); | |||
clean(); | |||
build(); | |||
copyPublicFolder(); |
@@ -45,19 +45,6 @@ var handleCompile; | |||
var PROXY_URL = 'http://localhost:9000'; | |||
// You can safely remove this after ejecting. | |||
// We only use this block for testing of Create React App itself: | |||
var isSmokeTest = process.argv.some(arg => arg.indexOf('--smoke-test') > -1); | |||
if (isSmokeTest) { | |||
handleCompile = function (err, stats) { | |||
if (err || stats.hasErrors() || stats.hasWarnings()) { | |||
process.exit(1); | |||
} else { | |||
process.exit(0); | |||
} | |||
}; | |||
} | |||
function setupCompiler (host, port, protocol) { | |||
// "Compiler" is a low-level interface to Webpack. | |||
// It lets us listen to some events and provide our own custom messages. | |||
@@ -181,7 +168,7 @@ function addMiddleware (devServer) { | |||
// - /*.hot-update.json (WebpackDevServer uses this too for hot reloading) | |||
// - /sockjs-node/* (WebpackDevServer uses this for hot reloading) | |||
// Tip: use https://jex.im/regulex/ to visualize the regex | |||
var mayProxy = /^(?!\/(.*\.hot-update\.json$|sockjs-node\/)).*$/; | |||
var mayProxy = /^(?!\/(index\.html$|.*\.hot-update\.json$|sockjs-node\/)).*$/; | |||
devServer.use(mayProxy, | |||
// Pass the scope regex both to Express and to the middleware for proxying | |||
// of both HTTP and WebSockets to work without false positives. | |||
@@ -201,6 +188,8 @@ function addMiddleware (devServer) { | |||
function runDevServer (host, port, protocol) { | |||
var devServer = new WebpackDevServer(compiler, { | |||
// Enable gzip compression of generated files. | |||
compress: true, | |||
// Silence WebpackDevServer's own logs since they're generally not useful. | |||
// It will still show compile warnings and errors with this setting. | |||
clientLogLevel: 'none', |