From 715a44864e92e97f982a21c80522dc2f07f3d687 Mon Sep 17 00:00:00 2001 From: Jesse Mazzella Date: Wed, 20 Dec 2023 11:23:24 -0800 Subject: [PATCH] Reduce bundle size (#7246) * chore: use ESModule imports for d3 libraries * chore: add d3 types * chore: use minified plotly * chore: use ESModule style imports for printj * chore: use `terser-webpack-plugin` to minimize * Revert "chore: use minified plotly" This reverts commit 0ae9b39d41b6e38f0fe38cd89a2cd73869f31c36. * Revert "Revert "chore: use minified plotly"" This reverts commit 08973a2d2e6675206907f678d447717ac6526613. * fix: use default minification options * test: stabilize notebook image drop e2e test * test(fix): remove .only() * refactor: convert TelemetryValueFormatter to es6 class --------- Co-authored-by: Scott Bell --- .webpack/webpack.common.js | 6 +- .../notebook/notebookSnapshots.e2e.spec.js | 12 ++- package.json | 8 +- src/api/telemetry/TelemetryValueFormatter.js | 82 +++++++++---------- .../displayLayout/CustomStringFormatter.js | 4 +- src/plugins/timeConductor/ConductorAxis.vue | 8 +- src/ui/components/TimeSystemAxis.vue | 8 +- 7 files changed, 66 insertions(+), 62 deletions(-) diff --git a/.webpack/webpack.common.js b/.webpack/webpack.common.js index 77a6103e5b..512dbb2515 100644 --- a/.webpack/webpack.common.js +++ b/.webpack/webpack.common.js @@ -69,9 +69,9 @@ const config = { csv: 'comma-separated-values', EventEmitter: 'eventemitter3', bourbon: 'bourbon.scss', - 'plotly-basic': 'plotly.js-basic-dist', - 'plotly-gl2d': 'plotly.js-gl2d-dist', - printj: path.join(projectRootDir, 'node_modules/printj/dist/printj.min.js'), + 'plotly-basic': 'plotly.js-basic-dist-min', + 'plotly-gl2d': 'plotly.js-gl2d-dist-min', + printj: 'printj/printj.mjs', styles: path.join(projectRootDir, 'src/styles'), MCT: path.join(projectRootDir, 'src/MCT'), testUtils: path.join(projectRootDir, 'src/utils/testUtils.js'), diff --git a/e2e/tests/functional/plugins/notebook/notebookSnapshots.e2e.spec.js b/e2e/tests/functional/plugins/notebook/notebookSnapshots.e2e.spec.js index f3fa07f58b..877da4da55 100644 --- a/e2e/tests/functional/plugins/notebook/notebookSnapshots.e2e.spec.js +++ b/e2e/tests/functional/plugins/notebook/notebookSnapshots.e2e.spec.js @@ -19,12 +19,13 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ - +/* global __dirname */ /* This test suite is dedicated to tests which verify the basic operations surrounding Notebooks. */ const fs = require('fs').promises; +const path = require('path'); const { test, expect } = require('../../../../pluginFixtures'); const { createDomainObjectWithDefaults } = require('../../../../appActions'); @@ -176,7 +177,9 @@ test.describe('Snapshot image tests', () => { }); test('Can drop an image onto a notebook and create a new entry', async ({ page }) => { - const imageData = await fs.readFile('src/images/favicons/favicon-96x96.png'); + const imageData = await fs.readFile( + path.resolve(__dirname, '../../../../../src/images/favicons/favicon-96x96.png') + ); const imageArray = new Uint8Array(imageData); const fileData = Array.from(imageArray); @@ -201,14 +204,17 @@ test.describe('Snapshot image tests', () => { // drop another image onto the entry await page.dispatchEvent('.c-snapshots', 'drop', { dataTransfer: dropTransfer }); + const secondThumbnail = page.getByRole('img', { name: 'favicon-96x96.png thumbnail' }).nth(1); + await secondThumbnail.waitFor({ state: 'attached' }); // expect two embedded images now expect(await page.getByRole('img', { name: 'favicon-96x96.png thumbnail' }).count()).toBe(2); await page.locator('.c-snapshot.c-ne__embed').first().getByTitle('More options').click(); await page.getByRole('menuitem', { name: /Remove This Embed/ }).click(); - await page.getByRole('button', { name: 'Ok', exact: true }).click(); + // Ensure that the thumbnail is removed before we assert + await secondThumbnail.waitFor({ state: 'detached' }); // expect one embedded image now as we deleted the other expect(await page.getByRole('img', { name: 'favicon-96x96.png thumbnail' }).count()).toBe(1); diff --git a/package.json b/package.json index fd35e7b387..58c093a5d1 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,9 @@ "@percy/cli": "1.27.4", "@percy/playwright": "1.0.4", "@playwright/test": "1.39.0", + "@types/d3-axis": "3.0.6", + "@types/d3-scale": "4.0.8", + "@types/d3-selection": "3.0.10", "@types/eventemitter3": "1.2.0", "@types/jasmine": "5.1.2", "@types/lodash": "4.14.192", @@ -62,8 +65,8 @@ "npm-run-all2": "6.1.1", "nyc": "15.1.0", "painterro": "1.2.87", - "plotly.js-basic-dist": "2.20.0", - "plotly.js-gl2d-dist": "2.20.0", + "plotly.js-basic-dist-min": "2.20.0", + "plotly.js-gl2d-dist-min": "2.20.0", "prettier": "2.8.7", "printj": "1.3.1", "resolve-url-loader": "5.0.0", @@ -72,6 +75,7 @@ "sass-loader": "13.3.2", "sinon": "17.0.0", "style-loader": "3.3.3", + "terser-webpack-plugin": "5.3.9", "tiny-emitter": "2.1.0", "typescript": "5.2.2", "uuid": "9.0.1", diff --git a/src/api/telemetry/TelemetryValueFormatter.js b/src/api/telemetry/TelemetryValueFormatter.js index f97d650ebe..88e19da120 100644 --- a/src/api/telemetry/TelemetryValueFormatter.js +++ b/src/api/telemetry/TelemetryValueFormatter.js @@ -20,39 +20,25 @@ * at runtime from the About dialog for additional information. *****************************************************************************/ -define(['lodash', 'printj'], function (_, printj) { - // TODO: needs reference to formatService; - function TelemetryValueFormatter(valueMetadata, formatMap) { +import _ from 'lodash'; +import { sprintf } from 'printj'; + +// TODO: needs reference to formatService; +export default class TelemetryValueFormatter { + constructor(valueMetadata, formatMap) { + this.valueMetadata = valueMetadata; + this.formatMap = formatMap; + this.valueMetadataFormat = this.getNonArrayValue(valueMetadata.format); + const numberFormatter = { - parse: function (x) { - return Number(x); - }, - format: function (x) { - return x; - }, - validate: function (x) { - return true; - } + parse: (x) => Number(x), + format: (x) => x, + validate: (x) => true }; - this.valueMetadata = valueMetadata; - - function getNonArrayValue(value) { - //metadata format could have array formats ex. string[]/number[] - const arrayRegex = /\[\]$/g; - if (value && value.match(arrayRegex)) { - return value.replace(arrayRegex, ''); - } - - return value; - } - - let valueMetadataFormat = getNonArrayValue(valueMetadata.format); - - //Is there an existing formatter for the format specified? If not, default to number format - this.formatter = formatMap.get(valueMetadataFormat) || numberFormatter; - - if (valueMetadataFormat === 'enum') { + // Is there an existing formatter for the format specified? If not, default to number format + this.formatter = formatMap.get(this.valueMetadataFormat) || numberFormatter; + if (this.valueMetadataFormat === 'enum') { this.formatter = {}; this.enumerations = valueMetadata.enumerations.reduce( function (vm, e) { @@ -66,14 +52,14 @@ define(['lodash', 'printj'], function (_, printj) { byString: {} } ); - this.formatter.format = function (value) { + this.formatter.format = (value) => { if (Object.prototype.hasOwnProperty.call(this.enumerations.byValue, value)) { return this.enumerations.byValue[value]; } return value; - }.bind(this); - this.formatter.parse = function (string) { + }; + this.formatter.parse = (string) => { if (typeof string === 'string') { if (Object.prototype.hasOwnProperty.call(this.enumerations.byString, string)) { return this.enumerations.byString[string]; @@ -81,19 +67,19 @@ define(['lodash', 'printj'], function (_, printj) { } return Number(string); - }.bind(this); + }; } // Check for formatString support once instead of per format call. if (valueMetadata.formatString) { const baseFormat = this.formatter.format; - const formatString = getNonArrayValue(valueMetadata.formatString); + const formatString = this.getNonArrayValue(valueMetadata.formatString); this.formatter.format = function (value) { - return printj.sprintf(formatString, baseFormat.call(this, value)); + return sprintf(formatString, baseFormat.call(this, value)); }; } - if (valueMetadataFormat === 'string') { + if (this.valueMetadataFormat === 'string') { this.formatter.parse = function (value) { if (value === undefined) { return ''; @@ -116,7 +102,17 @@ define(['lodash', 'printj'], function (_, printj) { } } - TelemetryValueFormatter.prototype.parse = function (datum) { + getNonArrayValue(value) { + //metadata format could have array formats ex. string[]/number[] + const arrayRegex = /\[\]$/g; + if (value && value.match(arrayRegex)) { + return value.replace(arrayRegex, ''); + } + + return value; + } + + parse(datum) { const isDatumArray = Array.isArray(datum); if (_.isObject(datum)) { const objectDatum = isDatumArray ? datum : datum[this.valueMetadata.source]; @@ -130,9 +126,9 @@ define(['lodash', 'printj'], function (_, printj) { } return this.formatter.parse(datum); - }; + } - TelemetryValueFormatter.prototype.format = function (datum) { + format(datum) { const isDatumArray = Array.isArray(datum); if (_.isObject(datum)) { const objectDatum = isDatumArray ? datum : datum[this.valueMetadata.source]; @@ -146,7 +142,5 @@ define(['lodash', 'printj'], function (_, printj) { } return this.formatter.format(datum); - }; - - return TelemetryValueFormatter; -}); + } +} diff --git a/src/plugins/displayLayout/CustomStringFormatter.js b/src/plugins/displayLayout/CustomStringFormatter.js index 7e49280541..f25e7041fd 100644 --- a/src/plugins/displayLayout/CustomStringFormatter.js +++ b/src/plugins/displayLayout/CustomStringFormatter.js @@ -1,4 +1,4 @@ -import printj from 'printj'; +import { sprintf } from 'printj'; export default class CustomStringFormatter { constructor(openmct, valueMetadata, itemFormat) { @@ -14,7 +14,7 @@ export default class CustomStringFormatter { } if (!this.itemFormat.startsWith('&')) { - return printj.sprintf(this.itemFormat, datum[this.valueMetadata.key]); + return sprintf(this.itemFormat, datum[this.valueMetadata.key]); } try { diff --git a/src/plugins/timeConductor/ConductorAxis.vue b/src/plugins/timeConductor/ConductorAxis.vue index b2eb7a59e1..0c5a4d80d1 100644 --- a/src/plugins/timeConductor/ConductorAxis.vue +++ b/src/plugins/timeConductor/ConductorAxis.vue @@ -26,9 +26,9 @@