You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

webpack.config.js 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2021 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. /* eslint-disable import/no-extraneous-dependencies, complexity */
  21. const path = require('path');
  22. const CleanWebpackPlugin = require('clean-webpack-plugin');
  23. const CopyWebpackPlugin = require('copy-webpack-plugin');
  24. const MiniCssExtractPlugin = require('mini-css-extract-plugin');
  25. const HtmlWebpackPlugin = require('html-webpack-plugin');
  26. const LodashPlugin = require('lodash-webpack-plugin');
  27. const webpack = require('webpack');
  28. const InterpolateHtmlPlugin = require('./InterpolateHtmlPlugin');
  29. const paths = require('./paths');
  30. const utils = require('./utils');
  31. module.exports = ({ production = true, release = false }) => {
  32. const timestamp = Date.now();
  33. const commonConfig = {
  34. mode: production ? 'production' : 'development',
  35. devtool: production && release ? 'source-map' : 'cheap-module-source-map',
  36. resolve: {
  37. // Add '.ts' and '.tsx' as resolvable extensions.
  38. extensions: ['.ts', '.tsx', '.js', '.json'],
  39. // import from 'Docs/foo.md' is rewritten to import from 'sonar-docs/src/foo.md'
  40. alias: {
  41. Docs: path.resolve(__dirname, '../../sonar-docs/src'),
  42. // d3-selection exports an event object, which requires live-binding.
  43. // In order to support this, we need to tell Webpack to NOT look into
  44. // the dist/ folder of this module, but in the src/ folder instead.
  45. // See https://github.com/d3/d3-selection#event
  46. 'd3-selection': path.resolve(__dirname, '../node_modules/d3-selection/src/index.js')
  47. }
  48. },
  49. optimization: {
  50. splitChunks: {
  51. chunks: 'all',
  52. automaticNameDelimiter: '-'
  53. },
  54. minimize: production && release
  55. }
  56. };
  57. const commonRules = [
  58. {
  59. // extract styles from 'app/' into separate file
  60. test: /\.css$/,
  61. include: path.resolve(__dirname, '../src/main/js/app/styles'),
  62. use: [
  63. production ? MiniCssExtractPlugin.loader : 'style-loader',
  64. utils.cssLoader(),
  65. utils.postcssLoader(production)
  66. ]
  67. },
  68. {
  69. // inline all other styles
  70. test: /\.css$/,
  71. exclude: path.resolve(__dirname, '../src/main/js/app/styles'),
  72. use: ['style-loader', utils.cssLoader(), utils.postcssLoader(production)]
  73. },
  74. {
  75. test: /\.md$/,
  76. use: 'raw-loader'
  77. },
  78. { test: require.resolve('react'), loader: 'expose-loader?React' },
  79. { test: require.resolve('react-dom'), loader: 'expose-loader?ReactDOM' },
  80. {
  81. test: /\.directory-loader\.js$/,
  82. loader: path.resolve(__dirname, 'documentation-loader/index.js')
  83. }
  84. ];
  85. const commonPlugins = [
  86. production &&
  87. new MiniCssExtractPlugin({
  88. filename: 'css/[name].[chunkhash:8].css',
  89. chunkFilename: 'css/[name].[chunkhash:8].chunk.css'
  90. }),
  91. new LodashPlugin({
  92. // keep these features
  93. // https://github.com/lodash/lodash-webpack-plugin#feature-sets
  94. shorthands: true,
  95. collections: true,
  96. exotics: true, // used to compare "exotic" values, like dates
  97. memoizing: true,
  98. flattening: true
  99. })
  100. ];
  101. return [
  102. Object.assign({ name: 'modern' }, commonConfig, {
  103. entry: [
  104. !production && require.resolve('react-dev-utils/webpackHotDevClient'),
  105. !production && require.resolve('react-error-overlay'),
  106. './src/main/js/app/utils/setPublicPath.js',
  107. './src/main/js/app/index.ts'
  108. ].filter(Boolean),
  109. output: {
  110. path: paths.appBuild,
  111. pathinfo: !production,
  112. filename: production ? 'js/[name].m.[chunkhash:8].js' : 'js/[name].js',
  113. chunkFilename: production ? 'js/[name].m.[chunkhash:8].chunk.js' : 'js/[name].chunk.js'
  114. },
  115. module: {
  116. rules: [
  117. {
  118. test: /(\.js$|\.ts(x?)$)/,
  119. exclude: /(node_modules|libs)/,
  120. use: [
  121. { loader: 'babel-loader' },
  122. {
  123. loader: 'ts-loader',
  124. options: { transpileOnly: true }
  125. }
  126. ]
  127. },
  128. ...commonRules
  129. ]
  130. },
  131. plugins: [
  132. production && new CleanWebpackPlugin(),
  133. production &&
  134. new CopyWebpackPlugin([
  135. {
  136. from: paths.docImages,
  137. to: paths.appBuild + '/images/embed-doc/images'
  138. }
  139. ]),
  140. production &&
  141. new CopyWebpackPlugin([
  142. {
  143. from: paths.appPublic,
  144. to: paths.appBuild,
  145. ignore: [paths.appHtml]
  146. }
  147. ]),
  148. ...commonPlugins,
  149. new HtmlWebpackPlugin({
  150. inject: false,
  151. template: paths.appHtml,
  152. minify: utils.minifyParams({ production: production && release }),
  153. timestamp
  154. }),
  155. // keep `InterpolateHtmlPlugin` after `HtmlWebpackPlugin`
  156. !production &&
  157. new InterpolateHtmlPlugin({
  158. WEB_CONTEXT: process.env.WEB_CONTEXT || '',
  159. SERVER_STATUS: process.env.SERVER_STATUS || 'UP',
  160. INSTANCE: process.env.INSTANCE || 'SonarQube',
  161. OFFICIAL: process.env.OFFICIAL || 'true'
  162. }),
  163. !production && new webpack.HotModuleReplacementPlugin()
  164. ].filter(Boolean),
  165. performance:
  166. production && release
  167. ? {
  168. // ignore source maps and documentation chunk
  169. assetFilter: assetFilename =>
  170. !assetFilename.endsWith('.map') && !assetFilename.startsWith('js/docs'),
  171. maxAssetSize: 400000,
  172. hints: 'error'
  173. }
  174. : undefined
  175. })
  176. ];
  177. };