diff --git a/docs/config/build-options.md b/docs/config/build-options.md index 4da08cf49d22d0..b9971fdb383f64 100644 --- a/docs/config/build-options.md +++ b/docs/config/build-options.md @@ -117,6 +117,13 @@ It should only be used when you are targeting a non-mainstream browser. One example is Android WeChat WebView, which supports most modern JavaScript features but not the [`#RGBA` hexadecimal color notation in CSS](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#rgb_colors). In this case, you need to set `build.cssTarget` to `chrome61` to prevent vite from transform `rgba()` colors into `#RGBA` hexadecimal notations. +## build.cssMinify + +- **Type:** `boolean` +- **Default:** the same as [`build.minify`](#build-minify) + +This option allows users to override CSS minification specifically instead of defaulting to `build.minify`, so you can configure minification for JS and CSS separately. Vite uses `esbuild` to minify CSS. + ## build.sourcemap - **Type:** `boolean | 'inline' | 'hidden'` diff --git a/packages/vite/src/node/build.ts b/packages/vite/src/node/build.ts index 503d94811391d6..527f0e9fbac204 100644 --- a/packages/vite/src/node/build.ts +++ b/packages/vite/src/node/build.ts @@ -127,6 +127,12 @@ export interface BuildOptions { * @default target */ cssTarget?: TransformOptions['target'] | false + /** + * Override CSS minification specifically instead of defaulting to `build.minify`, + * so you can configure minification for JS and CSS separately. + * @default minify + */ + cssMinify?: boolean /** * If `true`, a separate sourcemap file will be created. If 'inline', the * sourcemap will be appended to the resulting output file as data URI. @@ -409,6 +415,10 @@ export function resolveBuildOptions( resolved.minify = 'esbuild' } + if (resolved.cssMinify == null) { + resolved.cssMinify = !!resolved.minify + } + return resolved } diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 4956a90ca5fff9..a2dd0738add156 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -437,7 +437,7 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin { code = modulesCode } else { let content = css - if (config.build.minify) { + if (config.build.cssMinify) { content = await minifyCSS(content, config) } code = `export default ${JSON.stringify(content)}` @@ -1124,7 +1124,7 @@ async function finalizeCss( if (css.includes('@import') || css.includes('@charset')) { css = await hoistAtRules(css) } - if (minify && config.build.minify) { + if (minify && config.build.cssMinify) { css = await minifyCSS(css, config) } return css diff --git a/playground/css/__tests__/no-css-minify/no-css-minify.spec.ts b/playground/css/__tests__/no-css-minify/no-css-minify.spec.ts new file mode 100644 index 00000000000000..4fbc816cd1ee7b --- /dev/null +++ b/playground/css/__tests__/no-css-minify/no-css-minify.spec.ts @@ -0,0 +1,14 @@ +import { describe, expect, test } from 'vitest' +import { findAssetFile, isBuild } from '~utils' + +describe.runIf(isBuild)('no css minify', () => { + test('js minified but css not minified', () => { + expect(findAssetFile(/index-\w+\.js$/, 'no-css-minify')).not.toMatch( + '(function polyfill() {', + ) + expect(findAssetFile(/index-\w+\.css$/, 'no-css-minify')).toMatch(`\ +.test-minify { + color: rgba(255, 255, 0, 0.7); +}`) + }) +}) diff --git a/playground/css/__tests__/no-css-minify/vite.config.js b/playground/css/__tests__/no-css-minify/vite.config.js new file mode 100644 index 00000000000000..260e7f253520be --- /dev/null +++ b/playground/css/__tests__/no-css-minify/vite.config.js @@ -0,0 +1 @@ +module.exports = require('../../vite.config-no-css-minify') diff --git a/playground/css/package.json b/playground/css/package.json index 22ccc686d75ef8..6ae9aeec5bea05 100644 --- a/playground/css/package.json +++ b/playground/css/package.json @@ -9,7 +9,10 @@ "preview": "vite preview", "dev:relative-base": "vite --config ./vite.config-relative-base.js dev", "build:relative-base": "vite --config ./vite.config-relative-base.js build", - "preview:relative-base": "vite --config ./vite.config-relative-base.js preview" + "preview:relative-base": "vite --config ./vite.config-relative-base.js preview", + "dev:no-css-minify": "vite --config ./vite.config-no-css-minify.js dev", + "build:no-css-minify": "vite --config ./vite.config-no-css-minify.js build", + "preview:no-css-minify": "vite --config ./vite.config-no-css-minify.js preview" }, "devDependencies": { "@vitejs/test-css-dep": "link:./css-dep", diff --git a/playground/css/vite.config-no-css-minify.js b/playground/css/vite.config-no-css-minify.js new file mode 100644 index 00000000000000..99f739318a2fef --- /dev/null +++ b/playground/css/vite.config-no-css-minify.js @@ -0,0 +1,14 @@ +const baseConfig = require('./vite.config.js') + +/** + * @type {import('vite').UserConfig} + */ +module.exports = { + ...baseConfig, + build: { + ...baseConfig.build, + outDir: 'dist/no-css-minify', + minify: true, + cssMinify: false, + }, +}