diff --git a/packages/compass-components/src/force-emotion-speedy.ts b/packages/compass-components/src/force-emotion-speedy.ts new file mode 100644 index 00000000000..8b7c8d74243 --- /dev/null +++ b/packages/compass-components/src/force-emotion-speedy.ts @@ -0,0 +1,24 @@ +import { sheet } from '@leafygreen-ui/emotion'; +/** + * Emotion will dynamically decide which style insertion method to use based on + * the "env" it is built for: in "development" mode it uses a method of + * inserting literal style tags with css as text inside of them for every `css` + * method call to apply styles to the page. This method is really slow, every + * single style tag insertion causes style recalculation that can end up + * blocking the main thread for multiple seconds, when accumulated this can + * result in minutes of unresponsive page behavior. In "production" mode the + * style insertion is done using a modern JS API that doesn't result in such + * drastic performance issues. + * + * Specifically when embedding compass-web in mms, there is a massive + * performance hit that can be observed when emotion is not running in "speedy" + * mode, so to work around that we are always forcing emotion to enable it. + * + * Historically "speedy" mode was only active in production because editing + * styles in the browser devtools didn't work otherwise, nowadays there is no + * reason to not use it always, so there should be no downsides to doing this. + * + * See also https://github.com/10gen/compass-data-explorer/pull/11 where we + * already ran into a similar issue. + */ +sheet.speedy(true); diff --git a/packages/compass-components/src/index.ts b/packages/compass-components/src/index.ts index 7e4431ab956..ffacf0f8226 100644 --- a/packages/compass-components/src/index.ts +++ b/packages/compass-components/src/index.ts @@ -1,5 +1,10 @@ -export * from './components/leafygreen'; +// IMPORTANT: this import should always be the first one in compass-component +// main entrypoint to ensure that emotion is reconfigured before any component +// modules generate their stylesheets +import './force-emotion-speedy'; +// ------------------------------- +export * from './components/leafygreen'; export { default as emotion, flush, diff --git a/packages/compass-web/scripts/sync-dist-to-mms.js b/packages/compass-web/scripts/sync-dist-to-mms.js index cb1f3ee27e1..87ca17a4137 100644 --- a/packages/compass-web/scripts/sync-dist-to-mms.js +++ b/packages/compass-web/scripts/sync-dist-to-mms.js @@ -3,6 +3,7 @@ const fs = require('fs'); const path = require('path'); const child_process = require('child_process'); const os = require('os'); +const util = require('util'); const { debounce } = require('lodash'); if (!process.env.MMS_HOME) { @@ -58,11 +59,42 @@ const webpackWatchProcess = child_process.spawn('npm', ['run', 'watch'], { stdio: 'inherit', }); +const failProofRunner = () => + new (class FailProofRunner extends Array { + append(...fns) { + this.push(...fns); + return this; + } + + run() { + const errors = this.map((f) => { + try { + f(); + } catch (e) { + return e; + } + }).filter((e) => e); + + if (errors.length) { + fs.writeSync( + process.stdout.fd, + util.inspect(errors, { depth: 20 }) + '\n' + ); + } + + return errors.length; + } + })(); + function cleanup(signalName) { - distWatcher.close(); - webpackWatchProcess.kill(signalName); - fs.cpSync(tmpDir, destDir, { recursive: true }); - fs.rmSync(tmpDir, { recursive: true, force: true }); + const errorCount = failProofRunner() + .append(() => distWatcher.close()) + .append(() => webpackWatchProcess.kill(signalName)) + .append(() => fs.cpSync(tmpDir, destDir, { recursive: true })) + .append(() => fs.rmSync(tmpDir, { recursive: true, force: true })) + .run(); + fs.writeSync(process.stdout.fd, 'Exit compass-web sync...\n'); + process.exit(errorCount); } for (const evt of ['SIGINT', 'SIGTERM']) { diff --git a/packages/compass-web/webpack.config.js b/packages/compass-web/webpack.config.js index e71d2f01f47..c76ff5cbc92 100644 --- a/packages/compass-web/webpack.config.js +++ b/packages/compass-web/webpack.config.js @@ -294,13 +294,6 @@ module.exports = (env, args) => { tls: 'commonjs2 tls', }, plugins: [ - // Always package dist with NODE_ENV set to production, otherwise @emotion - // dev mode behavior completely hangs code in the browser when applying - // dev build to locally running mms - new webpack.DefinePlugin({ - 'process.env.NODE_ENV': JSON.stringify('production'), - }), - // Only applied when running webpack in --watch mode. In this mode we want // to constantly rebuild d.ts files when source changes, we also don't // want to fail and stop compilation if we failed to generate definitions