Skip to content

Commit 1da104e

Browse files
authored
fix: don't force terser on non-legacy (fix vitejs#6266) (vitejs#6272)
1 parent 5279de6 commit 1da104e

File tree

5 files changed

+59
-34
lines changed

5 files changed

+59
-34
lines changed

packages/playground/legacy/__tests__/legacy.spec.ts

+21-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import { isBuild, readManifest, untilUpdated } from '../../testUtils'
1+
import {
2+
findAssetFile,
3+
isBuild,
4+
readManifest,
5+
untilUpdated
6+
} from '../../testUtils'
27

38
test('should work', async () => {
49
expect(await page.textContent('#app')).toMatch('Hello')
@@ -53,4 +58,19 @@ if (isBuild) {
5358
'../../../vite/legacy-polyfills'
5459
)
5560
})
61+
62+
test('should minify legacy chunks with terser', async () => {
63+
// This is a ghetto heuristic, but terser output seems to reliably start
64+
// with one of the following, and non-terser output (including unminified or
65+
// ebuild-minified) does not!
66+
const terserPatt = /^(?:!function|System.register)/
67+
68+
expect(findAssetFile(/chunk-async-legacy/)).toMatch(terserPatt)
69+
expect(findAssetFile(/chunk-async\./)).not.toMatch(terserPatt)
70+
expect(findAssetFile(/immutable-chunk-legacy/)).toMatch(terserPatt)
71+
expect(findAssetFile(/immutable-chunk\./)).not.toMatch(terserPatt)
72+
expect(findAssetFile(/index-legacy/)).toMatch(terserPatt)
73+
expect(findAssetFile(/index\./)).not.toMatch(terserPatt)
74+
expect(findAssetFile(/polyfills-legacy/)).toMatch(terserPatt)
75+
})
5676
}

packages/plugin-legacy/index.js

+5-17
Original file line numberDiff line numberDiff line change
@@ -105,23 +105,6 @@ function viteLegacyPlugin(options = {}) {
105105
name: 'vite:legacy-generate-polyfill-chunk',
106106
apply: 'build',
107107

108-
config() {
109-
return {
110-
build: {
111-
minify: 'terser'
112-
}
113-
}
114-
},
115-
116-
configResolved(config) {
117-
if (!config.build.ssr && genLegacy && config.build.minify === 'esbuild') {
118-
throw new Error(
119-
`Can't use esbuild as the minifier when targeting legacy browsers ` +
120-
`because esbuild minification is not legacy safe.`
121-
)
122-
}
123-
},
124-
125108
async generateBundle(opts, bundle) {
126109
if (config.build.ssr) {
127110
return
@@ -297,6 +280,11 @@ function viteLegacyPlugin(options = {}) {
297280
// legacy-unsafe code - e.g. rewriting object properties into shorthands
298281
opts.__vite_skip_esbuild__ = true
299282

283+
// @ts-ignore force terser for legacy chunks. This only takes effect if
284+
// minification isn't disabled, because that leaves out the terser plugin
285+
// entirely.
286+
opts.__vite_force_terser__ = true
287+
300288
const needPolyfills =
301289
options.polyfills !== false && !Array.isArray(options.polyfills)
302290

packages/plugin-legacy/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,6 @@
3333
"systemjs": "^6.11.0"
3434
},
3535
"peerDependencies": {
36-
"vite": "^2.0.0"
36+
"vite": "^2.7.8"
3737
}
3838
}

packages/vite/src/node/build.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ export function resolveBuildPlugins(config: ResolvedConfig): {
365365
post: [
366366
buildImportAnalysisPlugin(config),
367367
buildEsbuildPlugin(config),
368-
...(options.minify === 'terser' ? [terserPlugin(config)] : []),
368+
...(options.minify ? [terserPlugin(config)] : []),
369369
...(options.manifest ? [manifestPlugin(config)] : []),
370370
...(options.ssrManifest ? [ssrManifestPlugin(config)] : []),
371371
buildReporterPlugin(config),

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

+31-14
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,46 @@ import type { Terser } from 'types/terser'
44
import type { ResolvedConfig } from '..'
55

66
export function terserPlugin(config: ResolvedConfig): Plugin {
7-
const worker = new Worker(
8-
(basedir: string, code: string, options: Terser.MinifyOptions) => {
9-
// when vite is linked, the worker thread won't share the same resolve
10-
// root with vite itself, so we have to pass in the basedir and resolve
11-
// terser first.
12-
// eslint-disable-next-line node/no-restricted-require
13-
const terserPath = require.resolve('terser', {
14-
paths: [basedir]
15-
})
16-
return require(terserPath).minify(code, options) as Terser.MinifyOutput
17-
}
18-
)
7+
const makeWorker = () =>
8+
new Worker(
9+
(basedir: string, code: string, options: Terser.MinifyOptions) => {
10+
// when vite is linked, the worker thread won't share the same resolve
11+
// root with vite itself, so we have to pass in the basedir and resolve
12+
// terser first.
13+
// eslint-disable-next-line node/no-restricted-require
14+
const terserPath = require.resolve('terser', {
15+
paths: [basedir]
16+
})
17+
return require(terserPath).minify(code, options) as Terser.MinifyOutput
18+
}
19+
)
20+
21+
let worker: ReturnType<typeof makeWorker>
1922

2023
return {
2124
name: 'vite:terser',
2225

2326
async renderChunk(code, _chunk, outputOptions) {
27+
// This plugin is included for any non-false value of config.build.minify,
28+
// so that normal chunks can use the preferred minifier, and legacy chunks
29+
// can use terser.
30+
if (
31+
config.build.minify !== 'terser' &&
32+
// @ts-ignore injected by @vitejs/plugin-legacy
33+
!outputOptions.__vite_force_terser__
34+
) {
35+
return null
36+
}
37+
2438
// Do not minify ES lib output since that would remove pure annotations
25-
// and break tree-shaking
39+
// and break tree-shaking.
2640
if (config.build.lib && outputOptions.format === 'es') {
2741
return null
2842
}
2943

44+
// Lazy load worker.
45+
worker ||= makeWorker()
46+
3047
const res = await worker.run(__dirname, code, {
3148
safari10: true,
3249
...config.build.terserOptions,
@@ -41,7 +58,7 @@ export function terserPlugin(config: ResolvedConfig): Plugin {
4158
},
4259

4360
closeBundle() {
44-
worker.stop()
61+
worker?.stop()
4562
}
4663
}
4764
}

0 commit comments

Comments
 (0)