From a1682451e9c420cdc43c4fffd7fd66890baedf25 Mon Sep 17 00:00:00 2001 From: sapphi-red Date: Mon, 3 Apr 2023 22:03:30 +0900 Subject: [PATCH 1/3] perf(css): cache lazy import --- packages/vite/src/node/plugins/css.ts | 68 +++++++++++++++++---------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 1ea8cba9c510d9..0c83933c75a5b5 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -891,7 +891,9 @@ async function compileCSS( if (needInlineImport) { postcssPlugins.unshift( - (await import('postcss-import')).default({ + ( + await lazyImport('postcss-import', () => import('postcss-import')) + ).default({ async resolve(id, basedir) { const publicFile = checkPublicFile(id, config) if (publicFile) { @@ -926,7 +928,9 @@ async function compileCSS( if (isModule) { postcssPlugins.unshift( - (await import('postcss-modules')).default({ + ( + await lazyImport('postcss-modules', () => import('postcss-modules')) + ).default({ ...modulesOptions, localsConvention: modulesOptions?.localsConvention, getJSON( @@ -963,31 +967,30 @@ async function compileCSS( let postcssResult: PostCSS.Result try { const source = removeDirectQuery(id) + const postcss = await lazyImport('postcss', () => import('postcss')) // postcss is an unbundled dep and should be lazy imported - postcssResult = await (await import('postcss')) - .default(postcssPlugins) - .process(code, { - ...postcssOptions, - parser: - lang === 'sss' - ? loadPreprocessor(PostCssDialectLang.sss, config.root) - : postcssOptions.parser, - to: source, - from: source, - ...(devSourcemap - ? { - map: { - inline: false, - annotation: false, - // postcss may return virtual files - // we cannot obtain content of them, so this needs to be enabled - sourcesContent: true, - // when "prev: preprocessorMap", the result map may include duplicate filename in `postcssResult.map.sources` - // prev: preprocessorMap, - }, - } - : {}), - }) + postcssResult = await postcss.default(postcssPlugins).process(code, { + ...postcssOptions, + parser: + lang === 'sss' + ? loadPreprocessor(PostCssDialectLang.sss, config.root) + : postcssOptions.parser, + to: source, + from: source, + ...(devSourcemap + ? { + map: { + inline: false, + annotation: false, + // postcss may return virtual files + // we cannot obtain content of them, so this needs to be enabled + sourcesContent: true, + // when "prev: preprocessorMap", the result map may include duplicate filename in `postcssResult.map.sources` + // prev: preprocessorMap, + }, + } + : {}), + }) // record CSS dependencies from @imports for (const message of postcssResult.messages) { @@ -1055,6 +1058,19 @@ async function compileCSS( } } +const lazyImportCache = new Map() +function lazyImport(name: string, imp: () => Promise): T | Promise { + const cached = lazyImportCache.get(name) + if (cached) return cached + + const promise = imp().then((module) => { + lazyImportCache.set(name, module) + return module + }) + lazyImportCache.set(name, promise) + return promise +} + export interface PreprocessCSSResult { code: string map?: SourceMapInput From e956ffbf110fae89c390dddf1ada57028068aa50 Mon Sep 17 00:00:00 2001 From: sapphi-red Date: Tue, 4 Apr 2023 00:28:47 +0900 Subject: [PATCH 2/3] refactor: rename to `cachedImport` --- packages/vite/src/node/plugins/css.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 0c83933c75a5b5..b2093b63f1c13b 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -892,7 +892,7 @@ async function compileCSS( if (needInlineImport) { postcssPlugins.unshift( ( - await lazyImport('postcss-import', () => import('postcss-import')) + await cachedImport('postcss-import', () => import('postcss-import')) ).default({ async resolve(id, basedir) { const publicFile = checkPublicFile(id, config) @@ -929,7 +929,7 @@ async function compileCSS( if (isModule) { postcssPlugins.unshift( ( - await lazyImport('postcss-modules', () => import('postcss-modules')) + await cachedImport('postcss-modules', () => import('postcss-modules')) ).default({ ...modulesOptions, localsConvention: modulesOptions?.localsConvention, @@ -967,7 +967,7 @@ async function compileCSS( let postcssResult: PostCSS.Result try { const source = removeDirectQuery(id) - const postcss = await lazyImport('postcss', () => import('postcss')) + const postcss = await cachedImport('postcss', () => import('postcss')) // postcss is an unbundled dep and should be lazy imported postcssResult = await postcss.default(postcssPlugins).process(code, { ...postcssOptions, @@ -1059,7 +1059,7 @@ async function compileCSS( } const lazyImportCache = new Map() -function lazyImport(name: string, imp: () => Promise): T | Promise { +function cachedImport(name: string, imp: () => Promise): T | Promise { const cached = lazyImportCache.get(name) if (cached) return cached From 648d455ac006ebf3186e23bb123b00bd04a5aa0a Mon Sep 17 00:00:00 2001 From: sapphi-red Date: Tue, 4 Apr 2023 00:37:52 +0900 Subject: [PATCH 3/3] refactor: avoid creating function everytime --- packages/vite/src/node/plugins/css.ts | 44 ++++++++++++++++----------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index b2093b63f1c13b..238357d400fed6 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -891,9 +891,7 @@ async function compileCSS( if (needInlineImport) { postcssPlugins.unshift( - ( - await cachedImport('postcss-import', () => import('postcss-import')) - ).default({ + (await importPostcssImport()).default({ async resolve(id, basedir) { const publicFile = checkPublicFile(id, config) if (publicFile) { @@ -928,9 +926,7 @@ async function compileCSS( if (isModule) { postcssPlugins.unshift( - ( - await cachedImport('postcss-modules', () => import('postcss-modules')) - ).default({ + (await importPostcssModules()).default({ ...modulesOptions, localsConvention: modulesOptions?.localsConvention, getJSON( @@ -967,7 +963,7 @@ async function compileCSS( let postcssResult: PostCSS.Result try { const source = removeDirectQuery(id) - const postcss = await cachedImport('postcss', () => import('postcss')) + const postcss = await importPostcss() // postcss is an unbundled dep and should be lazy imported postcssResult = await postcss.default(postcssPlugins).process(code, { ...postcssOptions, @@ -1059,17 +1055,31 @@ async function compileCSS( } const lazyImportCache = new Map() -function cachedImport(name: string, imp: () => Promise): T | Promise { - const cached = lazyImportCache.get(name) - if (cached) return cached - - const promise = imp().then((module) => { - lazyImportCache.set(name, module) - return module - }) - lazyImportCache.set(name, promise) - return promise +function createCachedImport( + name: string, + imp: () => Promise, +): () => T | Promise { + return () => { + const cached = lazyImportCache.get(name) + if (cached) return cached + + const promise = imp().then((module) => { + lazyImportCache.set(name, module) + return module + }) + lazyImportCache.set(name, promise) + return promise + } } +const importPostcssImport = createCachedImport( + 'postcss-import', + () => import('postcss-import'), +) +const importPostcssModules = createCachedImport( + 'postcss-modules', + () => import('postcss-modules'), +) +const importPostcss = createCachedImport('postcss', () => import('postcss')) export interface PreprocessCSSResult { code: string