From 0dbaf4af4319c2ee064143ea09015355e5cf3b53 Mon Sep 17 00:00:00 2001 From: Alex Boatwright Date: Thu, 21 Nov 2019 15:28:02 -0800 Subject: [PATCH] feat(ui): lazy load monaco in runtime (#15978) --- ui/global.d.ts | 1 - ui/src/shared/utils/featureFlag.ts | 88 ++++++++++++++++--- .../components/TimeMachineFluxEditor.scss | 17 ++++ .../components/TimeMachineFluxEditor.tsx | 52 ++++++----- ui/webpack.common.ts | 3 - 5 files changed, 123 insertions(+), 38 deletions(-) diff --git a/ui/global.d.ts b/ui/global.d.ts index b94f05ea8a..b4fe6efbdb 100644 --- a/ui/global.d.ts +++ b/ui/global.d.ts @@ -2,4 +2,3 @@ // got some globals here that only exist during compilation // -declare var ENABLE_MONACO: string diff --git a/ui/src/shared/utils/featureFlag.ts b/ui/src/shared/utils/featureFlag.ts index 6fc15fa464..ce3e821119 100644 --- a/ui/src/shared/utils/featureFlag.ts +++ b/ui/src/shared/utils/featureFlag.ts @@ -5,6 +5,7 @@ const OSS_FLAGS = { alerting: false, eventMarkers: false, deleteWithPredicate: false, + monacoEditor: false, downloadCellCSV: false, } @@ -12,12 +13,14 @@ const CLOUD_FLAGS = { alerting: true, eventMarkers: false, deleteWithPredicate: false, + monacoEditor: false, cloudBilling: CLOUD_BILLING_VISIBLE, // should be visible in dev and acceptance, but not in cloud downloadCellCSV: false, } -export const isFlagEnabled = (flagName: string) => { +export const isFlagEnabled = (flagName: string, equals?: string | boolean) => { let localStorageFlags + let _equals = equals try { localStorageFlags = JSON.parse(window.localStorage.featureFlags) @@ -25,25 +28,86 @@ export const isFlagEnabled = (flagName: string) => { localStorageFlags = {} } - return ( - localStorageFlags[flagName] === true || - (CLOUD && CLOUD_FLAGS[flagName]) || - (!CLOUD && OSS_FLAGS[flagName]) - ) + if (_equals === undefined) { + _equals = true + } + + if (localStorageFlags.hasOwnProperty(flagName)) { + return localStorageFlags[flagName] === _equals + } + + if (CLOUD) { + if (CLOUD_FLAGS.hasOwnProperty(flagName)) { + return CLOUD_FLAGS[flagName] === _equals + } + + return false + } + + if (OSS_FLAGS.hasOwnProperty(flagName)) { + return OSS_FLAGS[flagName] === _equals + } + + return false } // type influx.toggleFeature('myFlag') to disable / enable any feature flag -export const FeatureFlag: FunctionComponent<{name: string}> = ({ - name, - children, -}) => { - if (!isFlagEnabled(name)) { +export const FeatureFlag: FunctionComponent<{ + name: string + equals?: string | boolean +}> = ({name, equals, children}) => { + if (!isFlagEnabled(name, equals)) { return null } return children as any } +/* eslint-disable no-console */ +const list = () => { + console.log('Currently Available Feature Flags') + if (CLOUD) { + console.table(CLOUD_FLAGS) + } else { + console.table(OSS_FLAGS) + } +} +/* eslint-enable no-console */ + +const reset = () => { + const featureFlags = JSON.parse(window.localStorage.featureFlags || '{}') + + if (CLOUD) { + Object.keys(featureFlags).forEach(k => { + if (!CLOUD_FLAGS.hasOwnProperty(k)) { + delete featureFlags[k] + } else { + featureFlags[k] = CLOUD_FLAGS[k] + } + }) + } else { + Object.keys(featureFlags).forEach(k => { + if (!CLOUD_FLAGS.hasOwnProperty(k)) { + delete featureFlags[k] + } else { + featureFlags[k] = CLOUD_FLAGS[k] + } + }) + } + + window.localStorage.featureFlags = JSON.stringify(featureFlags) +} + +export const set = (flagName: string, value: string | boolean) => { + const featureFlags = JSON.parse(window.localStorage.featureFlags || '{}') + + featureFlags[flagName] = value + + window.localStorage.featureFlags = JSON.stringify(featureFlags) + + return featureFlags[flagName] +} + export const toggleLocalStorageFlag = (flagName: string) => { const featureFlags = JSON.parse(window.localStorage.featureFlags || '{}') @@ -57,4 +121,4 @@ export const toggleLocalStorageFlag = (flagName: string) => { // Expose utility in dev tools console for convenience const w: any = window -w.influx = {toggleFeature: toggleLocalStorageFlag} +w.influx = {toggleFeature: toggleLocalStorageFlag, list, reset} diff --git a/ui/src/timeMachine/components/TimeMachineFluxEditor.scss b/ui/src/timeMachine/components/TimeMachineFluxEditor.scss index 6edea361eb..36674d79de 100644 --- a/ui/src/timeMachine/components/TimeMachineFluxEditor.scss +++ b/ui/src/timeMachine/components/TimeMachineFluxEditor.scss @@ -25,3 +25,20 @@ width: 100%; height: 100%; } + +.time-machine-editor--loading { + width: 100%; + height: 100%; + position: relative; + background: #292933; + + &:after { + content: ''; + position: absolute; + background: #202028; + top: 8px; + bottom: 8px; + left: 24px; + right: 8px; + } +} diff --git a/ui/src/timeMachine/components/TimeMachineFluxEditor.tsx b/ui/src/timeMachine/components/TimeMachineFluxEditor.tsx index 1d4e3b9d37..ceda01db79 100644 --- a/ui/src/timeMachine/components/TimeMachineFluxEditor.tsx +++ b/ui/src/timeMachine/components/TimeMachineFluxEditor.tsx @@ -1,14 +1,18 @@ // Libraries -import React, {PureComponent} from 'react' +import React, {PureComponent, Suspense} from 'react' import {connect} from 'react-redux' import {Position} from 'codemirror' // Components -import FluxEditor from 'src/shared/components/FluxEditor' +const FluxEditor = React.lazy(() => import('src/shared/components/FluxEditor')) +const FluxMonacoEditor = React.lazy(() => + import('src/shared/components/FluxMonacoEditor') +) import Threesizer from 'src/shared/components/threesizer/Threesizer' import FluxFunctionsToolbar from 'src/timeMachine/components/fluxFunctionsToolbar/FluxFunctionsToolbar' import VariableToolbar from 'src/timeMachine/components/variableToolbar/VariableToolbar' import ToolbarTab from 'src/timeMachine/components/ToolbarTab' +import {FeatureFlag} from 'src/shared/utils/featureFlag' // Actions import {setActiveQueryText} from 'src/timeMachine/actions' @@ -40,6 +44,8 @@ interface State { type Props = StateProps & DispatchProps +const spinner =
+ class TimeMachineFluxEditor extends PureComponent { private cursorPosition: Position = {line: 0, ch: 0} @@ -55,27 +61,29 @@ class TimeMachineFluxEditor extends PureComponent { size: 0.75, handleDisplay: HANDLE_NONE, render: () => { - if (ENABLE_MONACO) { - const FluxMonacoEditor = require('src/shared/components/FluxMonacoEditor') - .default - return ( - - ) - } return ( - + <> + + + + + + + + + ) }, }, diff --git a/ui/webpack.common.ts b/ui/webpack.common.ts index 06fb92e778..450645395d 100644 --- a/ui/webpack.common.ts +++ b/ui/webpack.common.ts @@ -109,9 +109,6 @@ module.exports = { }), new ForkTsCheckerWebpackPlugin(), new webpack.ProgressPlugin(), - new webpack.DefinePlugin({ - ENABLE_MONACO: JSON.stringify(false) - }), new webpack.EnvironmentPlugin({...process.env, GIT_SHA, API_PREFIX: API_BASE_PATH, STATIC_PREFIX: BASE_PATH}), ], stats: {