webpack.config.prod.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. const fs = require('fs')
  2. const merge = require('webpack-merge')
  3. const TerserPlugin = require('terser-webpack-plugin')
  4. const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
  5. const MiniCssExtractPlugin = require('mini-css-extract-plugin')
  6. const SentryPlugin = require('@sentry/webpack-plugin')
  7. const RemoveFilesPlugin = require('remove-files-webpack-plugin')
  8. const base = require('./webpack.config')
  9. // Use "smart" merge: attempts to combine loaders targeting the same file type,
  10. // overriding the base config
  11. module.exports = merge.smart(
  12. base,
  13. {
  14. mode: 'production',
  15. // Enable a full source map. Generates a comment linking to the source map
  16. devtool: 'source-map',
  17. output: {
  18. // Override filename to include hash for immutable caching
  19. filename: 'js/[name]-[chunkhash].js'
  20. },
  21. module: {
  22. rules: [
  23. {
  24. // Override base font loading to add hash to filename so that we can
  25. // use "immutable" caching
  26. test: /\.(woff|woff2)$/,
  27. use: [
  28. {
  29. loader: 'file-loader',
  30. options: {
  31. outputPath: 'fonts',
  32. publicPath: '/fonts/',
  33. name: '[name]-[hash].[ext]'
  34. }
  35. }
  36. ]
  37. }
  38. ]
  39. },
  40. optimization: {
  41. // Minify JS (with Terser) and CSS (with cssnano)
  42. minimizer: [new TerserPlugin(), new OptimizeCssAssetsPlugin()]
  43. },
  44. plugins: [
  45. // Extract CSS to a separate file (rather than inlining to a <style> tag)
  46. new MiniCssExtractPlugin({
  47. // Output to public/stylesheets directory and append hash for immutable
  48. // caching
  49. filename: 'stylesheets/[name]-[chunkhash].css'
  50. })
  51. ]
  52. },
  53. // Conditionally merge in Sentry plugins
  54. generateSentryConfig()
  55. )
  56. /*
  57. * If Sentry secrets file exists, then configure SentryPlugin to upload source
  58. * maps to Sentry
  59. */
  60. function generateSentryConfig() {
  61. // Only upload if the Sentry secrets file is available and on master branch
  62. if (
  63. fs.existsSync('./.sentryclirc') &&
  64. process.env['BRANCH_NAME'] === 'master'
  65. ) {
  66. console.log('Sentry secrets file found. Uploading source maps to Sentry')
  67. return {
  68. plugins: [
  69. new SentryPlugin({
  70. release: process.env['SENTRY_RELEASE'],
  71. include: './public/js',
  72. ignore: ['ace-1.4.5', 'cmaps', 'libs']
  73. }),
  74. // After uploading source maps to Sentry, delete them. Some of the
  75. // source maps are of proprietary code and so we don't want to make them
  76. // publicly available
  77. new RemoveFilesPlugin({
  78. after: {
  79. test: [
  80. {
  81. folder: './public/js',
  82. method: filePath => /\.map$/.test(filePath)
  83. }
  84. ]
  85. }
  86. })
  87. ]
  88. }
  89. } else {
  90. console.log(
  91. 'Sentry secrets file not found. NOT uploading source maps to Sentry'
  92. )
  93. return {}
  94. }
  95. }