production.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // Note: You must restart bin/webpack-dev-server for changes to take effect
  2. const webpack = require('webpack');
  3. const merge = require('webpack-merge');
  4. const CompressionPlugin = require('compression-webpack-plugin');
  5. const sharedConfig = require('./shared.js');
  6. const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
  7. const OfflinePlugin = require('offline-plugin');
  8. const { publicPath } = require('./configuration.js');
  9. const path = require('path');
  10. let compressionAlgorithm;
  11. try {
  12. const zopfli = require('node-zopfli');
  13. compressionAlgorithm = (content, options, fn) => {
  14. zopfli.gzip(content, options, fn);
  15. };
  16. } catch (error) {
  17. compressionAlgorithm = 'gzip';
  18. }
  19. module.exports = merge(sharedConfig, {
  20. output: {
  21. filename: '[name]-[chunkhash].js',
  22. chunkFilename: '[name]-[chunkhash].js',
  23. },
  24. devtool: 'source-map', // separate sourcemap file, suitable for production
  25. stats: 'normal',
  26. plugins: [
  27. new webpack.optimize.UglifyJsPlugin({
  28. sourceMap: true,
  29. mangle: true,
  30. compress: {
  31. warnings: false,
  32. },
  33. output: {
  34. comments: false,
  35. },
  36. }),
  37. new CompressionPlugin({
  38. asset: '[path].gz[query]',
  39. algorithm: compressionAlgorithm,
  40. test: /\.(js|css|html|json|ico|svg|eot|otf|ttf)$/,
  41. }),
  42. new BundleAnalyzerPlugin({ // generates report.html and stats.json
  43. analyzerMode: 'static',
  44. generateStatsFile: true,
  45. statsOptions: {
  46. // allows usage with http://chrisbateman.github.io/webpack-visualizer/
  47. chunkModules: true,
  48. },
  49. openAnalyzer: false,
  50. logLevel: 'silent', // do not bother Webpacker, who runs with --json and parses stdout
  51. }),
  52. new OfflinePlugin({
  53. publicPath: publicPath, // sw.js must be served from the root to avoid scope issues
  54. caches: {
  55. main: [':rest:'],
  56. additional: [':externals:'],
  57. optional: [
  58. '**/locale_*.js', // don't fetch every locale; the user only needs one
  59. '**/*_polyfills-*.js', // the user may not need polyfills
  60. '**/*.woff2', // the user may have system-fonts enabled
  61. // images/audio can be cached on-demand
  62. '**/*.png',
  63. '**/*.jpg',
  64. '**/*.jpeg',
  65. '**/*.svg',
  66. '**/*.mp3',
  67. '**/*.ogg',
  68. ],
  69. },
  70. externals: [
  71. '/emoji/1f602.svg', // used for emoji picker dropdown
  72. '/emoji/sheet.png', // used in emoji-mart
  73. ],
  74. excludes: [
  75. '**/*.gz',
  76. '**/*.map',
  77. 'stats.json',
  78. 'report.html',
  79. // any browser that supports ServiceWorker will support woff2
  80. '**/*.eot',
  81. '**/*.ttf',
  82. '**/*-webfont-*.svg',
  83. '**/*.woff',
  84. ],
  85. ServiceWorker: {
  86. entry: `imports-loader?process.env=>${encodeURIComponent(JSON.stringify(process.env))}!${encodeURI(path.join(__dirname, '../../app/javascript/mastodon/service_worker/entry.js'))}`,
  87. cacheName: 'mastodon',
  88. output: '../assets/sw.js',
  89. publicPath: '/sw.js',
  90. minify: true,
  91. },
  92. }),
  93. ],
  94. });