From d2c3d8b70b2df6e16f053a7ac58e6b04e7b2078f Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 15 Jun 2023 16:38:44 +0800 Subject: [PATCH] perf(compiler-sfc): lazy require typescript --- .../compileScript/resolveType.spec.ts | 2 +- .../compiler-sfc/src/script/resolveType.ts | 44 ++++++++++++------- packages/vue/compiler-sfc/register-ts.js | 2 +- 3 files changed, 30 insertions(+), 18 deletions(-) diff --git a/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts b/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts index 85d67e01cb8..607654a952b 100644 --- a/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts +++ b/packages/compiler-sfc/__tests__/compileScript/resolveType.spec.ts @@ -10,7 +10,7 @@ import { } from '../../src/script/resolveType' import ts from 'typescript' -registerTS(ts) +registerTS(() => ts) describe('resolveType', () => { test('type literal', () => { diff --git a/packages/compiler-sfc/src/script/resolveType.ts b/packages/compiler-sfc/src/script/resolveType.ts index d30150a82d5..146c454729c 100644 --- a/packages/compiler-sfc/src/script/resolveType.ts +++ b/packages/compiler-sfc/src/script/resolveType.ts @@ -708,13 +708,14 @@ function resolveGlobalScope(ctx: TypeResolveContext): TypeScope[] | undefined { } } -let ts: typeof TS +let ts: typeof TS | undefined +let loadTS: (() => typeof TS) | undefined /** * @private */ -export function registerTS(_ts: any) { - ts = _ts +export function registerTS(_loadTS: () => typeof TS) { + loadTS = _loadTS } type FS = NonNullable @@ -723,7 +724,10 @@ function resolveFS(ctx: TypeResolveContext): FS | undefined { if (ctx.fs) { return ctx.fs } - const fs = ctx.options.fs || ts.sys + if (!ts && loadTS) { + ts = loadTS() + } + const fs = ctx.options.fs || ts?.sys if (!fs) { return } @@ -779,22 +783,25 @@ function importSourceToScope( } else { // module or aliased import - use full TS resolution, only supported in Node if (!__NODE_JS__) { - ctx.error( + return ctx.error( `Type import from non-relative sources is not supported in the browser build.`, node, scope ) } if (!ts) { - ctx.error( - `Failed to resolve import source ${JSON.stringify(source)}. ` + - `typescript is required as a peer dep for vue in order ` + - `to support resolving types from module imports.`, - node, - scope - ) + if (loadTS) ts = loadTS() + if (!ts) { + return ctx.error( + `Failed to resolve import source ${JSON.stringify(source)}. ` + + `typescript is required as a peer dep for vue in order ` + + `to support resolving types from module imports.`, + node, + scope + ) + } } - resolved = resolveWithTS(scope.filename, source, fs) + resolved = resolveWithTS(scope.filename, source, ts, fs) } if (resolved) { resolved = scope.resolvedImportSources[source] = normalizePath(resolved) @@ -839,6 +846,7 @@ const tsConfigRefMap = new Map() function resolveWithTS( containingFile: string, source: string, + ts: typeof TS, fs: FS ): string | undefined { if (!__NODE_JS__) return @@ -853,7 +861,7 @@ function resolveWithTS( const normalizedConfigPath = normalizePath(configPath) const cached = tsConfigCache.get(normalizedConfigPath) if (!cached) { - configs = loadTSConfig(configPath, fs).map(config => ({ config })) + configs = loadTSConfig(configPath, ts, fs).map(config => ({ config })) tsConfigCache.set(normalizedConfigPath, configs) } else { configs = cached @@ -918,7 +926,11 @@ function resolveWithTS( } } -function loadTSConfig(configPath: string, fs: FS): TS.ParsedCommandLine[] { +function loadTSConfig( + configPath: string, + ts: typeof TS, + fs: FS +): TS.ParsedCommandLine[] { // The only case where `fs` is NOT `ts.sys` is during tests. // parse config host requires an extra `readDirectory` method // during tests, which is stubbed. @@ -940,7 +952,7 @@ function loadTSConfig(configPath: string, fs: FS): TS.ParsedCommandLine[] { if (config.projectReferences) { for (const ref of config.projectReferences) { tsConfigRefMap.set(ref.path, configPath) - res.unshift(...loadTSConfig(ref.path, fs)) + res.unshift(...loadTSConfig(ref.path, ts, fs)) } } return res diff --git a/packages/vue/compiler-sfc/register-ts.js b/packages/vue/compiler-sfc/register-ts.js index 87f61b64863..7a073b3a3f8 100644 --- a/packages/vue/compiler-sfc/register-ts.js +++ b/packages/vue/compiler-sfc/register-ts.js @@ -1,5 +1,5 @@ if (typeof require !== 'undefined') { try { - require('@vue/compiler-sfc').registerTS(require('typescript')) + require('@vue/compiler-sfc').registerTS(() => require('typescript')) } catch (e) {} }