From e94892f584d912883beb8e3feca55941366daee4 Mon Sep 17 00:00:00 2001 From: Shawn Date: Tue, 26 Mar 2019 23:40:02 -0500 Subject: [PATCH] Initial lazy-load and code-splitting --- .babelrc | 2 +- package.json | 5 +- src/platforms/electron/installDevtools.js | 4 - src/ui/component/common/icon.jsx | 34 ++++- src/ui/component/fileRender/view.jsx | 13 +- src/ui/component/transactionList/view.jsx | 1 + src/ui/component/viewers/audioVideoViewer.jsx | 19 ++- src/ui/component/viewers/codeViewer.jsx | 39 +++--- src/ui/component/viewers/documentViewer.jsx | 8 +- webpack.base.config.js | 20 ++- yarn.lock | 116 ++++++++++++++++-- 11 files changed, 215 insertions(+), 46 deletions(-) diff --git a/.babelrc b/.babelrc index df5b644aa..132333597 100644 --- a/.babelrc +++ b/.babelrc @@ -1,10 +1,10 @@ { "presets": ["@babel/react", "@babel/flow"], "plugins": [ + "@babel/plugin-syntax-dynamic-import", "react-hot-loader/babel", ["@babel/plugin-proposal-decorators", { "decoratorsBeforeExport": true }], "@babel/plugin-transform-flow-strip-types", "@babel/plugin-proposal-class-properties", - "babel-plugin-add-module-exports" ] } diff --git a/package.json b/package.json index 9c0a1f78c..630656cf5 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,6 @@ "dev:electron": "cross-env NODE_ENV=development node ./src/platforms/electron/devServer.js", "dev:web": "webpack-dev-server --open --hot --progress --config webpack.web.config.js", "dev:internal-apis": "LBRY_API_URL='http://localhost:9090' yarn dev:electron", - "run:electron": "electron ./dist/electron/main.js", "run:web": "cross-env NODE_ENV=production yarn compile:web && node ./dist/web/server.js", "pack": "electron-builder --dir", "dist": "electron-builder", @@ -51,6 +50,7 @@ "@babel/core": "^7.0.0", "@babel/plugin-proposal-class-properties": "^7.0.0", "@babel/plugin-proposal-decorators": "^7.3.0", + "@babel/plugin-syntax-dynamic-import": "^7.2.0", "@babel/plugin-transform-flow-strip-types": "^7.2.3", "@babel/polyfill": "^7.2.5", "@babel/preset-flow": "^7.0.0", @@ -137,6 +137,7 @@ "react-redux": "^5.0.3", "react-simplemde-editor": "^4.0.0", "react-toggle": "^4.0.2", + "react-virtualized": "^9.21.0", "redux": "^3.6.0", "redux-persist": "^4.8.0", "redux-persist-transform-compress": "^4.2.0", @@ -151,11 +152,13 @@ "semver": "^5.3.0", "stream-to-blob-url": "^2.1.1", "style-loader": "^0.23.1", + "terser-webpack-plugin": "^1.2.3", "three": "^0.93.0", "three-full": "^11.3.2", "tree-kill": "^1.1.0", "video.js": "^7.2.2", "webpack": "^4.28.4", + "webpack-bundle-analyzer": "^3.1.0", "webpack-config-utils": "^2.3.1", "webpack-dev-middleware": "^3.6.0", "webpack-dev-server": "^3.1.14", diff --git a/src/platforms/electron/installDevtools.js b/src/platforms/electron/installDevtools.js index 1de13251a..c9e3bc978 100644 --- a/src/platforms/electron/installDevtools.js +++ b/src/platforms/electron/installDevtools.js @@ -3,7 +3,6 @@ export default async function installDevtools() { default: installExtension, REACT_DEVELOPER_TOOLS, REDUX_DEVTOOLS, - REACT_PERF, } = require('electron-devtools-installer'); await installExtension(REACT_DEVELOPER_TOOLS) @@ -14,7 +13,4 @@ export default async function installDevtools() { .then(name => console.log(`Added Extension: ${name}`)) .catch(err => console.log('An error occurred: ', err)); - await installExtension(REACT_PERF) - .then(name => console.log(`Added Extension: ${name}`)) - .catch(err => console.log('An error occurred: ', err)); } diff --git a/src/ui/component/common/icon.jsx b/src/ui/component/common/icon.jsx index 0ad65080f..4bd03fb34 100644 --- a/src/ui/component/common/icon.jsx +++ b/src/ui/component/common/icon.jsx @@ -1,10 +1,29 @@ // @flow import * as ICONS from 'constants/icons'; import React from 'react'; -import * as FeatherIcons from 'react-feather'; import Tooltip from 'component/common/tooltip'; import { customIcons } from './icon-custom'; +let featherIcons = false; +const featherIconsPromise = import(/* webpackChunkName: "react-feather" */ +/* webpackPrefetch: true */ +'react-feather').then(result => (featherIcons = result)); + +const LazyFeatherIcons = new Proxy( + {}, + { + get(target, name) { + if (featherIcons) { + return featherIcons[name]; + } + + return React.lazy(() => + featherIconsPromise.then(featherIcons => ({ default: featherIcons[name] })) + ); + }, + } +); + // It would be nice to standardize this somehow // These are copied from `scss/vars`, can they both come from the same source? const RED_COLOR = '#e2495e'; @@ -45,9 +64,8 @@ class IconComponent extends React.PureComponent { render() { const { icon, tooltip, iconColor, size } = this.props; - const Icon = customIcons[this.props.icon] || FeatherIcons[this.props.icon]; - console.log('icon', icon); - console.log('Icon', Icon); + const Icon = customIcons[this.props.icon] || LazyFeatherIcons[this.props.icon]; + if (!Icon) { return null; } @@ -63,7 +81,13 @@ class IconComponent extends React.PureComponent { if (tooltip) { tooltipText = this.getTooltip(icon); } - const inner = ; + const inner = ( + } + > + + + ); return tooltipText ? ( diff --git a/src/ui/component/fileRender/view.jsx b/src/ui/component/fileRender/view.jsx index 2f9ec6af0..fa125fcde 100644 --- a/src/ui/component/fileRender/view.jsx +++ b/src/ui/component/fileRender/view.jsx @@ -9,7 +9,10 @@ import DocxViewer from 'component/viewers/docxViewer'; import HtmlViewer from 'component/viewers/htmlViewer'; import AudioVideoViewer from 'component/viewers/audioVideoViewer'; // @if TARGET='app' -import ThreeViewer from 'component/viewers/threeViewer'; +const ThreeViewer = React.lazy(() => import( + /* webpackChunkName: "threeViewer" */ + 'component/viewers/threeViewer' +)); // @endif type Props = { @@ -173,7 +176,13 @@ class FileRender extends React.PureComponent { } render() { - return
{this.renderViewer()}
; + return ( +
+
}> + {this.renderViewer()} + + + ); } } diff --git a/src/ui/component/transactionList/view.jsx b/src/ui/component/transactionList/view.jsx index 37a9d65e0..262bee7a4 100644 --- a/src/ui/component/transactionList/view.jsx +++ b/src/ui/component/transactionList/view.jsx @@ -3,6 +3,7 @@ import type { Transaction } from 'types/transaction'; import * as icons from 'constants/icons'; import * as MODALS from 'constants/modal_types'; import * as React from 'react'; +import { List } from 'react-virtualized' import { FormField, Form } from 'component/common/form'; import Button from 'component/button'; import FileExporter from 'component/common/file-exporter'; diff --git a/src/ui/component/viewers/audioVideoViewer.jsx b/src/ui/component/viewers/audioVideoViewer.jsx index 10cf547bb..031f989cb 100644 --- a/src/ui/component/viewers/audioVideoViewer.jsx +++ b/src/ui/component/viewers/audioVideoViewer.jsx @@ -2,8 +2,11 @@ import type { Claim } from 'types/claim'; import React from 'react'; import { stopContextMenu } from 'util/context-menu'; -import videojs from 'video.js'; -import 'video.js/dist/video-js.css'; +import( + /* webpackChunkName: "videojs" */ + /* webpackPreload: true */ + 'video.js/dist/video-js.css' +); type Props = { source: { @@ -20,7 +23,8 @@ class AudioVideoViewer extends React.PureComponent { player: ?{ dispose: () => void }; componentDidMount() { - const { contentType, poster, claim } = this.props; + const me = this; + const { contentType, poster, claim } = me.props; const path = `https://api.lbry.tv/content/claims/${claim.name}/${claim.claim_id}/stream.mp4`; const sources = [ @@ -38,7 +42,14 @@ class AudioVideoViewer extends React.PureComponent { sources, }; - this.player = videojs(this.videoNode, videoJsOptions, () => {}); + import( + /* webpackChunkName: "videojs" */ + /* webpackMode: "lazy" */ + /* webpackPreload: true */ + 'video.js' + ).then((videojs) => { + me.player = videojs(me.videoNode, videoJsOptions, () => {}); + }); } componentWillUnmount() { diff --git a/src/ui/component/viewers/codeViewer.jsx b/src/ui/component/viewers/codeViewer.jsx index 1d0cd0620..c0a2c0238 100644 --- a/src/ui/component/viewers/codeViewer.jsx +++ b/src/ui/component/viewers/codeViewer.jsx @@ -1,7 +1,6 @@ // @flow import * as React from 'react'; -import CodeMirror from 'codemirror/lib/codemirror'; import { openSnippetMenu, stopContextMenu } from 'util/context-menu'; // Addons @@ -33,24 +32,30 @@ class CodeViewer extends React.PureComponent { } componentDidMount() { - const { theme, contentType } = this.props; + const me = this; + const { theme, contentType } = me.props; // Init CodeMirror - this.codeMirror = CodeMirror.fromTextArea(this.textarea, { - // Auto detect syntax with file contentType - mode: contentType, - // Adaptive theme - theme: theme === 'dark' ? 'one-dark' : 'default', - // Hide the cursor - readOnly: true, - // Styled text selection - styleSelectedText: true, - // Additional config opts - dragDrop: false, - lineNumbers: true, - lineWrapping: true, + import( + /* webpackChunkName: "codeViewer" */ + 'codemirror/lib/codemirror' + ).then((CodeMirror) => { + me.codeMirror = CodeMirror.fromTextArea(me.textarea, { + // Auto detect syntax with file contentType + mode: contentType, + // Adaptive theme + theme: theme === 'dark' ? 'one-dark' : 'default', + // Hide the cursor + readOnly: true, + // Styled text selection + styleSelectedText: true, + // Additional config opts + dragDrop: false, + lineNumbers: true, + lineWrapping: true, + }); + // Add events + me.codeMirror.on('contextmenu', openSnippetMenu); }); - // Add events - this.codeMirror.on('contextmenu', openSnippetMenu); } textarea: ?HTMLTextAreaElement; diff --git a/src/ui/component/viewers/documentViewer.jsx b/src/ui/component/viewers/documentViewer.jsx index a72a7a2e0..bf01c110a 100644 --- a/src/ui/component/viewers/documentViewer.jsx +++ b/src/ui/component/viewers/documentViewer.jsx @@ -2,9 +2,13 @@ import React from 'react'; import LoadingScreen from 'component/common/loading-screen'; -import CodeViewer from 'component/viewers/codeViewer'; import MarkdownPreview from 'component/common/markdown-preview'; +const LazyCodeViewer = React.lazy(() => import( + /* webpackChunkName: "codeViewer" */ + 'component/viewers/codeViewer' +)); + type Props = { theme: string, source: { @@ -64,7 +68,7 @@ class DocumentViewer extends React.PureComponent { viewer = ; } else { // Render plain text - viewer = ; + viewer = ; } return viewer; diff --git a/webpack.base.config.js b/webpack.base.config.js index a2cd8c9db..e0d1f8278 100644 --- a/webpack.base.config.js +++ b/webpack.base.config.js @@ -3,6 +3,8 @@ const webpack = require('webpack'); const merge = require('webpack-merge'); const { DefinePlugin, ProvidePlugin } = require('webpack'); const { getIfUtils, removeEmpty } = require('webpack-config-utils'); +const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); +const TerserPlugin = require('terser-webpack-plugin'); const NODE_ENV = process.env.NODE_ENV || 'development'; @@ -12,9 +14,22 @@ const UI_ROOT = path.resolve(__dirname, 'src/ui/'); const STATIC_ROOT = path.resolve(__dirname, 'static/'); const DIST_ROOT = path.resolve(__dirname, 'dist/'); +console.log(ifProduction('production', 'development')) + let baseConfig = { mode: ifProduction('production', 'development'), - devtool: ifProduction(false, 'eval-source-map'), + devtool: ifProduction(false, 'inline-cheap-source-map'), + optimization: { + minimizer: [ + new TerserPlugin({ + parallel: true, + terserOptions: { + mangle: true, + toplevel: true, + }, + }), + ], + }, node: { __dirname: false, }, @@ -67,6 +82,9 @@ let baseConfig = { }, plugins: [ + new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), + new webpack.EnvironmentPlugin(['NODE_ENV']), + new BundleAnalyzerPlugin(), new ProvidePlugin({ i18n: ['i18n', 'default'], __: ['i18n/__', 'default'], diff --git a/yarn.lock b/yarn.lock index ec57c0417..b0798d2f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1095,6 +1095,11 @@ acorn-jsx@^5.0.0: resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.1.tgz#32a064fd925429216a09b141102bfdd185fae40e" integrity sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg== +acorn-walk@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.1.1.tgz#d363b66f5fac5f018ff9c3a1e7b6f8e310cc3913" + integrity sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw== + acorn@^6.0.5: version "6.1.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.1.0.tgz#b0a3be31752c97a0f7013c5f4903b71a05db6818" @@ -1414,6 +1419,11 @@ async-foreach@^0.1.3: resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" integrity sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI= +async-limiter@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" + integrity sha512-jp/uFnooOiO+L211eZOoSyzpOITMXx1rBITauYykG3BRYPu8h0UcxsPNB04RR5vo4Tyz3+ay17tR6JVf9qzYWg== + async@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" @@ -1598,6 +1608,16 @@ before-after-hook@^1.1.0: resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-1.3.2.tgz#7bfbf844ad670aa7a96b5a4e4e15bd74b08ed66b" integrity sha512-zyPgY5dgbf99c0uGUjhY4w+mxqEGxPKg9RQDl34VvrVh2bM31lFN+mwR1ZHepq/KA3VCPk1gwJZL6IIJqjLy2w== +bfj@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/bfj/-/bfj-6.1.1.tgz#05a3b7784fbd72cfa3c22e56002ef99336516c48" + integrity sha512-+GUNvzHR4nRyGybQc2WpNJL4MJazMuvf92ueIyA0bIkPRwhhQu3IfZQ2PSoVPpCBJfmoSdOxu5rnotfFLlvYRQ== + dependencies: + bluebird "^3.5.1" + check-types "^7.3.0" + hoopy "^0.1.2" + tryer "^1.0.0" + big-integer@^1.6.17: version "1.6.42" resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.42.tgz#91623ae5ceeff9a47416c56c9440a66f12f534f1" @@ -2178,6 +2198,11 @@ charenc@~0.0.1: resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= +check-types@^7.3.0: + version "7.4.0" + resolved "https://registry.yarnpkg.com/check-types/-/check-types-7.4.0.tgz#0378ec1b9616ec71f774931a3c6516fad8c152f4" + integrity sha512-YbulWHdfP99UfZ73NcUDlNJhEIDgm9Doq9GhpyXbF+7Aegi3CVV7qqMCKTTqJxlvEvnQBp9IA+dxsGN6xK/nSg== + chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.4: version "2.1.2" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.2.tgz#9c23ea40b01638439e0513864d362aeacc5ad058" @@ -2249,7 +2274,7 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -classnames@^2.2.5: +classnames@^2.2.3, classnames@^2.2.5: version "2.2.6" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== @@ -2441,7 +2466,7 @@ commander@2.17.x, commander@~2.17.1: resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== -commander@^2.11.0, commander@^2.14.1, commander@^2.9.0: +commander@^2.11.0, commander@^2.14.1, commander@^2.18.0, commander@^2.9.0: version "2.19.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== @@ -3264,6 +3289,13 @@ dom-converter@^0.2: dependencies: utila "~0.4" +"dom-helpers@^2.4.0 || ^3.0.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8" + integrity sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA== + dependencies: + "@babel/runtime" "^7.1.2" + dom-scroll-into-view@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/dom-scroll-into-view/-/dom-scroll-into-view-1.2.1.tgz#e8f36732dd089b0201a88d7815dc3f88e6d66c7e" @@ -3351,6 +3383,11 @@ duplexer3@^0.1.4: resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= +duplexer@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" + integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= + duplexify@^3.4.2, duplexify@^3.6.0: version "3.7.1" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" @@ -4122,7 +4159,7 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: dependencies: homedir-polyfill "^1.0.1" -express@^4.16.2, express@^4.16.4: +express@^4.16.2, express@^4.16.3, express@^4.16.4: version "4.16.4" resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e" integrity sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg== @@ -4352,6 +4389,11 @@ file-type@^6.1.0: resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== +filesize@^3.6.1: + version "3.6.1" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" + integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg== + fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -4903,10 +4945,13 @@ graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1. resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= -gud@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0" - integrity sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw== +gzip-size@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.0.0.tgz#a55ecd99222f4c48fd8c01c625ce3b349d0a0e80" + integrity sha512-5iI7omclyqrnWw4XbXAmGhPsABkSIDQonv2K0h61lybgofWa6iZyvrI3r2zsJH4P8Nb64fFVzlvfhs0g7BBxAA== + dependencies: + duplexer "^0.1.1" + pify "^3.0.0" handle-thing@^2.0.0: version "2.0.0" @@ -5082,6 +5127,11 @@ homedir-polyfill@^1.0.1: dependencies: parse-passwd "^1.0.0" +hoopy@^0.1.2: + version "0.1.4" + resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" + integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ== + hosted-git-info@^2.1.4, hosted-git-info@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" @@ -6455,7 +6505,7 @@ longest-streak@^2.0.1: resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.2.tgz#2421b6ba939a443bb9ffebf596585a50b4c38e2e" integrity sha512-TmYTeEYxiAmSVdpbnQDXGtvYOIRsCMg89CVZzwzc2o7GFL1CjoiRPjH5ec0NFAVlAx3fVof9dX/t6KKRAo2OWA== -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== @@ -7431,6 +7481,11 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" +opener@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed" + integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA== + opn@^5.1.0: version "5.4.0" resolved "https://registry.yarnpkg.com/opn/-/opn-5.4.0.tgz#cb545e7aab78562beb11aa3bfabc7042e1761035" @@ -8646,6 +8701,18 @@ react-toggle@^4.0.2: dependencies: classnames "^2.2.5" +react-virtualized@^9.21.0: + version "9.21.0" + resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.21.0.tgz#8267c40ffb48db35b242a36dea85edcf280a6506" + integrity sha512-duKD2HvO33mqld4EtQKm9H9H0p+xce1c++2D5xn59Ma7P8VT7CprfAe5hwjd1OGkyhqzOZiTMlTal7LxjH5yBQ== + dependencies: + babel-runtime "^6.26.0" + classnames "^2.2.3" + dom-helpers "^2.4.0 || ^3.0.0" + loose-envify "^1.3.0" + prop-types "^15.6.0" + react-lifecycles-compat "^3.0.4" + react@^16.8.2: version "16.8.3" resolved "https://registry.yarnpkg.com/react/-/react-16.8.3.tgz#c6f988a2ce895375de216edcfaedd6b9a76451d9" @@ -10162,7 +10229,7 @@ term-size@^1.2.0: dependencies: execa "^0.7.0" -terser-webpack-plugin@^1.1.0, terser-webpack-plugin@^1.2.1: +terser-webpack-plugin@^1.1.0, terser-webpack-plugin@^1.2.1, terser-webpack-plugin@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.2.3.tgz#3f98bc902fac3e5d0de730869f50668561262ec8" integrity sha512-GOK7q85oAb/5kE12fMuLdn2btOS9OBZn4VsecpHDywoUC/jLhSAKOiYo0ezx7ss2EXPMzyEWFoE0s1WLE+4+oA== @@ -10362,6 +10429,11 @@ truncate-utf8-bytes@^1.0.0: dependencies: utf8-byte-length "^1.0.1" +tryer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" + integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== + ts-essentials@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-1.0.4.tgz#ce3b5dade5f5d97cf69889c11bf7d2da8555b15a" @@ -10921,6 +10993,25 @@ wbuf@^1.1.0, wbuf@^1.7.3: dependencies: minimalistic-assert "^1.0.0" +webpack-bundle-analyzer@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.1.0.tgz#2f19cbb87bb6d4f3cb4e59cb67c837bd9436e89d" + integrity sha512-nyDyWEs7C6DZlgvu1pR1zzJfIWSiGPbtaByZr8q+Fd2xp70FuM/8ngCJzj3Er1TYRLSFmp1F1OInbEm4DZH8NA== + dependencies: + acorn "^6.0.7" + acorn-walk "^6.1.1" + bfj "^6.1.1" + chalk "^2.4.1" + commander "^2.18.0" + ejs "^2.6.1" + express "^4.16.3" + filesize "^3.6.1" + gzip-size "^5.0.0" + lodash "^4.17.10" + mkdirp "^0.5.1" + opener "^1.5.1" + ws "^6.0.0" + webpack-cli@^3.2.1: version "3.2.3" resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.2.3.tgz#13653549adfd8ccd920ad7be1ef868bacc22e346" @@ -11186,6 +11277,13 @@ write@1.0.3: dependencies: mkdirp "^0.5.1" +ws@^6.0.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.0.tgz#13806d9913b2a5f3cbb9ba47b563c002cbc7c526" + integrity sha512-deZYUNlt2O4buFCa3t5bKLf8A7FPP/TVjwOeVNpw818Ma5nk4MLXls2eoEGS39o8119QIYxTrTDoPQ5B/gTD6w== + dependencies: + async-limiter "~1.0.0" + x-is-string@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82"