diff --git a/.chronus/changes/playground-speed-init-2026-1-23-16-10-50.md b/.chronus/changes/playground-speed-init-2026-1-23-16-10-50.md new file mode 100644 index 00000000000..a2d135195d7 --- /dev/null +++ b/.chronus/changes/playground-speed-init-2026-1-23-16-10-50.md @@ -0,0 +1,8 @@ +--- +# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking +changeKind: fix +packages: + - "@typespec/playground" +--- + +Optimization: Fetch all libraries in parallel diff --git a/packages/playground/src/browser-host.ts b/packages/playground/src/browser-host.ts index 0845abcf9b6..3e4b23250e9 100644 --- a/packages/playground/src/browser-host.ts +++ b/packages/playground/src/browser-host.ts @@ -21,25 +21,38 @@ export function createBrowserHostInternal(options: BrowserHostCreateOptions): Br const virtualFs = new Map(); const jsImports = new Map>(); - const libraries = options.libraries; - for (const [libName, { _TypeSpecLibrary_ }] of Object.entries(libraries)) { - for (const [key, value] of Object.entries(_TypeSpecLibrary_.typespecSourceFiles)) { + const libraries: Record = { + ...options.libraries, + }; + + function registerLibraryFiles( + libName: string, + lib: PlaygroundTspLibrary & { _TypeSpecLibrary_: any }, + ) { + for (const [key, value] of Object.entries(lib._TypeSpecLibrary_.typespecSourceFiles)) { virtualFs.set(`/test/node_modules/${libName}/${key}`, value); } - for (const [key, value] of Object.entries(_TypeSpecLibrary_.jsSourceFiles)) { + for (const [key, value] of Object.entries(lib._TypeSpecLibrary_.jsSourceFiles)) { addJsImport(`/test/node_modules/${libName}/${key}`, value); } } - virtualFs.set( - `/test/package.json`, - JSON.stringify({ - name: "playground-pkg", - dependencies: Object.fromEntries( - Object.values(libraries).map((x) => [x.name, x.packageJson.version]), - ), - }), - ); + function updatePackageJson() { + virtualFs.set( + `/test/package.json`, + JSON.stringify({ + name: "playground-pkg", + dependencies: Object.fromEntries( + Object.values(libraries).map((x) => [x.name, x.packageJson.version]), + ), + }), + ); + } + + for (const [libName, lib] of Object.entries(libraries)) { + registerLibraryFiles(libName, lib); + } + updatePackageJson(); function addJsImport(path: string, value: any) { virtualFs.set(path, ""); @@ -170,6 +183,35 @@ export function createBrowserHostInternal(options: BrowserHostCreateOptions): Br }; } +/** + * Load libraries in parallel from the given list. + * @param libsToLoad List of library names. Must be available in the webpage importmap. + * @param importOptions Import configuration. + */ +export async function loadLibraries( + libsToLoad: readonly string[], + importOptions: LibraryImportOptions = {}, +): Promise> { + const entries = await Promise.all( + libsToLoad.map(async (libName) => { + const { _TypeSpecLibrary_, $lib, $linter } = (await importLibrary( + libName, + importOptions, + )) as any; + const lib: PlaygroundTspLibrary & { _TypeSpecLibrary_: any } = { + name: libName, + isEmitter: $lib?.emitter, + definition: $lib, + packageJson: JSON.parse(_TypeSpecLibrary_.typespecSourceFiles["package.json"]), + linter: $linter, + _TypeSpecLibrary_, + }; + return [libName, lib] as const; + }), + ); + return Object.fromEntries(entries); +} + /** * Create the browser host from the list of libraries. * @param libsToLoad List of libraries to load. Those must be set in the webpage importmap. @@ -180,23 +222,12 @@ export async function createBrowserHost( libsToLoad: readonly string[], importOptions: LibraryImportOptions = {}, ): Promise { - const libraries: Record = {}; - for (const libName of libsToLoad) { - const { _TypeSpecLibrary_, $lib, $linter } = (await importLibrary( - libName, - importOptions, - )) as any; - libraries[libName] = { - name: libName, - isEmitter: $lib?.emitter, - definition: $lib, - packageJson: JSON.parse(_TypeSpecLibrary_.typespecSourceFiles["package.json"]), - linter: $linter, - _TypeSpecLibrary_, - }; - } + const [libraries, compiler] = await Promise.all([ + loadLibraries(libsToLoad, importOptions), + importTypeSpecCompiler(importOptions), + ]); return createBrowserHostInternal({ - compiler: await importTypeSpecCompiler(importOptions), + compiler, libraries, }); }