From 221f9b5cc1079a2bfb418f452a1a940948774a3e Mon Sep 17 00:00:00 2001 From: Ruicong Date: Tue, 17 Aug 2021 04:51:55 +0800 Subject: [PATCH] fix(css): dynamic import css abnormal after build (#3333) * fix(css): dynamic import css abnormal after build * fix(css): dynamic import css abnormal after build * fix: dynamicIndex * fix: typo & clear removedPureCssFiles in buildStart * fix: depend on the resolved config * fix: assert Co-authored-by: patak * fix: assert Co-authored-by: patak Co-authored-by: patak --- .../__tests__/dynamic-import.spec.ts | 10 ++++++++ .../playground/dynamic-import/css/index.css | 2 ++ packages/playground/dynamic-import/index.html | 1 + .../playground/dynamic-import/nested/index.js | 5 ++++ packages/vite/src/node/plugins/css.ts | 9 +++++++ .../src/node/plugins/importAnalysisBuild.ts | 24 ++++++++++++++++--- 6 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 packages/playground/dynamic-import/css/index.css diff --git a/packages/playground/dynamic-import/__tests__/dynamic-import.spec.ts b/packages/playground/dynamic-import/__tests__/dynamic-import.spec.ts index 292cdb2e861b4b..061c9f613a8b2e 100644 --- a/packages/playground/dynamic-import/__tests__/dynamic-import.spec.ts +++ b/packages/playground/dynamic-import/__tests__/dynamic-import.spec.ts @@ -45,3 +45,13 @@ test('should load dynamic import with vars', async () => { await page.click('.bar') await untilUpdated(() => page.textContent('.view'), 'Bar view', true) }) + +// dynamic import css +test('should load dynamic import with css', async () => { + await page.click('.css') + await untilUpdated( + () => page.$eval('.css', (node) => window.getComputedStyle(node).boxSizing), + 'border-box', + true + ) +}) diff --git a/packages/playground/dynamic-import/css/index.css b/packages/playground/dynamic-import/css/index.css new file mode 100644 index 00000000000000..9d3790dabe47cf --- /dev/null +++ b/packages/playground/dynamic-import/css/index.css @@ -0,0 +1,2 @@ +.css { box-sizing: border-box; } +.view { color: red; } diff --git a/packages/playground/dynamic-import/index.html b/packages/playground/dynamic-import/index.html index 3039d9eadf3c00..c87ef2a17f48d5 100644 --- a/packages/playground/dynamic-import/index.html +++ b/packages/playground/dynamic-import/index.html @@ -7,6 +7,7 @@ +
diff --git a/packages/playground/dynamic-import/nested/index.js b/packages/playground/dynamic-import/nested/index.js index 48a7cb7f924c38..1a118ecc79051b 100644 --- a/packages/playground/dynamic-import/nested/index.js +++ b/packages/playground/dynamic-import/nested/index.js @@ -65,6 +65,11 @@ document.querySelector('.issue-2658-2').addEventListener('click', async () => { text('.view', msg) }) +document.querySelector('.css').addEventListener('click', async () => { + await import('../css/index.css') + text('.view', 'dynamic import css') +}) + function text(el, text) { document.querySelector(el).textContent = text } diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 1956918658008f..794e300cf3f176 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -120,6 +120,11 @@ export const chunkToEmittedCssFileMap = new WeakMap< Set >() +export const removedPureCssFilesCache = new WeakMap< + ResolvedConfig, + Map +>() + const postcssConfigCache = new WeakMap< ResolvedConfig, PostCSSConfigResult | null @@ -150,6 +155,8 @@ export function cssPlugin(config: ResolvedConfig): Plugin { // Ensure a new cache for every build (i.e. rebuilding in watch mode) moduleCache = new Map>() cssModulesCache.set(config, moduleCache) + + removedPureCssFilesCache.set(config, new Map()) }, async transform(raw, id) { @@ -471,7 +478,9 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin { ) } } + const removedPureCssFiles = removedPureCssFilesCache.get(config)! pureCssChunks.forEach((fileName) => { + removedPureCssFiles.set(fileName, bundle[fileName] as RenderedChunk) delete bundle[fileName] }) } diff --git a/packages/vite/src/node/plugins/importAnalysisBuild.ts b/packages/vite/src/node/plugins/importAnalysisBuild.ts index bf619c46712b70..85f031d678ed14 100644 --- a/packages/vite/src/node/plugins/importAnalysisBuild.ts +++ b/packages/vite/src/node/plugins/importAnalysisBuild.ts @@ -4,7 +4,7 @@ import { Plugin } from '../plugin' import MagicString from 'magic-string' import { ImportSpecifier, init, parse as parseImports } from 'es-module-lexer' import { OutputChunk } from 'rollup' -import { chunkToEmittedCssFileMap } from './css' +import { chunkToEmittedCssFileMap, removedPureCssFilesCache } from './css' import { transformImportGlob } from '../importGlob' /** @@ -232,10 +232,11 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin { if (imports.length) { const s = new MagicString(code) for (let index = 0; index < imports.length; index++) { - const { s: start, e: end } = imports[index] + const { s: start, e: end, d: dynamicIndex } = imports[index] // check the chunk being imported const url = code.slice(start, end) const deps: Set = new Set() + let hasRemovedPureCssChunk = false if (url[0] === `"` && url[url.length - 1] === `"`) { const ownerFilename = chunk.fileName @@ -255,6 +256,21 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin { }) } chunk.imports.forEach(addDeps) + } else { + const removedPureCssFiles = + removedPureCssFilesCache.get(config)! + const chunk = removedPureCssFiles.get(filename) + if (chunk) { + const cssFiles = chunkToEmittedCssFileMap.get(chunk) + if (cssFiles && cssFiles.size > 0) { + cssFiles.forEach((file) => { + deps.add(config.base + file) + }) + hasRemovedPureCssChunk = true + } + + s.overwrite(dynamicIndex, end + 1, 'Promise.resolve({})') + } } } const normalizedFile = path.posix.join( @@ -276,7 +292,9 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin { markPos + preloadMarker.length + 1, // the dep list includes the main chunk, so only need to // preload when there are actual other deps. - deps.size > 1 + deps.size > 1 || + // main chunk is removed + (hasRemovedPureCssChunk && deps.size > 0) ? `[${[...deps].map((d) => JSON.stringify(d)).join(',')}]` : `[]` )