diff options
-rw-r--r-- | server/sonar-web/.babelrc | 27 | ||||
-rw-r--r-- | server/sonar-web/.eslintignore | 2 | ||||
-rw-r--r-- | server/sonar-web/.gitignore | 2 | ||||
-rw-r--r-- | server/sonar-web/config/autoprefixer.js | 28 | ||||
-rw-r--r-- | server/sonar-web/config/paths.js | 27 | ||||
-rw-r--r-- | server/sonar-web/config/webpack/webpack.config.base.js (renamed from server/sonar-web/webpack.config.js) | 19 | ||||
-rw-r--r-- | server/sonar-web/config/webpack/webpack.config.dev.js (renamed from server/sonar-web/webpack.config.dev.js) | 5 | ||||
-rw-r--r-- | server/sonar-web/config/webpack/webpack.config.fast.js (renamed from server/sonar-web/devServer.js) | 39 | ||||
-rw-r--r-- | server/sonar-web/config/webpack/webpack.config.prod.js | 34 | ||||
-rw-r--r-- | server/sonar-web/gulp/styles.js | 34 | ||||
-rw-r--r-- | server/sonar-web/gulpfile.js | 89 | ||||
-rw-r--r-- | server/sonar-web/package.json | 28 | ||||
-rw-r--r-- | server/sonar-web/scripts/build.js | 62 | ||||
-rw-r--r-- | server/sonar-web/scripts/start.js | 158 |
14 files changed, 389 insertions, 165 deletions
diff --git a/server/sonar-web/.babelrc b/server/sonar-web/.babelrc index 0ecf1664f9c..fb5f2613035 100644 --- a/server/sonar-web/.babelrc +++ b/server/sonar-web/.babelrc @@ -1,17 +1,28 @@ { - "presets": ["es2015", "stage-0", "react"], + "presets": ["es2015", "es2016", "react"], "ignore": [ "**/libs/**" ], + "plugins": [ + "transform-class-properties", + "transform-object-rest-spread" + ], "env": { - "hot": { - "plugins": [["react-transform", { - "transforms": [{ - "transform": "react-transform-hmr", - "imports": ["react"], - "locals": ["module"] + "production": { + "plugins": [ + "transform-react-constant-elements" + ] + }, + "development": { + "plugins": [ + ["react-transform", { + "transforms": [{ + "transform": "react-transform-hmr", + "imports": ["react"], + "locals": ["module"] + }] }] - }]] + ] } } } diff --git a/server/sonar-web/.eslintignore b/server/sonar-web/.eslintignore index 1e86f01a222..80fae5d334e 100644 --- a/server/sonar-web/.eslintignore +++ b/server/sonar-web/.eslintignore @@ -1,2 +1,4 @@ src/main/js/libs tests +scripts +config diff --git a/server/sonar-web/.gitignore b/server/sonar-web/.gitignore index 10ecba26bcc..4248ae850ed 100644 --- a/server/sonar-web/.gitignore +++ b/server/sonar-web/.gitignore @@ -5,7 +5,7 @@ node/ node_modules/ # npm logs -npm-debug.log.* +npm-debug.log npm.tar.gz # build diff --git a/server/sonar-web/config/autoprefixer.js b/server/sonar-web/config/autoprefixer.js new file mode 100644 index 00000000000..cfa9b836c52 --- /dev/null +++ b/server/sonar-web/config/autoprefixer.js @@ -0,0 +1,28 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +module.exports = { + browsers: [ + 'last 3 Chrome versions', + 'last 3 Firefox versions', + 'Safari >= 8', + 'Edge >= 12', + 'IE 11' + ] +}; diff --git a/server/sonar-web/config/paths.js b/server/sonar-web/config/paths.js new file mode 100644 index 00000000000..1484c1b0607 --- /dev/null +++ b/server/sonar-web/config/paths.js @@ -0,0 +1,27 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +var path = require('path'); + +var base = process.env.OUTPUT || path.join(__dirname, '../src/main/webapp'); + +module.exports = { + jsBuild: path.join(base, 'js/bundles'), + cssBuild: path.join(base, 'css') +}; diff --git a/server/sonar-web/webpack.config.js b/server/sonar-web/config/webpack/webpack.config.base.js index cea911812e7..f718dbd7dc2 100644 --- a/server/sonar-web/webpack.config.js +++ b/server/sonar-web/config/webpack/webpack.config.base.js @@ -1,14 +1,9 @@ /* eslint no-var: 0 */ -/* eslint object-shorthand: 0 */ -/* jscs:disable requireEnhancedObjectLiterals */ var path = require('path'); var webpack = require('webpack'); var autoprefixer = require('autoprefixer'); - -var autoprefixerOptions = require('./gulp/styles').autoprefixerOptions; - -var baseOutput = process.env.OUTPUT || path.join(__dirname, 'src/main/webapp'); -var output = path.join(baseOutput, 'js/bundles'); +var autoprefixerOptions = require('./../autoprefixer'); +var paths = require('./../paths'); module.exports = { entry: { @@ -59,21 +54,21 @@ module.exports = { 'widgets': './src/main/js/widgets/widgets.js' }, output: { - path: output, + path: paths.jsBuild, filename: '[name].js' }, plugins: [ new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.js') ], resolve: { - root: path.join(__dirname, 'src/main/js') + root: path.join(__dirname, '../../src/main/js') }, module: { loaders: [ { test: /\.js$/, loader: 'babel', - exclude: /(node_modules|libs)/ + exclude: /(node_modules|libs)/, }, { test: /(blueimp-md5|numeral)/, @@ -81,9 +76,9 @@ module.exports = { }, { test: /\.hbs$/, - loader: 'handlebars-loader', + loader: 'handlebars', query: { - helperDirs: path.join(__dirname, 'src/main/js/helpers/handlebars') + helperDirs: path.join(__dirname, '../../src/main/js/helpers/handlebars') } }, { diff --git a/server/sonar-web/webpack.config.dev.js b/server/sonar-web/config/webpack/webpack.config.dev.js index f0fc980c360..117450951a3 100644 --- a/server/sonar-web/webpack.config.dev.js +++ b/server/sonar-web/config/webpack/webpack.config.dev.js @@ -17,15 +17,14 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -/* eslint no-var: 0 */ var webpack = require('webpack'); - -var config = require('./webpack.config'); +var config = require('./webpack.config.base'); config.devtool = 'cheap-module-eval-source-map'; config.output.publicPath = '/js/bundles/'; config.entry.vendor.unshift('webpack-hot-middleware/client'); config.plugins = [].concat(config.plugins, [ + new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"development"' }), new webpack.HotModuleReplacementPlugin() ]); diff --git a/server/sonar-web/devServer.js b/server/sonar-web/config/webpack/webpack.config.fast.js index 837e83ef104..87cc9383b3a 100644 --- a/server/sonar-web/devServer.js +++ b/server/sonar-web/config/webpack/webpack.config.fast.js @@ -17,40 +17,11 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - /* eslint no-var: 0 */ - /* eslint no-console: 0 */ - /* eslint object-shorthand: 0 */ - /* jscs:disable requireEnhancedObjectLiterals */ -var url = require('url'); -var express = require('express'); -var proxy = require('express-http-proxy'); var webpack = require('webpack'); -var config = require('./webpack.config.dev'); +var config = require('./webpack.config.base'); -var app = express(); -var compiler = webpack(config); +config.plugins = [].concat(config.plugins, [ + new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"development"' }), +]); -var PORT = process.env.PORT || 8080; -var API_HOST = process.env.API_HOST || 'http://localhost:9000'; - -app.use(require('webpack-dev-middleware')(compiler, { - noInfo: true, - publicPath: config.output.publicPath -})); - -app.use(require('webpack-hot-middleware')(compiler)); - -app.all('*', proxy(API_HOST, { - forwardPath: function (req) { - return url.parse(req.url).path; - } -})); - -app.listen(PORT, 'localhost', function (err) { - if (err) { - console.log(err); - return; - } - - console.log('Listening at http://localhost:' + PORT); -}); +module.exports = config; diff --git a/server/sonar-web/config/webpack/webpack.config.prod.js b/server/sonar-web/config/webpack/webpack.config.prod.js new file mode 100644 index 00000000000..7c5c3917986 --- /dev/null +++ b/server/sonar-web/config/webpack/webpack.config.prod.js @@ -0,0 +1,34 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * 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 config = require('./webpack.config.base'); + +config.plugins = [].concat(config.plugins, [ + new webpack.DefinePlugin({ 'process.env.NODE_ENV': '"production"' }), + new webpack.optimize.OccurrenceOrderPlugin(), + new webpack.optimize.DedupePlugin(), + new webpack.optimize.UglifyJsPlugin({ + compress: { screw_ie8: true, warnings: false }, + mangle: { screw_ie8: true }, + output: { screw_ie8: true, comments: false } + }) +]); + +module.exports = config; diff --git a/server/sonar-web/gulp/styles.js b/server/sonar-web/gulp/styles.js deleted file mode 100644 index 14d98861074..00000000000 --- a/server/sonar-web/gulp/styles.js +++ /dev/null @@ -1,34 +0,0 @@ -var path = require('path'); - -var gulp = require('gulp'); -var gulpif = require('gulp-if'); -var less = require('gulp-less'); -var nano = require('gulp-cssnano'); -var autoprefixer = require('gulp-autoprefixer'); - - -var nanoOptions = { - zindex: false, - discardComments: { removeAll: true } -}; - -var autoprefixerOptions = { - browsers: [ - 'last 3 Chrome versions', - 'last 3 Firefox versions', - 'Safari >= 8', - 'Edge >= 12', - 'IE 11' - ] -}; - - -module.exports.autoprefixerOptions = autoprefixerOptions; - -module.exports.styles = function (output, production) { - return gulp.src(['src/main/less/sonar.less']) - .pipe(less()) - .pipe(autoprefixer(autoprefixerOptions)) - .pipe(gulpif(production, nano(nanoOptions))) - .pipe(gulp.dest(path.join(output, 'css'))); -}; diff --git a/server/sonar-web/gulpfile.js b/server/sonar-web/gulpfile.js index 517f94c6fd6..4f8baa3c1b1 100644 --- a/server/sonar-web/gulpfile.js +++ b/server/sonar-web/gulpfile.js @@ -1,75 +1,38 @@ -var path = require('path'); - +/* eslint no-var: 0 */ var del = require('del'); var gulp = require('gulp'); -var gutil = require('gulp-util'); -var webpack = require('webpack'); - -var argv = require('yargs').argv; -var output = argv.output || path.join(__dirname, 'src/main/webapp'); - -var styles = require('./gulp/styles').styles; -var webpackConfig = require('./webpack.config.js'); -webpackConfig.output.path = path.join(output, 'js/bundles'); - - -// Clean +var gulpif = require('gulp-if'); +var less = require('gulp-less'); +var nano = require('gulp-cssnano'); +var autoprefixer = require('gulp-autoprefixer'); +var paths = require('./config/paths'); +var autoprefixerOptions = require('./config/autoprefixer'); + +var nanoOptions = { + zindex: false, + discardComments: { removeAll: true } +}; + +function styles (output, production) { + return gulp.src(['src/main/less/sonar.less']) + .pipe(less()) + .pipe(autoprefixer(autoprefixerOptions)) + .pipe(gulpif(production, nano(nanoOptions))) + .pipe(gulp.dest(output)); +} gulp.task('clean', function (done) { - del([ - path.join(output, 'js'), - path.join(output, 'css') - ], done); + del(paths.cssBuild, done); }); - -// Styles - gulp.task('styles:prod', function () { - return styles(output, true); + return styles(paths.cssBuild, true); }); gulp.task('styles:dev', function () { - return styles(output, false, true); -}); - - -// Webpack - -gulp.task('webpack:prod', function (callback) { - var webpackProdConfig = Object.create(webpackConfig); - webpackProdConfig.plugins = webpackProdConfig.plugins.concat( - new webpack.DefinePlugin({ - 'process.env': { - 'NODE_ENV': JSON.stringify('production'), - 'OUTPUT': output - } - }), - new webpack.optimize.DedupePlugin(), - new webpack.optimize.UglifyJsPlugin() - ); - - webpack(webpackProdConfig, function (err) { - if (err) { - throw new gutil.PluginError('webpack:prod', err); - } - callback(); - }); + return styles(paths.cssBuild, false); }); -gulp.task('webpack:dev', function (callback) { - // run webpack - webpack(webpackConfig, function (err) { - if (err) { - throw new gutil.PluginError('webpack:dev', err); - } - callback(); - }); -}); - - -// Tasks - -gulp.task('build', ['clean', 'styles:prod', 'webpack:prod']); -gulp.task('build:dev', ['clean', 'styles:dev', 'webpack:dev']); -gulp.task('default', ['build']); +gulp.task('default', ['clean', 'styles:prod']); +gulp.task('build', ['clean', 'styles:prod']); +gulp.task('build-fast', ['clean', 'styles:dev']); diff --git a/server/sonar-web/package.json b/server/sonar-web/package.json index 3bc34ccd86f..7ad51930cd0 100644 --- a/server/sonar-web/package.json +++ b/server/sonar-web/package.json @@ -7,21 +7,27 @@ "devDependencies": { "autoprefixer": "6.2.2", "babel-cli": "6.3.17", - "babel-core": "6.3.17", + "babel-core": "6.13.2", "babel-eslint": "^6.0.4", - "babel-loader": "6.2.0", + "babel-loader": "6.2.4", "babel-plugin-react-transform": "2.0.2", + "babel-plugin-transform-class-properties": "6.11.5", + "babel-plugin-transform-object-rest-spread": "6.8.0", + "babel-plugin-transform-react-constant-elements": "6.9.1", "babel-polyfill": "6.3.14", - "babel-preset-es2015": "6.3.13", - "babel-preset-react": "6.3.13", + "babel-preset-es2015": "6.13.2", + "babel-preset-es2016": "6.11.3", + "babel-preset-react": "6.11.1", "babel-preset-stage-0": "6.3.13", "babel-register": "6.3.13", "backbone": "1.2.3", "backbone.marionette": "2.4.3", "blueimp-md5": "1.1.1", "chai": "3.3.0", + "chalk": "1.1.3", "classnames": "2.2.0", "clipboard": "1.5.5", + "cross-env": "^2.0.0", "css-loader": "0.23.1", "d3": "3.5.6", "del": "2.0.2", @@ -53,6 +59,7 @@ "mockery": "1.7.0", "moment": "2.10.6", "numeral": "1.5.3", + "nyc": "^8.1.0", "postcss-loader": "0.8.0", "react": "15.0.1", "react-addons-perf": "15.0.1", @@ -69,6 +76,7 @@ "redux-logger": "2.2.1", "redux-simple-router": "1.0.1", "redux-thunk": "1.0.2", + "rimraf": "2.5.4", "script-loader": "0.6.1", "sinon": "1.15.4", "sinon-chai": "2.8.0", @@ -83,12 +91,12 @@ "yargs": "3.27.0" }, "scripts": { - "build-fast": "gulp build:dev", - "build": "gulp build", - "test": "mocha --opts tests/mocha.opts src/main/js/**/__tests__/**/*", - "coverage": "nyc --exclude tests,**/__tests__/** mocha --opts tests/mocha.opts src/main/js/**/__tests__/**/* && nyc report --reporter lcov --report-dir target/coverage", - "lint": "eslint src/main/js", - "dev": "NODE_ENV=hot node devServer" + "start": "node ./scripts/start.js", + "build-fast": "node ./scripts/build.js --fast && gulp build-fast", + "build": "node ./scripts/build.js && gulp build", + "test": "cross-env NODE_ENV=test mocha --opts tests/mocha.opts src/main/js/**/__tests__/**/*", + "coverage": "cross-env NODE_ENV=test nyc mocha --opts tests/mocha.opts src/main/js/**/__tests__/**/* && nyc report --reporter lcov --report-dir target/coverage", + "lint": "eslint src/main/js" }, "engines": { "node": ">=4" diff --git a/server/sonar-web/scripts/build.js b/server/sonar-web/scripts/build.js new file mode 100644 index 00000000000..0226ff25163 --- /dev/null +++ b/server/sonar-web/scripts/build.js @@ -0,0 +1,62 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +process.env.NODE_ENV = 'production'; + +var chalk = require('chalk'); +var fs = require('fs'); +var path = require('path'); +var rimrafSync = require('rimraf').sync; +var webpack = require('webpack'); +var paths = require('../config/paths'); + +var isFastBuild = process.argv.some(arg => arg.indexOf('--fast') > -1); + +var config = isFastBuild ? + require('../config/webpack/webpack.config.fast') : + require('../config/webpack/webpack.config.prod'); + +// 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 directory...')); +console.log(paths.jsBuild + '/*'); +console.log(); +rimrafSync(paths.jsBuild + '/*'); + +if (isFastBuild) { + console.log(chalk.magenta.bold('Running fast build...')); +} else { + console.log(chalk.cyan.bold('Creating optimized production build...')); +} +console.log(); + +webpack(config).run(function (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); + } + + console.log(chalk.green.bold('Compiled successfully!')); + + var jsonStats = stats.toJson(); + var seconds = jsonStats.time / 1000; + console.log('Duration: ' + seconds.toFixed(2) + 's'); + console.log(); +}); diff --git a/server/sonar-web/scripts/start.js b/server/sonar-web/scripts/start.js new file mode 100644 index 00000000000..ceb9d61928a --- /dev/null +++ b/server/sonar-web/scripts/start.js @@ -0,0 +1,158 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +process.env.NODE_ENV = 'development'; + +var url = require('url'); +var express = require('express'); +var proxy = require('express-http-proxy'); +var webpack = require('webpack'); +var chalk = require('chalk'); +var config = require('../config/webpack/webpack.config.dev.js'); + +var app = express(); + +var DEFAULT_PORT = process.env.PORT || 8080; +var API_HOST = process.env.API_HOST || 'http://localhost:9000'; + +var compiler; + +var friendlySyntaxErrorLabel = 'Syntax error:'; + +function isLikelyASyntaxError (message) { + return message.indexOf(friendlySyntaxErrorLabel) !== -1; +} + +// This is a little hacky. +// It would be easier if webpack provided a rich error object. + +function formatMessage (message) { + return message + // Make some common errors shorter: + .replace( + // Babel syntax error + 'Module build failed: SyntaxError:', + friendlySyntaxErrorLabel + ) + .replace( + // Webpack file not found error + /Module not found: Error: Cannot resolve 'file' or 'directory'/, + 'Module not found:' + ) + // Internal stacks are generally useless so we strip them + .replace(/^\s*at\s.*:\d+:\d+[\s\)]*\n/gm, '') // at ... ...:x:y + // Webpack loader names obscure CSS filenames + .replace('./~/css-loader!./~/postcss-loader!', ''); +} + +function setupCompiler () { + compiler = webpack(config); + + compiler.plugin('invalid', function () { + console.log(chalk.cyan.bold('Compiling...')); + }); + + compiler.plugin('done', function (stats) { + var hasErrors = stats.hasErrors(); + var hasWarnings = stats.hasWarnings(); + if (!hasErrors && !hasWarnings) { + console.log(chalk.green.bold('Compiled successfully!')); + return; + } + + var json = stats.toJson(); + var formattedErrors = json.errors.map(message => + 'Error in ' + formatMessage(message) + ); + var formattedWarnings = json.warnings.map(message => + 'Warning in ' + formatMessage(message) + ); + + if (hasErrors) { + console.log(chalk.red.bold('Failed to compile:')); + console.log(); + if (formattedErrors.some(isLikelyASyntaxError)) { + // If there are any syntax errors, show just them. + // This prevents a confusing ESLint parsing error + // preceding a much more useful Babel syntax error. + formattedErrors = formattedErrors.filter(isLikelyASyntaxError); + } + formattedErrors.forEach(message => { + console.log(message); + console.log(); + }); + // If errors exist, ignore warnings. + return; + } + + if (hasWarnings) { + console.log(chalk.yellow('Compiled with warnings.')); + console.log(); + formattedWarnings.forEach(message => { + console.log(message); + console.log(); + }); + + console.log('You may use special comments to disable some warnings.'); + console.log('Use ' + chalk.yellow( + '// eslint-disable-next-line') + ' to ignore the next line.'); + console.log('Use ' + chalk.yellow( + '/* eslint-disable */') + ' to ignore all warnings in a file.'); + } + }); +} + +function runDevServer (port) { + app.use(require('webpack-dev-middleware')(compiler, { + noInfo: true, + quiet: true, + publicPath: config.output.publicPath + })); + + app.use(require('webpack-hot-middleware')(compiler, { + noInfo: true, + quiet: true + })); + + app.all('*', proxy(API_HOST, { + forwardPath: function (req) { + return url.parse(req.url).path; + } + })); + + app.listen(port, 'localhost', function (err) { + if (err) { + console.log(err); + return; + } + + console.log(chalk.green.bold( + 'The app is running at http://localhost:' + port + '/')); + console.log(chalk.cyan.bold('Compiling...')); + console.log(); + }); +} + +function run (port) { + setupCompiler(); + runDevServer(port); +} + +run(DEFAULT_PORT); + |