diff --git a/docs/config/shared-options.md b/docs/config/shared-options.md index 774c35df42a5a5..c6a14b24cbc830 100644 --- a/docs/config/shared-options.md +++ b/docs/config/shared-options.md @@ -280,7 +280,7 @@ export default defineConfig({ }) ``` -When [`build.minify`](./build-options.md#build-minify) is `true`, you can configure to only minify [certain aspects](https://esbuild.github.io/api/#minify) of the code by setting either of `esbuild.minifyIdentifiers`, `esbuild.minifySyntax`, and `esbuild.minifyWhitespace` to `true`. Note the `esbuild.minify` option can't be used to override `build.minify`. +When [`build.minify`](./build-options.md#build-minify) is `true`, all minify optimizations are applied by default. To disable [certain aspects](https://esbuild.github.io/api/#minify) of it, set any of `esbuild.minifyIdentifiers`, `esbuild.minifySyntax`, or `esbuild.minifyWhitespace` options to `false`. Note the `esbuild.minify` option can't be used to override `build.minify`. Set to `false` to disable esbuild transforms. diff --git a/packages/vite/src/node/__tests__/plugins/esbuild.spec.ts b/packages/vite/src/node/__tests__/plugins/esbuild.spec.ts index 50e9183b46e64c..5f063301799cff 100644 --- a/packages/vite/src/node/__tests__/plugins/esbuild.spec.ts +++ b/packages/vite/src/node/__tests__/plugins/esbuild.spec.ts @@ -41,6 +41,31 @@ describe('resolveEsbuildTranspileOptions', () => { expect(options).toEqual(null) }) + test('resolve specific minify options', () => { + const options = resolveEsbuildTranspileOptions( + defineResolvedConfig({ + build: { + minify: 'esbuild' + }, + esbuild: { + keepNames: true, + minifyIdentifiers: false + } + }), + 'es' + ) + expect(options).toEqual({ + target: undefined, + format: 'esm', + keepNames: true, + minify: false, + minifyIdentifiers: false, + minifySyntax: true, + minifyWhitespace: true, + treeShaking: true + }) + }) + test('resolve no minify', () => { const options = resolveEsbuildTranspileOptions( defineResolvedConfig({ @@ -140,6 +165,7 @@ describe('resolveEsbuildTranspileOptions', () => { keepNames: true, minify: false, minifyIdentifiers: true, + minifySyntax: true, minifyWhitespace: false, treeShaking: true }) @@ -157,7 +183,7 @@ describe('resolveEsbuildTranspileOptions', () => { esbuild: { keepNames: true, minifyIdentifiers: true, - minifyWhitespace: true, + minifySyntax: false, treeShaking: true } }), @@ -169,6 +195,7 @@ describe('resolveEsbuildTranspileOptions', () => { keepNames: true, minify: false, minifyIdentifiers: true, + minifySyntax: false, minifyWhitespace: true, treeShaking: true }) diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 01c72d0c24edcc..50a835e9ad707c 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -19,6 +19,7 @@ import type Sass from 'sass' import type Stylus from 'stylus' import type Less from 'less' import type { Alias } from 'types/alias' +import type { TransformOptions } from 'esbuild' import { formatMessages, transform } from 'esbuild' import type { RawSourceMap } from '@ampproject/remapping' import { getCodeWithSourcemap, injectSourcesContent } from '../server/sourcemap' @@ -55,6 +56,7 @@ import { publicFileToBuiltUrl, resolveAssetFileNames } from './asset' +import type { ESBuildOptions } from './esbuild' // const debug = createDebugger('vite:css') @@ -1211,8 +1213,8 @@ async function minifyCSS(css: string, config: ResolvedConfig) { try { const { code, warnings } = await transform(css, { loader: 'css', - minify: true, - target: config.build.cssTarget || undefined + target: config.build.cssTarget || undefined, + ...resolveEsbuildMinifyOptions(config.esbuild || {}) }) if (warnings.length) { const msgs = await formatMessages(warnings, { kind: 'warning' }) @@ -1231,6 +1233,24 @@ async function minifyCSS(css: string, config: ResolvedConfig) { } } +function resolveEsbuildMinifyOptions( + options: ESBuildOptions +): TransformOptions { + if ( + options.minifyIdentifiers != null || + options.minifySyntax != null || + options.minifyWhitespace != null + ) { + return { + minifyIdentifiers: options.minifyIdentifiers ?? true, + minifySyntax: options.minifySyntax ?? true, + minifyWhitespace: options.minifyWhitespace ?? true + } + } else { + return { minify: true } + } +} + export async function hoistAtRules(css: string): Promise { const s = new MagicString(css) const cleanCss = emptyCssComments(css) diff --git a/packages/vite/src/node/plugins/esbuild.ts b/packages/vite/src/node/plugins/esbuild.ts index ee1c36db651849..42e5bbac76316a 100644 --- a/packages/vite/src/node/plugins/esbuild.ts +++ b/packages/vite/src/node/plugins/esbuild.ts @@ -318,15 +318,17 @@ export function resolveEsbuildTranspileOptions( // If user enable fine-grain minify options, minify with their options instead if ( - options.minifyIdentifiers || - options.minifySyntax || - options.minifyWhitespace + options.minifyIdentifiers != null || + options.minifySyntax != null || + options.minifyWhitespace != null ) { if (isEsLibBuild) { // Disable minify whitespace as it breaks tree-shaking return { ...options, minify: false, + minifyIdentifiers: options.minifyIdentifiers ?? true, + minifySyntax: options.minifySyntax ?? true, minifyWhitespace: false, treeShaking: true } @@ -334,6 +336,9 @@ export function resolveEsbuildTranspileOptions( return { ...options, minify: false, + minifyIdentifiers: options.minifyIdentifiers ?? true, + minifySyntax: options.minifySyntax ?? true, + minifyWhitespace: options.minifyWhitespace ?? true, treeShaking: true } } diff --git a/playground/minify/__tests__/minify.spec.ts b/playground/minify/__tests__/minify.spec.ts new file mode 100644 index 00000000000000..b8d4e458e968b8 --- /dev/null +++ b/playground/minify/__tests__/minify.spec.ts @@ -0,0 +1,18 @@ +import fs from 'node:fs' +import path from 'node:path' +import { expect, test } from 'vitest' +import { isBuild, readFile, testDir } from '~utils' + +test.runIf(isBuild)('no minifySyntax', () => { + const assetsDir = path.resolve(testDir, 'dist/assets') + const files = fs.readdirSync(assetsDir) + + const jsFile = files.find((f) => f.endsWith('.js')) + const jsContent = readFile(path.resolve(assetsDir, jsFile)) + + const cssFile = files.find((f) => f.endsWith('.css')) + const cssContent = readFile(path.resolve(assetsDir, cssFile)) + + expect(jsContent).toContain('{console.log("hello world")}') + expect(cssContent).toContain('color:#ff0000') +}) diff --git a/playground/minify/index.html b/playground/minify/index.html new file mode 100644 index 00000000000000..1b599018cd92b6 --- /dev/null +++ b/playground/minify/index.html @@ -0,0 +1,3 @@ +

Minify

+ + diff --git a/playground/minify/main.js b/playground/minify/main.js new file mode 100644 index 00000000000000..e77c8a997b3314 --- /dev/null +++ b/playground/minify/main.js @@ -0,0 +1,5 @@ +import './test.css' + +if (window) { + console.log('hello world') +} diff --git a/playground/minify/package.json b/playground/minify/package.json new file mode 100644 index 00000000000000..e46abf8c4b218c --- /dev/null +++ b/playground/minify/package.json @@ -0,0 +1,11 @@ +{ + "name": "test-minify", + "private": true, + "version": "0.0.0", + "scripts": { + "dev": "vite", + "build": "vite build", + "debug": "node --inspect-brk ../../packages/vite/bin/vite", + "preview": "vite preview" + } +} diff --git a/playground/minify/test.css b/playground/minify/test.css new file mode 100644 index 00000000000000..dab6f886b3cf82 --- /dev/null +++ b/playground/minify/test.css @@ -0,0 +1,4 @@ +h1 { + /* do not minify as red text */ + color: #ff0000; +} diff --git a/playground/minify/vite.config.js b/playground/minify/vite.config.js new file mode 100644 index 00000000000000..43eca91a5c0f30 --- /dev/null +++ b/playground/minify/vite.config.js @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' + +export default defineConfig({ + esbuild: { + minifySyntax: false + } +})