aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/config
diff options
context:
space:
mode:
authorStas Vilchik <stas.vilchik@sonarsource.com>2018-03-22 11:48:45 +0100
committerSonarTech <sonartech@sonarsource.com>2018-03-22 12:37:52 +0100
commitdf91a4ec347ba6e27184c6ea1117c226560fd3d0 (patch)
tree626d6ea2b5ac39c6d40f93da87600874d73ce5c0 /server/sonar-web/config
parent8da037d336f42543ef35d146be0adebea8928a6e (diff)
downloadsonarqube-df91a4ec347ba6e27184c6ea1117c226560fd3d0.tar.gz
sonarqube-df91a4ec347ba6e27184c6ea1117c226560fd3d0.zip
migrate to webpack 4 (#39)
Diffstat (limited to 'server/sonar-web/config')
-rw-r--r--server/sonar-web/config/InterpolateHtmlPlugin.js55
-rw-r--r--server/sonar-web/config/paths.js39
-rw-r--r--server/sonar-web/config/webpack.config.js167
3 files changed, 136 insertions, 125 deletions
diff --git a/server/sonar-web/config/InterpolateHtmlPlugin.js b/server/sonar-web/config/InterpolateHtmlPlugin.js
new file mode 100644
index 00000000000..6e318f38e10
--- /dev/null
+++ b/server/sonar-web/config/InterpolateHtmlPlugin.js
@@ -0,0 +1,55 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info 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.
+ */
+
+// Copied from https://github.com/facebook/create-react-app/blob/master/packages/react-dev-utils/InterpolateHtmlPlugin.js
+
+// This Webpack plugin lets us interpolate custom variables into `index.html`.
+// Usage: `new InterpolateHtmlPlugin({ 'MY_VARIABLE': 42 })`
+// Then, you can use %MY_VARIABLE% in your `index.html`.
+
+// It works in tandem with HtmlWebpackPlugin.
+// Learn more about creating plugins like this:
+// https://github.com/ampedandwired/html-webpack-plugin#events
+
+'use strict';
+const escapeStringRegexp = require('escape-string-regexp');
+
+class InterpolateHtmlPlugin {
+ constructor(replacements) {
+ this.replacements = replacements;
+ }
+
+ apply(compiler) {
+ compiler.hooks.compilation.tap('InterpolateHtmlPlugin', compilation => {
+ compilation.hooks.htmlWebpackPluginBeforeHtmlProcessing.tap('InterpolateHtmlPlugin', data => {
+ // Run HTML through a series of user-specified string replacements.
+ Object.keys(this.replacements).forEach(key => {
+ const value = this.replacements[key];
+ data.html = data.html.replace(
+ new RegExp('%' + escapeStringRegexp(key) + '%', 'g'),
+ value
+ );
+ });
+ });
+ });
+ }
+}
+
+module.exports = InterpolateHtmlPlugin;
diff --git a/server/sonar-web/config/paths.js b/server/sonar-web/config/paths.js
index 9bb3c591122..cc9a4f70bf2 100644
--- a/server/sonar-web/config/paths.js
+++ b/server/sonar-web/config/paths.js
@@ -18,42 +18,9 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
const path = require('path');
-const fs = require('fs');
-// Make sure any symlinks in the project folder are resolved:
-// https://github.com/facebookincubator/create-react-app/issues/637
-const appDirectory = fs.realpathSync(process.cwd());
-function resolveApp(relativePath) {
- return path.resolve(appDirectory, relativePath);
-}
-
-// We support resolving modules according to `NODE_PATH`.
-// This lets you use absolute paths in imports inside large monorepos:
-// https://github.com/facebookincubator/create-react-app/issues/253.
-
-// It works similar to `NODE_PATH` in Node itself:
-// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders
-
-// We will export `nodePaths` as an array of absolute paths.
-// It will then be used by Webpack configs.
-// Jest doesn’t need this because it already handles `NODE_PATH` out of the box.
-
-const nodePaths = (process.env.NODE_PATH || '')
- .split(process.platform === 'win32' ? ';' : ':')
- .filter(Boolean)
- .map(resolveApp);
-
-// config after eject: we're in ./config/
module.exports = {
- appBuild: resolveApp('build/webapp'),
- appPublic: resolveApp('public'),
- appHtml: resolveApp('public/index.html'),
- appPackageJson: resolveApp('package.json'),
- appSrc: resolveApp('src/main/js'),
- jsBuild: resolveApp('build/webapp/js'),
- cssBuild: resolveApp('build/webapp/css'),
- htmlBuild: resolveApp('build/webapp/index.html'),
- appNodeModules: resolveApp('node_modules'),
- ownNodeModules: resolveApp('node_modules'),
- nodePaths
+ appBuild: path.join(__dirname, '../build/webapp'),
+ appPublic: path.join(__dirname, '../public'),
+ appHtml: path.join(__dirname, '../public/index.html')
};
diff --git a/server/sonar-web/config/webpack.config.js b/server/sonar-web/config/webpack.config.js
index c112acd4bca..3461d359ecb 100644
--- a/server/sonar-web/config/webpack.config.js
+++ b/server/sonar-web/config/webpack.config.js
@@ -1,20 +1,41 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info 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.
+ */
/* eslint-disable import/no-extraneous-dependencies */
const path = require('path');
-const ExtractTextPlugin = require('extract-text-webpack-plugin');
+const CleanWebpackPlugin = require('clean-webpack-plugin');
+const CopyWebpackPlugin = require('copy-webpack-plugin');
+const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
-const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const webpack = require('webpack');
+const InterpolateHtmlPlugin = require('./InterpolateHtmlPlugin');
const paths = require('./paths');
const cssMinimizeOptions = {
discardComments: { removeAll: true }
};
-const cssLoader = ({ production, fast }) => ({
+const cssLoader = ({ production }) => ({
loader: 'css-loader',
options: {
importLoaders: 1,
- minimize: production && !fast && cssMinimizeOptions,
+ minimize: production && cssMinimizeOptions,
url: false
}
});
@@ -33,35 +54,20 @@ const postcssLoader = () => ({
}
});
-module.exports = ({ production = true, fast = false }) => ({
- bail: production,
-
- devtool: production ? (fast ? false : 'source-map') : 'cheap-module-source-map',
+module.exports = ({ production = true }) => ({
+ mode: production ? 'production' : 'development',
+ devtool: production ? 'source-map' : 'cheap-module-source-map',
resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: ['.ts', '.tsx', '.js', '.json']
},
- entry: {
- vendor: [
- !production && require.resolve('react-dev-utils/webpackHotDevClient'),
- require.resolve('./polyfills'),
- !production && require.resolve('react-error-overlay'),
- 'lodash',
- 'd3-array',
- 'd3-hierarchy',
- 'd3-scale',
- 'd3-selection',
- 'd3-shape',
- 'react',
- 'react-dom'
- ].filter(Boolean),
-
- app: [
- './src/main/js/app/utils/setPublicPath.js',
- './src/main/js/app/index.js',
- './src/main/js/components/SourceViewer/SourceViewer'
- ]
- },
+ entry: [
+ !production && require.resolve('react-dev-utils/webpackHotDevClient'),
+ require.resolve('./polyfills'),
+ !production && require.resolve('react-error-overlay'),
+ './src/main/js/app/utils/setPublicPath.js',
+ './src/main/js/app/index.js'
+ ].filter(Boolean),
output: {
path: paths.appBuild,
pathinfo: !production,
@@ -71,88 +77,71 @@ module.exports = ({ production = true, fast = false }) => ({
module: {
rules: [
{
- test: /\.js$/,
- loader: 'babel-loader',
- exclude: /(node_modules|libs)/
- },
- {
- test: /\.tsx?$/,
+ test: /(\.js$|\.ts(x?)$)/,
+ exclude: /(node_modules|libs)/,
use: [
+ { loader: 'babel-loader' },
{
- loader: 'awesome-typescript-loader',
- options: {
- transpileOnly: true,
- useBabel: true,
- useCache: true
- }
+ loader: 'ts-loader',
+ options: { transpileOnly: true }
}
]
},
- production
- ? {
- test: /\.css$/,
- loader: ExtractTextPlugin.extract({
- fallback: 'style-loader',
- use: [cssLoader({ production, fast }), postcssLoader()]
- })
- }
- : {
- test: /\.css$/,
- use: ['style-loader', cssLoader({ production, fast }), postcssLoader()]
- },
+ {
+ test: /\.css$/,
+ use: [
+ production ? MiniCssExtractPlugin.loader : 'style-loader',
+ cssLoader({ production }),
+ postcssLoader()
+ ].filter(Boolean)
+ },
{ test: require.resolve('lodash'), loader: 'expose-loader?_' },
{ test: require.resolve('react'), loader: 'expose-loader?React' },
{ test: require.resolve('react-dom'), loader: 'expose-loader?ReactDOM' }
].filter(Boolean)
},
plugins: [
- new webpack.optimize.CommonsChunkPlugin({ name: 'vendor' }),
+ // `allowExternal: true` to remove files outside of the current dir
+ production && new CleanWebpackPlugin([paths.appBuild], { allowExternal: true, verbose: false }),
production &&
- new ExtractTextPlugin({
- filename: production ? 'css/sonar.[chunkhash:8].css' : 'css/sonar.css'
- }),
+ new CopyWebpackPlugin([
+ {
+ from: paths.appPublic,
+ to: paths.appBuild,
+ ignore: [paths.appHtml]
+ }
+ ]),
- !production && new InterpolateHtmlPlugin({ WEB_CONTEXT: '' }),
+ production &&
+ new MiniCssExtractPlugin({
+ filename: 'css/[name].[chunkhash:8].css',
+ chunkFilename: 'css/[name].[chunkhash:8].chunk.css'
+ }),
new HtmlWebpackPlugin({
inject: false,
template: paths.appHtml,
- minify: production &&
- !fast && {
- removeComments: true,
- collapseWhitespace: true,
- removeRedundantAttributes: true,
- useShortDoctype: true,
- removeEmptyAttributes: true,
- removeStyleLinkTypeAttributes: true,
- keepClosingSlash: true,
- minifyJS: true,
- minifyCSS: true,
- minifyURLs: true
- }
+ minify: production && {
+ removeComments: true,
+ collapseWhitespace: true,
+ removeRedundantAttributes: true,
+ useShortDoctype: true,
+ removeEmptyAttributes: true,
+ removeStyleLinkTypeAttributes: true,
+ keepClosingSlash: true,
+ minifyJS: true,
+ minifyCSS: true,
+ minifyURLs: true
+ }
}),
- new webpack.DefinePlugin({
- 'process.env.NODE_ENV': JSON.stringify(production ? 'production' : 'development')
- }),
-
- production &&
- !fast &&
- new webpack.optimize.UglifyJsPlugin({
- sourceMap: true,
- compress: { screw_ie8: true, warnings: false },
- mangle: { screw_ie8: true },
- output: { comments: false, screw_ie8: true }
- }),
+ // keep `InterpolateHtmlPlugin` after `HtmlWebpackPlugin`
+ !production && new InterpolateHtmlPlugin({ WEB_CONTEXT: '' }),
!production && new webpack.HotModuleReplacementPlugin()
].filter(Boolean),
- // Some libraries import Node modules but don't use them in the browser.
- // Tell Webpack to provide empty mocks for them so importing them works.
- node: {
- fs: 'empty',
- net: 'empty',
- tls: 'empty'
+ optimization: {
+ splitChunks: { chunks: 'all' }
}
});