From 7694784147ff31c94d4e420efb3be757526c31a6 Mon Sep 17 00:00:00 2001 From: Forrest Date: Thu, 20 Jul 2023 14:32:54 -0400 Subject: [PATCH] chore(bundle): reduce size and better chunking - Lazy load AWS SDK and JSZip - Chunk out whatwg-url and vtk.js OpenGL --- src/io/amazonS3.ts | 5 ++++- src/io/state-file/index.ts | 5 ++++- src/io/state-file/schema.ts | 2 +- src/io/zip.ts | 4 +++- src/lazy/index.ts | 25 +++++++++++++++++++++++++ src/lazy/lazyAwsSdk.ts | 4 ++++ src/lazy/lazyJSZip.ts | 4 ++++ vite.config.ts | 10 ++++++++++ 8 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 src/lazy/index.ts create mode 100644 src/lazy/lazyAwsSdk.ts create mode 100644 src/lazy/lazyJSZip.ts diff --git a/src/io/amazonS3.ts b/src/io/amazonS3.ts index 74c27130c..e91a08f82 100644 --- a/src/io/amazonS3.ts +++ b/src/io/amazonS3.ts @@ -1,6 +1,7 @@ -import { S3Client, ListObjectsV2Command } from '@aws-sdk/client-s3'; import { URL } from 'whatwg-url'; +const importAwsSdk = () => import('@/src/lazy/lazyAwsSdk'); + /** * Detects `s3://` uri. * @param uri @@ -19,6 +20,8 @@ async function fetchObjectsWithPagination( prefix: string, onObjectAvailable: ObjectAvailableCallback = () => {} ) { + const { S3Client, ListObjectsV2Command } = await importAwsSdk(); + const client = new S3Client({ region: 'us-east-1', // workaround for sdk's inability to specify anonymous credentials diff --git a/src/io/state-file/index.ts b/src/io/state-file/index.ts index cad4c0dea..383d7f466 100644 --- a/src/io/state-file/index.ts +++ b/src/io/state-file/index.ts @@ -1,4 +1,3 @@ -import JSZip from 'jszip'; import { useDatasetStore } from '@/src/store/datasets'; import { useLabelmapStore } from '@/src/store/datasets-labelmaps'; import { useLayersStore } from '@/src/store/datasets-layers'; @@ -11,6 +10,8 @@ import { Manifest } from './schema'; import { retypeFile } from '../io'; import { ARCHIVE_FILE_TYPES } from '../mimeTypes'; +const importJSZip = () => import('@/src/lazy/lazyJSZip'); + export const MANIFEST = 'manifest.json'; export const MANIFEST_VERSION = '2.1.0'; @@ -21,6 +22,7 @@ export async function serialize() { const toolStore = useToolStore(); const layersStore = useLayersStore(); + const { JSZip } = await importJSZip(); const zip = new JSZip(); const manifest: Manifest = { version: MANIFEST_VERSION, @@ -67,6 +69,7 @@ export async function serialize() { export async function isStateFile(file: File) { const typedFile = await retypeFile(file); if (ARCHIVE_FILE_TYPES.has(typedFile.type)) { + const { JSZip } = await importJSZip(); const zip = await JSZip.loadAsync(typedFile); return zip.file(MANIFEST) !== null; diff --git a/src/io/state-file/schema.ts b/src/io/state-file/schema.ts index e136b7ddb..bcfdcfc97 100644 --- a/src/io/state-file/schema.ts +++ b/src/io/state-file/schema.ts @@ -1,4 +1,4 @@ -import JSZip from 'jszip'; +import type JSZip from 'jszip'; import { z } from 'zod'; import type { Vector3 } from '@kitware/vtk.js/types'; import vtkPiecewiseFunctionProxy, { diff --git a/src/io/zip.ts b/src/io/zip.ts index 73f988eed..96dfae0a1 100644 --- a/src/io/zip.ts +++ b/src/io/zip.ts @@ -1,8 +1,10 @@ -import JSZip from 'jszip'; import { basename, dirname } from '@/src/utils/path'; import { FileEntry } from './types'; +const importJSZip = () => import('@/src/lazy/lazyJSZip'); + export async function extractFilesFromZip(zipFile: File): Promise { + const { JSZip } = await importJSZip(); const zip = await JSZip.loadAsync(zipFile); const promises: Promise[] = []; const paths: string[] = []; diff --git a/src/lazy/index.ts b/src/lazy/index.ts new file mode 100644 index 000000000..2f3b05127 --- /dev/null +++ b/src/lazy/index.ts @@ -0,0 +1,25 @@ +import { config as configAwsSdk } from './lazyAwsSdk'; +import { config as configJSZip } from './lazyJSZip'; + +interface Config { + autoChunk: Array; +} + +const configs = [configAwsSdk, configJSZip].filter( + (config): config is Config => { + const autoChunk = config?.autoChunk; + if (!Array.isArray(autoChunk)) return false; + return autoChunk.every((pattern) => pattern instanceof RegExp); + } +); + +/** + * Determines if we should let rollup handle chunking on a given ID. + * + * Only runs on node_modules. See vite.config.ts for more info. + */ +export const shouldAutoChunk = (id: string) => { + return configs.some((config) => { + return config.autoChunk.some((pattern) => pattern.test(id)); + }); +}; diff --git a/src/lazy/lazyAwsSdk.ts b/src/lazy/lazyAwsSdk.ts new file mode 100644 index 000000000..e8c25f5b6 --- /dev/null +++ b/src/lazy/lazyAwsSdk.ts @@ -0,0 +1,4 @@ +export { S3Client, ListObjectsV2Command } from '@aws-sdk/client-s3'; +export const config = { + autoChunk: [/@aws-(sdk|crypto)/], +}; diff --git a/src/lazy/lazyJSZip.ts b/src/lazy/lazyJSZip.ts new file mode 100644 index 000000000..6e140dd2c --- /dev/null +++ b/src/lazy/lazyJSZip.ts @@ -0,0 +1,4 @@ +export { default as JSZip } from 'jszip'; +export const config = { + autoChunk: [/jszip/], +}; diff --git a/vite.config.ts b/vite.config.ts index 73fd1c485..5a5673d77 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -10,6 +10,7 @@ import { sentryVitePlugin } from '@sentry/vite-plugin'; import replace from '@rollup/plugin-replace'; import pkgLock from './package-lock.json'; +import { shouldAutoChunk } from './src/lazy'; function resolve(...args) { return normalizePath(resolvePath(...args)); @@ -43,9 +44,18 @@ export default defineConfig({ return 'vuetify'; } if (id.includes('vtk.js')) { + if (id.includes('OpenGL')) { + return 'vtk.js-opengl'; + } return 'vtk.js'; } if (id.includes('node_modules')) { + if (shouldAutoChunk(id)) { + return undefined; + } + if (id.includes('whatwg-url')) { + return 'whatwg-url'; + } return 'vendor'; } return undefined;