Skip to content

Commit

Permalink
fix: do not include css string in bundle if not needed
Browse files Browse the repository at this point in the history
This reduces bundle size when using esbuild as minifier.
  • Loading branch information
yyx990803 committed Sep 15, 2021
1 parent 15bb5a1 commit 3e3c203
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 8 deletions.
7 changes: 6 additions & 1 deletion packages/vite/src/node/plugins/css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ const cssModuleRE = new RegExp(`\\.module${cssLangs}`)
const directRequestRE = /(\?|&)direct\b/
const commonjsProxyRE = /\?commonjs-proxy/
const inlineRE = /(\?|&)inline\b/
const usedRE = /(\?|&)used\b/

const enum PreprocessLang {
less = 'less',
Expand Down Expand Up @@ -315,7 +316,11 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin {
}

return {
code: modulesCode || `export default ${JSON.stringify(css)}`,
code:
modulesCode ||
(usedRE.test(id)
? `export default ${JSON.stringify(css)}`
: `export default ''`),
map: { mappings: '' },
// avoid the css module from being tree-shaken so that we can retrieve
// it in renderChunk()
Expand Down
34 changes: 27 additions & 7 deletions packages/vite/src/node/plugins/importAnalysisBuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ 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, removedPureCssFilesCache } from './css'
import {
chunkToEmittedCssFileMap,
isCSSRequest,
removedPureCssFilesCache
} from './css'
import { transformImportGlob } from '../importGlob'
import { bareImportRE } from '../utils'

/**
* A flag for injected helpers. This flag will be set to `false` if the output
Expand Down Expand Up @@ -116,7 +121,7 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
let imports: readonly ImportSpecifier[] = []
try {
imports = parseImports(source)[0]
} catch (e) {
} catch (e: any) {
this.error(e, e.idx)
}

Expand All @@ -133,15 +138,15 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
s: start,
e: end,
ss: expStart,
n: specifier,
d: dynamicIndex
} = imports[index]

const isGlob =
// import.meta.glob
if (
source.slice(start, end) === 'import.meta' &&
source.slice(end, end + 5) === '.glob'

// import.meta.glob
if (isGlob) {
) {
const { importsString, exp, endIndex, isEager } =
await transformImportGlob(
source,
Expand All @@ -167,6 +172,21 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
const replacement = `${preloadMethod}(() => ${original},${isModernFlag}?"${preloadMarker}":void 0)`
str().overwrite(dynamicIndex, dynamicEnd, replacement)
}

// Differentiate CSS imports that use the default export from those that
// do not by injecting a ?used query - this allows us to avoid including
// the CSS string when unnecessary (esbuild has trouble treeshaking
// them)
if (
specifier &&
isCSSRequest(specifier) &&
source.slice(expStart, start).includes('from') &&
// edge case for package names ending with .css (e.g normalize.css)
!(bareImportRE.test(specifier) && !specifier.includes('/'))
) {
const url = specifier.replace(/\?|$/, (m) => `?used${m ? '&' : ''}`)
str().overwrite(start, end, dynamicIndex > -1 ? `'${url}'` : url)
}
}

if (
Expand Down Expand Up @@ -225,7 +245,7 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
let imports: ImportSpecifier[]
try {
imports = parseImports(code)[0].filter((i) => i.d > -1)
} catch (e) {
} catch (e: any) {
this.error(e, e.idx)
}

Expand Down

0 comments on commit 3e3c203

Please sign in to comment.