diff options
author | Stas Vilchik <stas.vilchik@sonarsource.com> | 2018-03-22 11:48:45 +0100 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2018-03-22 12:37:52 +0100 |
commit | df91a4ec347ba6e27184c6ea1117c226560fd3d0 (patch) | |
tree | 626d6ea2b5ac39c6d40f93da87600874d73ce5c0 /server/sonar-web/config | |
parent | 8da037d336f42543ef35d146be0adebea8928a6e (diff) | |
download | sonarqube-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.js | 55 | ||||
-rw-r--r-- | server/sonar-web/config/paths.js | 39 | ||||
-rw-r--r-- | server/sonar-web/config/webpack.config.js | 167 |
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' } } }); |