Skip to content

Commit df997d0

Browse files
Copilotsapphi-red
andauthored
feat(lib): enable minification but keep pure annotations for es output with terser (#20522)
Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: sapphi-red <[email protected]>
1 parent 4d01112 commit df997d0

File tree

5 files changed

+58
-8
lines changed

5 files changed

+58
-8
lines changed

packages/vite/src/node/plugins/terser.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,6 @@ export function terserPlugin(config: ResolvedConfig): Plugin {
9797
return null
9898
}
9999

100-
// Do not minify ES lib output since that would remove pure annotations
101-
// and break tree-shaking.
102-
if (config.build.lib && outputOptions.format === 'es') {
103-
return null
104-
}
105-
106100
// Lazy load worker.
107101
worker ||= makeWorker()
108102

@@ -111,6 +105,14 @@ export function terserPlugin(config: ResolvedConfig): Plugin {
111105
const res = await worker.run(terserPath, code, {
112106
safari10: true,
113107
...terserOptions,
108+
format: {
109+
...terserOptions.format,
110+
// For ES lib mode, preserve comments to keep pure annotations for tree-shaking
111+
preserve_annotations:
112+
config.build.lib && outputOptions.format === 'es'
113+
? true
114+
: terserOptions.format?.preserve_annotations,
115+
},
114116
sourceMap: !!outputOptions.sourcemap,
115117
module: outputOptions.format.startsWith('es'),
116118
toplevel: outputOptions.format === 'cjs',

playground/lib/__tests__/lib.spec.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,21 @@ describe.runIf(isBuild)('build', () => {
8282
expect(umd).toMatch('process.env.NODE_ENV')
8383
})
8484

85+
test('debugger statements are removed by terser for es', () => {
86+
const terserEs = readFile('dist/terser/my-lib-custom-filename.js')
87+
expect(terserEs).not.toMatch('debugger')
88+
})
89+
90+
test('pure annotations are not removed by terser for es', () => {
91+
const terserEs = readFile('dist/terser/my-lib-custom-filename.js')
92+
expect(terserEs).toMatch(/[@#]__PURE__/)
93+
})
94+
95+
test('pure annotations are removed by terser for non-es output', () => {
96+
const terserIife = readFile('dist/terser/my-lib-custom-filename.iife.js')
97+
expect(terserIife).not.toMatch(/[@#]__PURE__/)
98+
})
99+
85100
test('single entry with css', () => {
86101
const css = readFile('dist/css-single-entry/test-my-lib.css')
87102
const js = readFile('dist/css-single-entry/test-my-lib.js')

playground/lib/__tests__/serve.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,12 @@ export async function serve(): Promise<{ close(): Promise<void> }> {
108108
configFile: path.resolve(__dirname, '../vite.css-code-split.config.js'),
109109
})
110110

111+
await build({
112+
root: rootDir,
113+
logLevel: 'warn', // output esbuild warns
114+
configFile: path.resolve(__dirname, '../vite.terser.config.js'),
115+
})
116+
111117
// start static file server
112118
const serve = sirv(path.resolve(rootDir, 'dist'))
113119
const httpServer = http.createServer((req, res) => {

playground/lib/src/main.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export default function myLib(sel) {
1+
export default /* @__PURE__ */ Object.assign(function myLib(sel) {
22
// Force esbuild spread helpers (https://github.com/evanw/esbuild/issues/951)
33
console.log({ ...'foo' })
44

@@ -9,7 +9,10 @@ export default function myLib(sel) {
99

1010
// make sure umd helper has been moved to the right position
1111
console.log(`amd function(){ "use strict"; }`)
12-
}
12+
13+
// eslint-disable-next-line no-debugger
14+
debugger
15+
})
1316

1417
// For triggering unhandled global esbuild helpers in previous regex-based implementation for injection
1518
;(function () {})()?.foo
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import path from 'node:path'
2+
import { defineConfig } from 'vite'
3+
import baseConfig from './vite.config'
4+
5+
export default defineConfig({
6+
...baseConfig,
7+
build: {
8+
...baseConfig.build,
9+
minify: 'terser',
10+
terserOptions: {
11+
compress: {
12+
drop_debugger: true,
13+
},
14+
},
15+
outDir: 'dist/terser',
16+
lib: {
17+
...baseConfig.build.lib,
18+
entry: path.resolve(__dirname, 'src/main.js'),
19+
formats: ['es', 'iife'],
20+
},
21+
},
22+
plugins: [],
23+
cacheDir: 'node_modules/.vite-terser',
24+
})

0 commit comments

Comments
 (0)