Skip to content

Commit

Permalink
fix(plugin-legacy): don't force terser on non-legacy (fix #6266)
Browse files Browse the repository at this point in the history
This fixes two misbehaviors of the legacy plugin:

1. Respect {minify: false} for legacy assets.
2. Don't inflict es2019/terser on non-legacy chunks.

For the first problem, we could have fixed by checking for false in
viteLegacyPlugin.config(). Unfortunately that would have left the second
problem unsolved. Without adding significant complexity to the config,
there's no easy way to use different minifiers in the build depending on
the individual chunk.

So instead we include terserPlugin() whenever minify is enabled, even
true or 'esbuild', then check the actual configuration in the plugin.
This allows the legacy plugin to inject its special override, leaving
all the non-legacy stuff intact and uncomplicated.

See also, previous attempts: #5157 #5168
  • Loading branch information
agriffis committed Dec 27, 2021
1 parent 1f945f6 commit 3e0e4fd
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 20 deletions.
22 changes: 21 additions & 1 deletion packages/playground/legacy/__tests__/legacy.spec.ts
@@ -1,4 +1,9 @@
import { isBuild, readManifest, untilUpdated } from '../../testUtils'
import {
findAssetFile,
isBuild,
readManifest,
untilUpdated
} from '../../testUtils'

test('should work', async () => {
expect(await page.textContent('#app')).toMatch('Hello')
Expand Down Expand Up @@ -53,4 +58,19 @@ if (isBuild) {
'../../../vite/legacy-polyfills'
)
})

test('should minify legacy chunks with terser', async () => {
// This is a ghetto heuristic, but terser output seems to reliably start
// with one of the following, and non-terser output (including unminified or
// ebuild-minified) does not!
const terserPatt = /^(?:!function|System.register)/

expect(findAssetFile(/chunk-async-legacy/)).toMatch(terserPatt)
expect(findAssetFile(/chunk-async\./)).not.toMatch(terserPatt)
expect(findAssetFile(/immutable-chunk-legacy/)).toMatch(terserPatt)
expect(findAssetFile(/immutable-chunk\./)).not.toMatch(terserPatt)
expect(findAssetFile(/index-legacy/)).toMatch(terserPatt)
expect(findAssetFile(/index\./)).not.toMatch(terserPatt)
expect(findAssetFile(/polyfills-legacy/)).toMatch(terserPatt)
})
}
22 changes: 5 additions & 17 deletions packages/plugin-legacy/index.js
Expand Up @@ -105,23 +105,6 @@ function viteLegacyPlugin(options = {}) {
name: 'vite:legacy-generate-polyfill-chunk',
apply: 'build',

config() {
return {
build: {
minify: 'terser'
}
}
},

configResolved(config) {
if (!config.build.ssr && genLegacy && config.build.minify === 'esbuild') {
throw new Error(
`Can't use esbuild as the minifier when targeting legacy browsers ` +
`because esbuild minification is not legacy safe.`
)
}
},

async generateBundle(opts, bundle) {
if (config.build.ssr) {
return
Expand Down Expand Up @@ -297,6 +280,11 @@ function viteLegacyPlugin(options = {}) {
// legacy-unsafe code - e.g. rewriting object properties into shorthands
opts.__vite_skip_esbuild__ = true

// @ts-ignore force terser for legacy chunks. This only takes effect if
// minification isn't disabled, because that leaves out the terser plugin
// entirely.
opts.__vite_force_terser__ = true

const needPolyfills =
options.polyfills !== false && !Array.isArray(options.polyfills)

Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-legacy/package.json
Expand Up @@ -33,6 +33,6 @@
"systemjs": "^6.11.0"
},
"peerDependencies": {
"vite": "^2.0.0"
"vite": "^2.7.8"
}
}
2 changes: 1 addition & 1 deletion packages/vite/src/node/build.ts
Expand Up @@ -365,7 +365,7 @@ export function resolveBuildPlugins(config: ResolvedConfig): {
post: [
buildImportAnalysisPlugin(config),
buildEsbuildPlugin(config),
...(options.minify === 'terser' ? [terserPlugin(config)] : []),
...(options.minify ? [terserPlugin(config)] : []),
...(options.manifest ? [manifestPlugin(config)] : []),
...(options.ssrManifest ? [ssrManifestPlugin(config)] : []),
buildReporterPlugin(config),
Expand Down
11 changes: 11 additions & 0 deletions packages/vite/src/node/plugins/terser.ts
Expand Up @@ -21,6 +21,17 @@ export function terserPlugin(config: ResolvedConfig): Plugin {
name: 'vite:terser',

async renderChunk(code, _chunk, outputOptions) {
// This plugin is included for any non-false value of config.build.minify,
// so that normal chunks can use the preferred minifier, and legacy chunks
// can use terser.
if (
config.build.minify !== 'terser' &&
// @ts-ignore injected by @vitejs/plugin-legacy
!outputOptions.__vite_force_terser__
) {
return null
}

// Do not minify ES lib output since that would remove pure annotations
// and break tree-shaking
if (config.build.lib && outputOptions.format === 'es') {
Expand Down

0 comments on commit 3e0e4fd

Please sign in to comment.