webpack.config.prod.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. const webpack = require('webpack');
  2. const HtmlWebpackPlugin = require('html-webpack-plugin');
  3. const MiniCssExtractPlugin = require('mini-css-extract-plugin');
  4. const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
  5. const OfflinePlugin = require('offline-plugin');
  6. const TerserPlugin = require('terser-webpack-plugin');
  7. const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
  8. const WebpackPwaManifest = require('webpack-pwa-manifest');
  9. const CompressionPlugin = require('compression-webpack-plugin');
  10. const WebpackPluginFrTheme = require('webpack-plugin-fr-theme');
  11. const { HashedModuleIdsPlugin } = require('webpack');
  12. const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
  13. const { CleanWebpackPlugin } = require('clean-webpack-plugin');
  14. const CopyWebpackPlugin = require('copy-webpack-plugin');
  15. const ProgressBarPlugin = require('progress-bar-webpack-plugin');
  16. const paths = require('./paths');
  17. const getClientEnvironment = require('./env');
  18. const loaders = require('./loader.prod');
  19. const publicPath = paths.servedPath;
  20. const publicUrl = publicPath.slice(0, -1);
  21. const env = getClientEnvironment(publicUrl);
  22. if (env.stringified['process.env'].NODE_ENV !== '"production"') {
  23. throw new Error('生产环境编译,必须设定环境变量为 NODE_ENV=production.');
  24. }
  25. module.exports = {
  26. mode: 'production',
  27. // build遇到错误,中止build
  28. bail: true,
  29. target: 'web',
  30. entry: [require.resolve('react-app-polyfill/ie11'), paths.appIndexJs],
  31. output: {
  32. path: paths.appBuild,
  33. pathinfo: true,
  34. publicPath: '',
  35. filename: 'assets/js/[name].[hash].js',
  36. sourceMapFilename: 'assets/js/[name].[hash].map',
  37. chunkFilename: 'assets/js/[name].[chunkhash].chunk.js',
  38. },
  39. resolve: {
  40. modules: [paths.appSrc, paths.appNodeModules],
  41. extensions: ['.jsx', '.js', '.scss', '.css', '.json'],
  42. alias: {
  43. '@': paths.appSrc,
  44. },
  45. plugins: [
  46. // 阻止从src和node_modules目录之外导入模块
  47. new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
  48. ],
  49. },
  50. optimization: {
  51. nodeEnv: 'production',
  52. sideEffects: true,
  53. noEmitOnErrors: true,
  54. runtimeChunk: true,
  55. minimize: true,
  56. minimizer: [
  57. new TerserPlugin({
  58. terserOptions: {
  59. warnings: false,
  60. parse: {},
  61. compress: {
  62. ecma: 5,
  63. warnings: false,
  64. comparisons: false,
  65. inline: 2,
  66. },
  67. mangle: true,
  68. output: {
  69. ecma: 5,
  70. comments: false,
  71. ascii_only: true,
  72. },
  73. },
  74. parallel: true,
  75. cache: true,
  76. sourceMap: true,
  77. }),
  78. new OptimizeCSSAssetsPlugin(),
  79. ],
  80. splitChunks: {
  81. chunks: 'async', // 必须三选一: "initial直接引入" | "all"(默认就是all)全部 | "async动态引入"
  82. minSize: 30000, // 最小尺寸,默认0
  83. minChunks: 1, // 最小 chunk ,默认1
  84. maxAsyncRequests: 5, // 最大异步请求数, 默认1
  85. maxInitialRequests: 3, // 最大初始化请求书,默认1
  86. name: false,
  87. cacheGroups: {
  88. vendor: {
  89. name: 'vendor',
  90. test: /[\\/]node_modules[\\/]/,
  91. chunks: 'all',
  92. },
  93. otherBase: {
  94. test: module =>
  95. /@ant-design|swagger-ui-react|react|prop-types|antd|recharts|lodash|react-quill/.test(module.context), // 直接使用 test 来做路径匹配,抽离react相关代码
  96. chunks: 'all',
  97. name: 'otherBase',
  98. priority: 10,
  99. },
  100. // styles: {
  101. // name: 'styles',
  102. // test: /\.(scss|css|less)$/,
  103. // chunks: 'all',
  104. // enforce: true,
  105. // },
  106. },
  107. },
  108. },
  109. module: {
  110. // 缺少exports,报错而不是警告
  111. strictExportPresence: true,
  112. rules: [
  113. loaders.jsLoader,
  114. {
  115. oneOf: [
  116. loaders.cssLoaderRule,
  117. loaders.scssLoaderRule,
  118. loaders.lessLoaderRule,
  119. loaders.svgSpriteLoader,
  120. loaders.fontWoffLoader,
  121. loaders.fontTtfLoader,
  122. loaders.imageLoader,
  123. loaders.mediaLoader,
  124. loaders.otherLoader,
  125. ],
  126. },
  127. ],
  128. },
  129. performance: {
  130. hints: false,
  131. },
  132. plugins: [
  133. // new ProgressBarPlugin(),
  134. new WebpackPluginFrTheme(),
  135. new webpack.DefinePlugin(env.stringified),
  136. new webpack.NamedModulesPlugin(),
  137. new webpack.optimize.ModuleConcatenationPlugin(),
  138. new webpack.optimize.OccurrenceOrderPlugin(true),
  139. new MiniCssExtractPlugin({
  140. filename: 'assets/css/app.[name].css',
  141. chunkFilename: 'assets/css/app.[contenthash:12].css',
  142. }),
  143. new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /en-gb|zh-cn/),
  144. new CopyWebpackPlugin([
  145. {
  146. from: paths.appPublic,
  147. to: paths.appBuild,
  148. },
  149. ]),
  150. new HtmlWebpackPlugin({
  151. inject: true,
  152. template: paths.appHtml,
  153. sourceMap: true,
  154. minify: {
  155. removeComments: true,
  156. collapseWhitespace: true,
  157. removeRedundantAttributes: true,
  158. useShortDoctype: true,
  159. removeEmptyAttributes: true,
  160. removeStyleLinkTypeAttributes: true,
  161. keepClosingSlash: true,
  162. minifyJS: true,
  163. minifyCSS: true,
  164. minifyURLs: true,
  165. },
  166. }),
  167. new CleanWebpackPlugin(),
  168. new CompressionPlugin({
  169. algorithm: 'gzip',
  170. test: /\.js$|\.css$|\.html$/,
  171. threshold: 10240,
  172. minRatio: 0.8,
  173. }),
  174. new WebpackPwaManifest({
  175. name: 'AISware AI²',
  176. short_name: 'AISquare',
  177. description: '通用人工智能平台',
  178. background_color: '#fafafa',
  179. theme_color: '#b1624d',
  180. inject: true,
  181. ios: false,
  182. }),
  183. new HashedModuleIdsPlugin({
  184. hashFunction: 'sha256',
  185. hashDigest: 'hex',
  186. hashDigestLength: 20,
  187. }),
  188. new OfflinePlugin({
  189. relativePaths: true,
  190. appShell: '/',
  191. caches: 'all',
  192. AppCache: false,
  193. updateStrategy: 'changed',
  194. safeToUseOptionalCaches: true,
  195. ServiceWorker: {
  196. output: 'assets/js/sw.js',
  197. publicPath: 'assets/js',
  198. minify: true,
  199. events: true,
  200. },
  201. }),
  202. //new BundleAnalyzerPlugin(),
  203. ],
  204. };