diff --git a/packages/vite/src/node/__tests__/plugins/css.spec.ts b/packages/vite/src/node/__tests__/plugins/css.spec.ts index 3c2431aa6f56ec..bb6e7d60c1cc65 100644 --- a/packages/vite/src/node/__tests__/plugins/css.spec.ts +++ b/packages/vite/src/node/__tests__/plugins/css.spec.ts @@ -310,6 +310,7 @@ require("other-module");` const replacer = getEmptyChunkReplacer(['pure_css_chunk.js'], 'cjs') const newCode = replacer(code) + expect(newCode.length).toBe(code.length) expect(newCode).toMatchInlineSnapshot( `"require("some-module"),/* empty css */require("other-module");"`, ) @@ -317,14 +318,30 @@ require("other-module");` expect(newCode).not.toContain('pure_css_chunk.js') }) + test('replaces require call in minified code that uses comma operator 2', () => { + const code = 'require("pure_css_chunk.js"),console.log();' + const replacer = getEmptyChunkReplacer(['pure_css_chunk.js'], 'cjs') + const newCode = replacer(code) + expect(newCode.length).toBe(code.length) + expect(newCode).toMatchInlineSnapshot( + `"/* empty css */console.log();"`, + ) + // So there should be no pure css chunk anymore + expect(newCode).not.toContain('pure_css_chunk.js') + }) + test('replaces require call in minified code that uses comma operator followed by assignment', () => { const code = 'require("some-module"),require("pure_css_chunk.js");const v=require("other-module");' const replacer = getEmptyChunkReplacer(['pure_css_chunk.js'], 'cjs') - expect(replacer(code)).toMatchInlineSnapshot( + const newCode = replacer(code) + expect(newCode.length).toBe(code.length) + expect(newCode).toMatchInlineSnapshot( `"require("some-module");/* empty css */const v=require("other-module");"`, ) + // So there should be no pure css chunk anymore + expect(newCode).not.toContain('pure_css_chunk.js') }) }) diff --git a/packages/vite/src/node/build.ts b/packages/vite/src/node/build.ts index d06c1657a43952..933ba5bdd0e5d8 100644 --- a/packages/vite/src/node/build.ts +++ b/packages/vite/src/node/build.ts @@ -167,10 +167,10 @@ export interface BuildEnvironmentOptions { sourcemap?: boolean | 'inline' | 'hidden' /** * Set to `false` to disable minification, or specify the minifier to use. - * Available options are 'terser' or 'esbuild'. - * @default 'esbuild' + * Available options are 'terser' or 'esbuild' or 'oxc'. + * @default 'oxc' */ - minify?: boolean | 'terser' | 'esbuild' + minify?: boolean | 'terser' | 'esbuild' | 'oxc' /** * Options for terser * https://terser.org/docs/api-reference#minify-options @@ -418,7 +418,7 @@ export function resolveBuildEnvironmentOptions( { ...buildEnvironmentOptionsDefaults, cssCodeSplit: !raw.lib, - minify: consumer === 'server' ? false : 'esbuild', + minify: consumer === 'server' ? false : 'oxc', rollupOptions: { platform: consumer === 'server' ? 'node' : 'browser', }, @@ -438,7 +438,7 @@ export function resolveBuildEnvironmentOptions( if ((merged.minify as string) === 'false') { merged.minify = false } else if (merged.minify === true) { - merged.minify = 'esbuild' + merged.minify = 'oxc' } const defaultModulePreload = { @@ -777,6 +777,7 @@ async function buildEnvironment( : path.posix.join(options.assetsDir, `[name]-[hash].[ext]`), inlineDynamicImports: output.format === 'umd' || output.format === 'iife', + minify: options.minify === 'oxc', ...output, } } diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 7424b5163bf37c..476c5897b25836 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -1151,10 +1151,15 @@ export function getEmptyChunkReplacer( code.replace( emptyChunkRE, // remove css import while preserving source map location - (m) => - outputFormat === 'es' - ? `/* empty css ${''.padEnd(m.length - 15)}*/` - : `${m.at(-1)}/* empty css ${''.padEnd(m.length - 16)}*/`, + (m, p1, p2) => { + if (outputFormat === 'es') { + return `/* empty css ${''.padEnd(m.length - 15)}*/` + } + if (p2 === ',') { + return `${p1}/* empty css ${''.padEnd(m.length - 15 - p1.length)}*/` + } + return `${p2}/* empty css ${''.padEnd(m.length - 16)}*/` + }, ) } diff --git a/packages/vite/src/node/plugins/worker.ts b/packages/vite/src/node/plugins/worker.ts index cbf1080973c3ec..fdb4ea16e8c785 100644 --- a/packages/vite/src/node/plugins/worker.ts +++ b/packages/vite/src/node/plugins/worker.ts @@ -116,6 +116,7 @@ async function bundleWorkerEntry( config.build.assetsDir, '[name]-[hash].[ext]', ), + minify: config.build.minify === 'oxc', ...workerConfig, format, sourcemap: config.build.sourcemap, diff --git a/playground/css-codesplit/__tests__/css-codesplit.spec.ts b/playground/css-codesplit/__tests__/css-codesplit.spec.ts index cc54d865a6795e..08fb60e45be145 100644 --- a/playground/css-codesplit/__tests__/css-codesplit.spec.ts +++ b/playground/css-codesplit/__tests__/css-codesplit.spec.ts @@ -55,7 +55,7 @@ describe.runIf(isBuild)('build', () => { expect(sharedCSSWithJSChunk).toMatch(`/* empty css`) // there are functions and modules in the src code that should be tree-shaken expect(sharedCSSWithJSChunk).not.toMatch('function') - expect(sharedCSSWithJSChunk).not.toMatch(/import(?!".\/modulepreload)/) + expect(sharedCSSWithJSChunk).not.toMatch(/import(?!\s*".\/modulepreload)/) }) test('should generate correct manifest', async () => { diff --git a/playground/js-sourcemap/__tests__/js-sourcemap.spec.ts b/playground/js-sourcemap/__tests__/js-sourcemap.spec.ts index 057a8d54efccdb..d38a19841a6c36 100644 --- a/playground/js-sourcemap/__tests__/js-sourcemap.spec.ts +++ b/playground/js-sourcemap/__tests__/js-sourcemap.spec.ts @@ -140,7 +140,7 @@ describe.runIf(isBuild)('build tests', () => { expect(formatSourcemapForSnapshot(JSON.parse(map))).toMatchInlineSnapshot(` { "ignoreList": [], - "mappings": ";4jCAAA,OAAO,6BAAuB,wBAE9B,QAAQ,IAAI", + "mappings": ";ypCAAA,OAAO,6BAAuB,wBAE9B,QAAQ,IAAI,wBAAuB", "sources": [ "../../after-preload-dynamic.js", ], diff --git a/playground/worker/__tests__/es/worker-es.spec.ts b/playground/worker/__tests__/es/worker-es.spec.ts index 659a838eaeddae..1bc039b712639f 100644 --- a/playground/worker/__tests__/es/worker-es.spec.ts +++ b/playground/worker/__tests__/es/worker-es.spec.ts @@ -104,7 +104,7 @@ describe.runIf(isBuild)('build', () => { ) // worker should have all imports resolved and no exports - expect(workerContent).not.toMatch(/import[^.]/) + expect(workerContent).not.toMatch(/import\s*["(]/) expect(workerContent).not.toMatch(/\bexport\b/) // chunk expect(content).toMatch(`new Worker("/es/assets`) @@ -113,7 +113,7 @@ describe.runIf(isBuild)('build', () => { expect(content).toMatch(`(self.URL||self.webkitURL).createObjectURL`) expect(content).toMatch(`self.Blob`) expect(content).toMatch( - /try\{if\(\w+=\w+&&\(self\.URL\|\|self\.webkitURL\)\.createObjectURL\(\w+\),!\w+\)throw""/, + /try\{\w+=\w+&&\(self\.URL\|\|self\.webkitURL\)\.createObjectURL\(\w+\)[;\w()!]+throw\s*""/, ) // inlined shared worker expect(content).toMatch( diff --git a/playground/worker/__tests__/relative-base/worker-relative-base.spec.ts b/playground/worker/__tests__/relative-base/worker-relative-base.spec.ts index 6121f331937275..e0726b37760863 100644 --- a/playground/worker/__tests__/relative-base/worker-relative-base.spec.ts +++ b/playground/worker/__tests__/relative-base/worker-relative-base.spec.ts @@ -75,7 +75,7 @@ describe.runIf(isBuild)('build', () => { ) // worker should have all imports resolved and no exports - expect(workerContent).not.toMatch(/import(?!\.)/) // accept import.meta.url + expect(workerContent).not.toMatch(/import\s*["(]/) expect(workerContent).not.toMatch(/\bexport\b/) // chunk expect(content).toMatch(`new Worker(""+new URL("../worker-entries/`)