From 59e0eacab3f15e6fdc8d858dea6c1753f0927037 Mon Sep 17 00:00:00 2001 From: Brian Ng Date: Sat, 19 Aug 2017 11:05:35 -0500 Subject: [PATCH 1/4] Lazy load Babel on REPL --- js/repl/LoadingMessage.js | 0 js/repl/PresetLoadingAnimation.js | 8 +- js/repl/Repl.js | 79 +++++++- js/repl/ReplOptions.js | 297 ++++++++++++++++-------------- js/repl/UriUtils.js | 4 + js/repl/loadBabel.js | 43 +++++ js/repl/loadBuildArtifacts.js | 39 ++++ js/repl/replUtils.js | 15 ++ js/repl/types.js | 18 +- repl2.html | 1 - 10 files changed, 350 insertions(+), 154 deletions(-) create mode 100644 js/repl/LoadingMessage.js create mode 100644 js/repl/loadBabel.js create mode 100644 js/repl/loadBuildArtifacts.js diff --git a/js/repl/LoadingMessage.js b/js/repl/LoadingMessage.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/repl/PresetLoadingAnimation.js b/js/repl/PresetLoadingAnimation.js index 636af654c4..bced120d43 100644 --- a/js/repl/PresetLoadingAnimation.js +++ b/js/repl/PresetLoadingAnimation.js @@ -1,8 +1,12 @@ import { css } from "glamor"; import React from "react"; -const PresetLoadingAnimation = () => -
+type PresetLoadingAnimationProps = { + className: ?string, +}; + +const PresetLoadingAnimation = ({ className }: PresetLoadingAnimationProps) => +
diff --git a/js/repl/Repl.js b/js/repl/Repl.js index 9066d3a33e..168bc6075f 100644 --- a/js/repl/Repl.js +++ b/js/repl/Repl.js @@ -8,8 +8,9 @@ import ReplOptions from "./ReplOptions"; import StorageService from "./StorageService"; import UriUtils from "./UriUtils"; import compile from "./compile"; +import loadBabel from "./loadBabel"; import loadPlugin from "./loadPlugin"; -import scopedEval from "./scopedEval"; +import PresetLoadingAnimation from "./PresetLoadingAnimation"; import { envPresetConfig, pluginConfigs, @@ -22,12 +23,15 @@ import { loadPersistedState, configArrayToStateMap, configToState, + persistedStateToBabelState, persistedStateToEnvConfig, } from "./replUtils"; -import { media } from "./styles"; +import scopedEval from "./scopedEval"; +import { colors, media } from "./styles"; import type { BabelPresets, + BabelState, EnvConfig, PluginState, PluginStateMap, @@ -36,6 +40,7 @@ import type { type Props = {}; type State = { + babel: BabelState, builtIns: boolean, code: string, compiled: ?string, @@ -86,7 +91,8 @@ export default class Repl extends React.Component { // A partial State is defined first b'c this._compile needs it. // The compile helper will then populate the missing State values. - const state = { + this.state = { + babel: persistedStateToBabelState(persistedState), builtIns: persistedState.builtIns, code: persistedState.code, compiled: null, @@ -110,18 +116,28 @@ export default class Repl extends React.Component { sourceMap: null, }; - this.state = { - ...state, - ...this._compile(persistedState.code, state), - }; - - // Load any plug-ins enabled by query params. - this._checkForUnloadedPlugins(); + this._setupBabel(); } render() { const state = this.state; + if (!state.babel.isLoaded) { + const message = state.babel.isLoading + ? "Loading Babel..." + : "An error occurred while loading Babel :("; + + return ( +
+
+ {message} + {state.babel.isLoading && + } +
+
+ ); + } + const options = { lineWrapping: state.lineWrap, }; @@ -167,6 +183,30 @@ export default class Repl extends React.Component { ); } + _setupBabel() { + loadBabel(this.state.babel, success => { + this.setState( + state => { + const babelState = state.babel; + + if (success) { + babelState.isLoaded = true; + babelState.isLoading = false; + } else { + babelState.didError = true; + babelState.isLoading = false; + } + + return { + babel: babelState, + ...this._compile(state.code, state), + }; + }, + () => this._checkForUnloadedPlugins() + ); + }); + } + _checkForUnloadedPlugins() { const { envConfig, @@ -370,7 +410,9 @@ export default class Repl extends React.Component { const state = { babili: plugins["babili-standalone"].isEnabled, browsers: envConfig.browsers, + build: this.state.babel.build, builtIns: this.state.builtIns, + circleciRepo: this.state.babel.circleciRepo, code: this.state.code, debug: this.state.debugEnvPreset, evaluate: this.state.runtimePolyfillState.isEnabled, @@ -379,6 +421,7 @@ export default class Repl extends React.Component { prettier: plugins.prettier.isEnabled, showSidebar: this.state.isSidebarExpanded, targets: envConfigToTargetsString(envConfig), + version: this.state.babel.version, }; StorageService.set("replState", state); @@ -408,6 +451,22 @@ export default class Repl extends React.Component { } const styles = { + loader: css({ + alignItems: "center", + background: colors.inverseBackgroundDark, + color: colors.inverseForegroundLight, + display: "flex", + height: "100vh", + justifyContent: "center", + }), + loadingAnimation: css({ + justifyContent: "center", + margin: "2rem 0 0 0", + }), + loaderContent: css({ + margin: "auto", + textAlign: "center", + }), codeMirrorPanel: css({ flex: "0 0 50%", }), diff --git a/js/repl/ReplOptions.js b/js/repl/ReplOptions.js index 67d223ffc5..026e2b4a9a 100644 --- a/js/repl/ReplOptions.js +++ b/js/repl/ReplOptions.js @@ -78,146 +78,150 @@ class ExpandedContainer extends Component { return (
-
-
Settings
- - - {pluginConfigs.map(config => - - )} -
-
-
Presets
- {presetPluginConfigs.map(config => +
+
+
Settings
- )} -
-
- -
+ + {pluginConfigs.map(config => + + )} +
+
+
Presets
+ {presetPluginConfigs.map(config => + + )} +
+
+
+ +