From ee24597a36a80ae4133d32aa44dfd721ce074b74 Mon Sep 17 00:00:00 2001 From: Thomas Weber Date: Wed, 19 May 2021 13:45:05 -0500 Subject: [PATCH] Run scratch-blocks lazily It can take up to 40ms to setup, which is unnecessary at startup. In the future, I want to further break it up into its own bundle --- src/containers/custom-procedures.jsx | 3 ++- src/lib/backpack/block-to-image.js | 3 ++- src/lib/blocks.js | 3 ++- src/lib/make-toolbox-xml.js | 24 ++++++++++++++++-------- src/lib/tw-lazy-scratch-blocks.js | 15 +++++++++++++++ 5 files changed, 37 insertions(+), 11 deletions(-) create mode 100644 src/lib/tw-lazy-scratch-blocks.js diff --git a/src/containers/custom-procedures.jsx b/src/containers/custom-procedures.jsx index e691b0466..4c6c55ca4 100644 --- a/src/containers/custom-procedures.jsx +++ b/src/containers/custom-procedures.jsx @@ -3,7 +3,7 @@ import defaultsDeep from 'lodash.defaultsdeep'; import PropTypes from 'prop-types'; import React from 'react'; import CustomProceduresComponent from '../components/custom-procedures/custom-procedures.jsx'; -import ScratchBlocks from 'scratch-blocks'; +import LazyScratchBlocks from '../lib/tw-lazy-scratch-blocks'; import {connect} from 'react-redux'; class CustomProcedures extends React.Component { @@ -38,6 +38,7 @@ class CustomProcedures extends React.Component { ); // @todo This is a hack to make there be no toolbox. + const ScratchBlocks = LazyScratchBlocks.get(); const oldDefaultToolbox = ScratchBlocks.Blocks.defaultToolbox; ScratchBlocks.Blocks.defaultToolbox = null; this.workspace = ScratchBlocks.inject(this.blocks, workspaceConfig); diff --git a/src/lib/backpack/block-to-image.js b/src/lib/backpack/block-to-image.js index eac4753b3..f3bc1c517 100644 --- a/src/lib/backpack/block-to-image.js +++ b/src/lib/backpack/block-to-image.js @@ -1,5 +1,5 @@ import computedStyleToInlineStyle from 'computed-style-to-inline-style'; -import ScratchBlocks from 'scratch-blocks'; +import LazyScratchBlocks from '../tw-lazy-scratch-blocks'; /** * Given a blockId, return a data-uri image that can be used to create a thumbnail. @@ -7,6 +7,7 @@ import ScratchBlocks from 'scratch-blocks'; * @return {Promise} resolves to a data-url of a picture of the blocks */ export default function (blockId) { + const ScratchBlocks = LazyScratchBlocks.get(); // Not sure any better way to access the scratch-blocks workspace than this... const block = ScratchBlocks.getMainWorkspace().getBlockById(blockId); const blockSvg = block.getSvgRoot().cloneNode(true /* deep */); diff --git a/src/lib/blocks.js b/src/lib/blocks.js index 809a77ce2..fccc37c5c 100644 --- a/src/lib/blocks.js +++ b/src/lib/blocks.js @@ -1,4 +1,4 @@ -import ScratchBlocks from 'scratch-blocks'; +import LazyScratchBlocks from './tw-lazy-scratch-blocks'; /** * Connect scratch blocks with the vm @@ -6,6 +6,7 @@ import ScratchBlocks from 'scratch-blocks'; * @return {ScratchBlocks} ScratchBlocks connected with the vm */ export default function (vm) { + const ScratchBlocks = LazyScratchBlocks.get(); const jsonForMenuBlock = function (name, menuOptionsFn, colors, start) { return { diff --git a/src/lib/make-toolbox-xml.js b/src/lib/make-toolbox-xml.js index 44e077ede..893665bde 100644 --- a/src/lib/make-toolbox-xml.js +++ b/src/lib/make-toolbox-xml.js @@ -1,12 +1,20 @@ -import ScratchBlocks from 'scratch-blocks'; +import LazyScratchBlocks from './tw-lazy-scratch-blocks'; const categorySeparator = ''; const blockSeparator = ''; // At default scale, about 28px +const translate = (id, english) => { + if (LazyScratchBlocks.isLoaded()) { + const ScratchBlocks = LazyScratchBlocks.get(); + return ScratchBlocks.ScratchMsgs.translate(id, english); + } + return english; +}; + /* eslint-disable no-unused-vars */ const motion = function (isInitialSetup, isStage, targetId) { - const stageSelected = ScratchBlocks.ScratchMsgs.translate( + const stageSelected = translate( 'MOTION_STAGE_SELECTED', 'Stage selected: no motion blocks' ); @@ -152,8 +160,8 @@ const xmlEscape = function (unsafe) { }; const looks = function (isInitialSetup, isStage, targetId, costumeName, backdropName) { - const hello = ScratchBlocks.ScratchMsgs.translate('LOOKS_HELLO', 'Hello!'); - const hmm = ScratchBlocks.ScratchMsgs.translate('LOOKS_HMM', 'Hmm...'); + const hello = translate('LOOKS_HELLO', 'Hello!'); + const hmm = translate('LOOKS_HMM', 'Hmm...'); return ` ${isStage ? '' : ` @@ -438,7 +446,7 @@ const control = function (isInitialSetup, isStage) { }; const sensing = function (isInitialSetup, isStage) { - const name = ScratchBlocks.ScratchMsgs.translate('SENSING_ASK_TEXT', 'What\'s your name?'); + const name = translate('SENSING_ASK_TEXT', 'What\'s your name?'); return ` ${isStage ? '' : ` @@ -513,9 +521,9 @@ const sensing = function (isInitialSetup, isStage) { }; const operators = function (isInitialSetup) { - const apple = ScratchBlocks.ScratchMsgs.translate('OPERATORS_JOIN_APPLE', 'apple'); - const banana = ScratchBlocks.ScratchMsgs.translate('OPERATORS_JOIN_BANANA', 'banana'); - const letter = ScratchBlocks.ScratchMsgs.translate('OPERATORS_LETTEROF_APPLE', 'a'); + const apple = translate('OPERATORS_JOIN_APPLE', 'apple'); + const banana = translate('OPERATORS_JOIN_BANANA', 'banana'); + const letter = translate('OPERATORS_LETTEROF_APPLE', 'a'); return ` diff --git a/src/lib/tw-lazy-scratch-blocks.js b/src/lib/tw-lazy-scratch-blocks.js new file mode 100644 index 000000000..7616ea986 --- /dev/null +++ b/src/lib/tw-lazy-scratch-blocks.js @@ -0,0 +1,15 @@ +let _ScratchBlocks = null; + +const isLoaded = () => !!_ScratchBlocks; + +const get = () => { + if (!isLoaded()) { + _ScratchBlocks = require('scratch-blocks'); + } + return _ScratchBlocks; +}; + +export default { + isLoaded, + get +};