diff --git a/ui/v2.5/config/webpack.dev.js b/ui/v2.5/config/webpack.dev.js index 76835b6ef..030cd8153 100644 --- a/ui/v2.5/config/webpack.dev.js +++ b/ui/v2.5/config/webpack.dev.js @@ -8,7 +8,27 @@ module.exports = merge(commonConfig, { entry: [ './src/index.tsx' // the entry point of our app ], + output: { + filename: 'static/js/bundle.js', + chunkFilename: 'static/js/[name].chunk.js', + }, + optimization: { + // Automatically split vendor and commons + // https://twitter.com/wSokra/status/969633336732905474 + // https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366 + splitChunks: { + chunks: 'all', + name: false, + }, + // Keep the runtime chunk separated to enable long term caching + // https://twitter.com/wSokra/status/969679223278505985 + // https://github.com/facebook/create-react-app/issues/5358 + runtimeChunk: { + name: entrypoint => `runtime-${entrypoint.name}`, + }, + }, devServer: { + compress: true, host: '0.0.0.0', hot: true, // enable HMR on the server host: '0.0.0.0', port: process.env.PORT, diff --git a/ui/v2.5/config/webpack.prod.js b/ui/v2.5/config/webpack.prod.js index 15160140a..067747009 100644 --- a/ui/v2.5/config/webpack.prod.js +++ b/ui/v2.5/config/webpack.prod.js @@ -1,6 +1,9 @@ // production config const merge = require('webpack-merge'); const {resolve} = require('path'); +const TerserPlugin = require('terser-webpack-plugin'); +const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); +const safePostCssParser = require('postcss-safe-parser'); const commonConfig = require('./webpack.common'); @@ -8,10 +11,84 @@ module.exports = merge(commonConfig, { mode: 'production', entry: './src/index.tsx', output: { - filename: 'static/js/bundle.[hash].min.js', + filename: 'static/js/[name].[contenthash:8].js', + chunkFilename: 'static/js/[name].[contenthash:8].chunk.js', path: resolve(__dirname, '../build'), publicPath: '/', }, + optimization: { + minimize: true, + minimizer: [ + // This is only used in production mode + new TerserPlugin({ + terserOptions: { + parse: { + // We want terser to parse ecma 8 code. However, we don't want it + // to apply any minification steps that turns valid ecma 5 code + // into invalid ecma 5 code. This is why the 'compress' and 'output' + // sections only apply transformations that are ecma 5 safe + // https://github.com/facebook/create-react-app/pull/4234 + ecma: 8, + }, + compress: { + ecma: 5, + warnings: false, + // Disabled because of an issue with Uglify breaking seemingly valid code: + // https://github.com/facebook/create-react-app/issues/2376 + // Pending further investigation: + // https://github.com/mishoo/UglifyJS2/issues/2011 + comparisons: false, + // Disabled because of an issue with Terser breaking valid code: + // https://github.com/facebook/create-react-app/issues/5250 + // Pending further investigation: + // https://github.com/terser-js/terser/issues/120 + inline: 2, + }, + mangle: { + safari10: true, + }, + // Added for profiling in devtools + keep_classnames: true, + keep_fnames: true, + output: { + ecma: 5, + comments: false, + // Turned on because emoji and regex is not minified properly using default + // https://github.com/facebook/create-react-app/issues/2488 + ascii_only: true, + }, + }, + sourceMap: true, + }), + // This is only used in production mode + new OptimizeCSSAssetsPlugin({ + cssProcessorOptions: { + parser: safePostCssParser, + map: { + // `inline: false` forces the sourcemap to be output into a + // separate file + inline: false, + // `annotation: true` appends the sourceMappingURL to the end of + // the css file, helping the browser find the sourcemap + annotation: true, + } + }, + }), + ], + // Automatically split vendor and commons + // https://twitter.com/wSokra/status/969633336732905474 + // https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366 + splitChunks: { + chunks: 'all', + name: false, + }, + // Keep the runtime chunk separated to enable long term caching + // https://twitter.com/wSokra/status/969679223278505985 + // https://github.com/facebook/create-react-app/issues/5358 + runtimeChunk: { + name: entrypoint => `runtime-${entrypoint.name}`, + }, + }, devtool: 'source-map', plugins: [], }); diff --git a/ui/v2.5/package.json b/ui/v2.5/package.json index 0112b7d05..0a1f9c222 100644 --- a/ui/v2.5/package.json +++ b/ui/v2.5/package.json @@ -2,6 +2,7 @@ "name": "stash", "version": "0.1.0", "private": true, + "sideEffects": false, "scripts": { "start": "yarn run start-dev", "start-dev": "webpack-dev-server --config=config/webpack.dev.js", @@ -104,7 +105,8 @@ "jest-watch-typeahead": "0.4.2", "mini-css-extract-plugin": "0.8.0", "node-sass": "4.13.1", - "optimize-css-assets-webpack-plugin": "5.0.3", + "optimize-css-assets-webpack-plugin": "^5.0.3", + "postcss-safe-parser": "^4.0.1", "prettier": "1.19.1", "react-hot-loader": "^4.12.19", "sass-loader": "8.0.0", @@ -112,7 +114,7 @@ "style-loader": "1.0.0", "stylelint": "^13.0.0", "stylelint-order": "^4.0.0", - "terser-webpack-plugin": "2.2.1", + "terser-webpack-plugin": "^2.3.2", "ts-loader": "^6.2.1", "typescript": "~3.7.4", "webpack": "4.41.2", diff --git a/ui/v2.5/yarn.lock b/ui/v2.5/yarn.lock index efa4d620f..463466477 100644 --- a/ui/v2.5/yarn.lock +++ b/ui/v2.5/yarn.lock @@ -5698,7 +5698,7 @@ find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: make-dir "^2.0.0" pkg-dir "^3.0.0" -find-cache-dir@^3.0.0: +find-cache-dir@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.2.0.tgz#e7fe44c1abc1299f516146e563108fd1006c1874" integrity sha512-1JKclkYYsf1q9WIJKLZa9S9muC+08RIjzAlLrK4QcYLJMS6mk9yombQ9qf+zJ7H9LS800k0s44L4sDq9VYzqyg== @@ -9430,7 +9430,7 @@ optimism@^0.10.0: dependencies: "@wry/context" "^0.4.0" -optimize-css-assets-webpack-plugin@5.0.3: +optimize-css-assets-webpack-plugin@^5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.3.tgz#e2f1d4d94ad8c0af8967ebd7cf138dcb1ef14572" integrity sha512-q9fbvCRS6EYtUKKSwI87qm2IxlyJK5b4dygW1rKUBT6mMDhdG5e5bZT63v6tnJR9F9FB/H5a0HTmtw+laUBxKA== @@ -11584,6 +11584,14 @@ schema-utils@^2.0.0, schema-utils@^2.0.1, schema-utils@^2.1.0, schema-utils@^2.5 ajv "^6.10.2" ajv-keywords "^3.4.1" +schema-utils@^2.6.1: + version "2.6.4" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.4.tgz#a27efbf6e4e78689d91872ee3ccfa57d7bdd0f53" + integrity sha512-VNjcaUxVnEeun6B2fiiUDjXXBtD4ZSH7pdbfIu1pOFwgptDPLMo/z9jr4sUfsjFVPqDCEin/F7IYlq7/E6yDbQ== + dependencies: + ajv "^6.10.2" + ajv-keywords "^3.4.1" + scss-tokenizer@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" @@ -11653,7 +11661,7 @@ send@0.17.1: range-parser "~1.2.1" statuses "~1.5.0" -serialize-javascript@^2.1.0, serialize-javascript@^2.1.2: +serialize-javascript@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== @@ -12499,20 +12507,6 @@ terminal-link@^2.0.0: ansi-escapes "^4.2.1" supports-hyperlinks "^2.0.0" -terser-webpack-plugin@2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.2.1.tgz#5569e6c7d8be79e5e43d6da23acc3b6ba77d22bd" - integrity sha512-jwdauV5Al7zopR6OAYvIIRcxXCSvLjZjr7uZE8l2tIWb/ryrGN48sJftqGf5k9z09tWhajx53ldp0XPI080YnA== - dependencies: - cacache "^13.0.1" - find-cache-dir "^3.0.0" - jest-worker "^24.9.0" - schema-utils "^2.5.0" - serialize-javascript "^2.1.0" - source-map "^0.6.1" - terser "^4.3.9" - webpack-sources "^1.4.3" - terser-webpack-plugin@^1.4.1: version "1.4.3" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz#5ecaf2dbdc5fb99745fd06791f46fc9ddb1c9a7c" @@ -12528,7 +12522,21 @@ terser-webpack-plugin@^1.4.1: webpack-sources "^1.4.0" worker-farm "^1.7.0" -terser@^4.1.2, terser@^4.3.9: +terser-webpack-plugin@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.2.tgz#6d3d1b0590c8f729bfbaeb7fb2528b8b62db4c74" + integrity sha512-SmvB/6gtEPv+CJ88MH5zDOsZdKXPS/Uzv2//e90+wM1IHFUhsguPKEILgzqrM1nQ4acRXN/SV4Obr55SXC+0oA== + dependencies: + cacache "^13.0.1" + find-cache-dir "^3.2.0" + jest-worker "^24.9.0" + schema-utils "^2.6.1" + serialize-javascript "^2.1.2" + source-map "^0.6.1" + terser "^4.4.3" + webpack-sources "^1.4.3" + +terser@^4.1.2: version "4.5.0" resolved "https://registry.yarnpkg.com/terser/-/terser-4.5.0.tgz#c93504b3235bd3409dade19c97ed2c185a96ac76" integrity sha512-UEocwHeNeGFbZ2wHJSidpYu4pkEoRI/tyrjWjGYBL8P3MwKsAtprK5ZbHX1MopkHkTSDm6g6vscLxITFMyE3bw== @@ -12537,6 +12545,15 @@ terser@^4.1.2, terser@^4.3.9: source-map "~0.6.1" source-map-support "~0.5.12" +terser@^4.4.3: + version "4.6.3" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.3.tgz#e33aa42461ced5238d352d2df2a67f21921f8d87" + integrity sha512-Lw+ieAXmY69d09IIc/yqeBqXpEQIpDGZqT34ui1QWXIUpR2RjbqEkT8X7Lgex19hslSqcWM5iMN2kM11eMsESQ== + dependencies: + commander "^2.20.0" + source-map "~0.6.1" + source-map-support "~0.5.12" + test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e"