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.

174 lines
4.4 KiB

  1. const cssnano = require('cssnano');
  2. const fastGlob = require('fast-glob');
  3. const FixStyleOnlyEntriesPlugin = require('webpack-fix-style-only-entries');
  4. const MiniCssExtractPlugin = require('mini-css-extract-plugin');
  5. const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
  6. const PostCSSPresetEnv = require('postcss-preset-env');
  7. const PostCSSSafeParser = require('postcss-safe-parser');
  8. const TerserPlugin = require('terser-webpack-plugin');
  9. const VueLoaderPlugin = require('vue-loader/lib/plugin');
  10. const { statSync } = require('fs');
  11. const { resolve, parse } = require('path');
  12. const { SourceMapDevToolPlugin } = require('webpack');
  13. const themes = {};
  14. for (const path of fastGlob.sync(resolve(__dirname, 'web_src/less/themes/*.less'))) {
  15. themes[parse(path).name] = [path];
  16. }
  17. module.exports = {
  18. mode: 'production',
  19. entry: {
  20. index: [
  21. resolve(__dirname, 'web_src/js/index.js'),
  22. resolve(__dirname, 'web_src/less/index.less'),
  23. ],
  24. swagger: [
  25. resolve(__dirname, 'web_src/js/swagger.js'),
  26. ],
  27. jquery: [
  28. resolve(__dirname, 'web_src/js/jquery.js'),
  29. ],
  30. ...themes,
  31. },
  32. devtool: false,
  33. output: {
  34. path: resolve(__dirname, 'public'),
  35. filename: 'js/[name].js',
  36. chunkFilename: 'js/[name].js',
  37. },
  38. optimization: {
  39. minimize: true,
  40. minimizer: [
  41. new TerserPlugin({
  42. sourceMap: true,
  43. extractComments: false,
  44. terserOptions: {
  45. output: {
  46. comments: false,
  47. },
  48. },
  49. }),
  50. new OptimizeCSSAssetsPlugin({
  51. cssProcessor: cssnano,
  52. cssProcessorOptions: {
  53. parser: PostCSSSafeParser,
  54. },
  55. cssProcessorPluginOptions: {
  56. preset: [
  57. 'default',
  58. {
  59. discardComments: {
  60. removeAll: true,
  61. },
  62. },
  63. ],
  64. },
  65. }),
  66. ],
  67. splitChunks: {
  68. chunks: 'async',
  69. name: (_, chunks) => chunks.map((item) => item.name).join('-'),
  70. }
  71. },
  72. module: {
  73. rules: [
  74. {
  75. test: /\.vue$/,
  76. exclude: /node_modules/,
  77. loader: 'vue-loader',
  78. },
  79. {
  80. test: /\.js$/,
  81. exclude: /node_modules/,
  82. use: [
  83. {
  84. loader: 'babel-loader',
  85. options: {
  86. cacheDirectory: true,
  87. cacheCompression: false,
  88. cacheIdentifier: [
  89. resolve(__dirname, 'package.json'),
  90. resolve(__dirname, 'package-lock.json'),
  91. resolve(__dirname, 'webpack.config.js'),
  92. ].map((path) => statSync(path).mtime.getTime()).join(':'),
  93. presets: [
  94. [
  95. '@babel/preset-env',
  96. {
  97. useBuiltIns: 'usage',
  98. corejs: 3,
  99. },
  100. ],
  101. ],
  102. plugins: [
  103. [
  104. '@babel/plugin-transform-runtime',
  105. {
  106. regenerator: true,
  107. }
  108. ],
  109. '@babel/plugin-proposal-object-rest-spread',
  110. ],
  111. },
  112. },
  113. ],
  114. },
  115. {
  116. test: /\.(less|css)$/i,
  117. use: [
  118. {
  119. loader: MiniCssExtractPlugin.loader,
  120. },
  121. {
  122. loader: 'css-loader',
  123. options: {
  124. importLoaders: 2,
  125. url: false,
  126. }
  127. },
  128. {
  129. loader: 'postcss-loader',
  130. options: {
  131. plugins: () => [
  132. PostCSSPresetEnv(),
  133. ],
  134. },
  135. },
  136. {
  137. loader: 'less-loader',
  138. },
  139. ],
  140. },
  141. ],
  142. },
  143. plugins: [
  144. new VueLoaderPlugin(),
  145. // needed so themes don't generate useless js files
  146. new FixStyleOnlyEntriesPlugin({
  147. silent: true,
  148. }),
  149. new MiniCssExtractPlugin({
  150. filename: 'css/[name].css',
  151. chunkFilename: 'css/[name].css',
  152. }),
  153. new SourceMapDevToolPlugin({
  154. filename: 'js/[name].js.map',
  155. include: [
  156. 'js/index.js',
  157. ],
  158. }),
  159. ],
  160. performance: {
  161. maxEntrypointSize: 512000,
  162. maxAssetSize: 512000,
  163. assetFilter: (filename) => {
  164. if (filename.endsWith('.map')) return false;
  165. if (['js/swagger.js', 'js/highlight.js'].includes(filename)) return false;
  166. return true;
  167. },
  168. },
  169. resolve: {
  170. symlinks: false,
  171. },
  172. };