diff --git a/BUILD.md b/BUILD.md
index 4dd9d53796..a0f5646f04 100644
--- a/BUILD.md
+++ b/BUILD.md
@@ -20,14 +20,6 @@ In the project root, `typescript` is used to bolster the linting of TypeScript f
In `./packages/plexus`, `typescript` is used to generate type declarations for the ES module build. See [`./packages/plexus/BUILD.md`](packages/plexus/BUILD.md#typescript---emitdeclarationonly) for details.
-### Workspaces
-
-[Create React App](https://facebook.github.io/create-react-app/) (CRA) is used as the build-tooling for the Jaeger UI website. In 2.1.2+ CRA introduced a guard for the `start`, `build` and `test` scripts which checks the version of NPM packages available to make sure they're consistent with CRA's expectations ([reference](https://github.com/facebook/create-react-app/blob/dea19fdb30c2e896ed8ac75b68a612b0b92b2406/packages/react-scripts/scripts/utils/verifyPackageTree.js#L23-L29)). This process checks `node_modules` in parent directories and errors if an unexpected package version is encountered.
-
-To avoid a world of pain, the [`nohoist`](https://yarnpkg.com/blog/2018/02/15/nohoist/#scope-private) feature of `yarn` workspaces is leveraged. CRA and it's dependencies are local to `./packages/jaeger-ui/node_modules` instead of `./node_modules`, i.e. they're not hoisted. This ensures CRA is using the packages it expects to use.
-
-Unfortunately, the CRA check is not savvy to `yarn` workspaces and errors even though the _`yarn` workspace-magic_ ensures the right packages are actually used by the CRA scripts. So, the escape hatch provided by CRA is used to skip the check: the envvar `SKIP_PREFLIGHT_CHECK=true`, set in `./packages/jaeger-ui/.env`.
-
### Scripts
#### `build`
diff --git a/package.json b/package.json
index fec09488fa..556d14e478 100644
--- a/package.json
+++ b/package.json
@@ -37,12 +37,7 @@
"packages/*"
],
"nohoist": [
- "**/customize-cra",
- "**/customize-cra/**",
- "**/react-scripts",
- "**/react-scripts/**",
- "**/react-app-rewired",
- "**/react-app-rewired/**"
+ "**/parse5"
]
},
"scripts": {
diff --git a/packages/jaeger-ui/.env b/packages/jaeger-ui/.env
deleted file mode 100644
index 14328033a3..0000000000
--- a/packages/jaeger-ui/.env
+++ /dev/null
@@ -1,8 +0,0 @@
-# create-react-app does a check on several packages to make sure the
-# versions required by CRA are the package versions available:
-# https://github.com/facebook/create-react-app/blob/dea19fdb30c2e896ed8ac75b68a612b0b92b2406/packages/react-scripts/scripts/utils/verifyPackageTree.js#L23-L29
-# The repo is set up to use yarn workspaces and keeps all
-# packages/jaeger-ui packages local to packages/jaeger-ui. But, the
-# check CRA does not detect this. So, the following env-var skips the
-# check.
-SKIP_PREFLIGHT_CHECK=true
diff --git a/packages/jaeger-ui/.eslintrc.js b/packages/jaeger-ui/.eslintrc.js
new file mode 100644
index 0000000000..2458d3225a
--- /dev/null
+++ b/packages/jaeger-ui/.eslintrc.js
@@ -0,0 +1,11 @@
+module.exports = {
+ // Let ESLint know about constants injected by the build system.
+ // These aren't technically globals (in that they are replaced by literals at build time),
+ // but from a linter perspective, they are globals and so need to be explicitly listed.
+ // https://vitejs.dev/config/shared-options.html#define
+ globals: {
+ __REACT_APP_GA_DEBUG__: false,
+ __REACT_APP_VSN_STATE__: false,
+ __APP_ENVIRONMENT__: false,
+ },
+};
diff --git a/packages/jaeger-ui/.gitignore b/packages/jaeger-ui/.gitignore
index 8ac4a42c83..e8d57c71ae 100644
--- a/packages/jaeger-ui/.gitignore
+++ b/packages/jaeger-ui/.gitignore
@@ -1 +1,4 @@
tsconfig.lint.tsbuildinfo
+
+# Bundle size breakdown generated by rollup-plugin-visualizer
+stats.html
diff --git a/packages/jaeger-ui/config-overrides-antd-vars.less b/packages/jaeger-ui/config-overrides-antd-vars.less
deleted file mode 100644
index 31ecdf902d..0000000000
--- a/packages/jaeger-ui/config-overrides-antd-vars.less
+++ /dev/null
@@ -1,24 +0,0 @@
-@primary-color: #199;
-
-@font-size-base: 14px;
-@text-color-dark: #e4e4e4;
-@text-color-secondary-dark: #fff;
-
-// Layout
-@layout-body-background :#fff;
-@layout-header-background : #404040;
-@layout-footer-background : @layout-body-background;
-@layout-header-height : 64px;
-@layout-header-padding : 0 50px;
-@layout-footer-padding : 24px 50px;
-@layout-sider-background : @layout-header-background;
-@layout-trigger-height : 48px;
-@layout-trigger-background : tint(@heading-color, 20%);
-@layout-trigger-color : #fff;
-@layout-zero-trigger-width : 36px;
-@layout-zero-trigger-height : 42px;
-
-@menu-dark-bg: #151515;
-
-// Table
-@table-row-hover-bg:#e5f2f2;
diff --git a/packages/jaeger-ui/config-overrides.js b/packages/jaeger-ui/config-overrides.js
deleted file mode 100644
index 0ad31c08b7..0000000000
--- a/packages/jaeger-ui/config-overrides.js
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright (c) 2017 Uber Technologies, Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-/* eslint-disable import/no-extraneous-dependencies */
-const fs = require('fs');
-const { addBabelPlugin, addLessLoader } = require('customize-cra');
-const lessToJs = require('less-vars-to-js');
-const ManifestPlugin = require('webpack-manifest-plugin');
-const stringify = require('json-stable-stringify');
-
-function useEslintRc(config) {
- const { rules } = config.module;
- const preRule = rules.find(rule => rule.enforce === 'pre');
- if (!preRule) {
- throw new Error('Unable to find estlint rule, pre');
- }
- const use = Array.isArray(preRule.use) ? preRule.use[0] : null;
- if (!use) {
- throw new Error('Unable to find estlint rule, use');
- }
- const isEslintRule = /node_modules\/eslint-loader\//.test(use.loader);
- if (!isEslintRule || !use.options) {
- throw new Error('Unable to find estlint rule, eslint loader');
- }
- use.options.useEslintrc = true;
- return config;
-}
-
-/* configureStableSerializationWebpackManifestPlugin makes webpack-manifest-plugin
- provide a stable output format. Stable output allows the resulting manifest to be packaged
- without changing checksums. This overrides any existing formats for all instances
- of the plugin loaded at the time that this is run.
-*/
-function configureStableSerializationWebpackManifestPlugin(_config) {
- const serializeFunc = manifest => stringify(manifest, { space: 2 });
- const config = _config;
- config.plugins.forEach(_p => {
- const p = _p;
- if (p instanceof ManifestPlugin) {
- p.opts.serialize = serializeFunc;
- }
- });
- return config;
-}
-
-// Convert less vars to JS
-const loadedVarOverrides = fs.readFileSync('config-overrides-antd-vars.less', 'utf8');
-const modifyVars = lessToJs(loadedVarOverrides);
-
-function webpack(_config) {
- let config = _config;
- config = addLessLoader({
- modifyVars,
- javascriptEnabled: true,
- })(config);
- config = configureStableSerializationWebpackManifestPlugin(config);
- config = addBabelPlugin(['import', { libraryName: 'antd', style: true }])(config);
- useEslintRc(config);
- return config;
-}
-
-module.exports = { webpack };
diff --git a/packages/jaeger-ui/public/favicon.ico b/packages/jaeger-ui/favicon.ico
similarity index 100%
rename from packages/jaeger-ui/public/favicon.ico
rename to packages/jaeger-ui/favicon.ico
diff --git a/packages/jaeger-ui/public/index.html b/packages/jaeger-ui/index.html
similarity index 77%
rename from packages/jaeger-ui/public/index.html
rename to packages/jaeger-ui/index.html
index 9a0f706b81..e299a84125 100644
--- a/packages/jaeger-ui/public/index.html
+++ b/packages/jaeger-ui/index.html
@@ -12,7 +12,7 @@