Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a top-level terser option to allow users to customize the minifier #6752

Merged
merged 10 commits into from Oct 22, 2021
142 changes: 106 additions & 36 deletions packages/@vue/cli-service/lib/config/terserOptions.js
@@ -1,40 +1,110 @@
module.exports = options => ({
terserOptions: {
compress: {
// turn off flags with small gains to speed up minification
arrows: false,
collapse_vars: false, // 0.3kb
comparisons: false,
computed_props: false,
hoist_funs: false,
hoist_props: false,
hoist_vars: false,
inline: false,
loops: false,
negate_iife: false,
properties: false,
reduce_funcs: false,
reduce_vars: false,
switches: false,
toplevel: false,
typeofs: false,

// a few flags with noticeable gains/speed ratio
// numbers based on out of the box vendor bundle
booleans: true, // 0.7kb
if_return: true, // 0.4kb
sequences: true, // 0.7kb
unused: true, // 2.3kb

// required features to drop conditional branches
conditionals: true,
dead_code: true,
evaluate: true
// @ts-check
const TerserPlugin = require('terser-webpack-plugin')

const genTerserOptions = (defaultOptions, options) => {
const userOptions = options.terser && options.terser.terserOptions
// user's config is first
return {
...defaultOptions,
...userOptions
}
}

const terserMinify = (options) => ({
terserOptions: genTerserOptions(
{
compress: {
// turn off flags with small gains to speed up minification
arrows: false,
collapse_vars: false, // 0.3kb
comparisons: false,
computed_props: false,
hoist_funs: false,
hoist_props: false,
hoist_vars: false,
inline: false,
loops: false,
negate_iife: false,
properties: false,
reduce_funcs: false,
reduce_vars: false,
switches: false,
toplevel: false,
typeofs: false,

// a few flags with noticeable gains/speed ratio
// numbers based on out of the box vendor bundle
booleans: true, // 0.7kb
if_return: true, // 0.4kb
sequences: true, // 0.7kb
unused: true, // 2.3kb

// required features to drop conditional branches
conditionals: true,
dead_code: true,
evaluate: true
},
mangle: {
safari10: true
}
},
mangle: {
safari10: true
}
},
options
),
parallel: options.parallel,
extractComments: false
})

// `terserOptions` options will be passed to `esbuild`
// Link to options - https://esbuild.github.io/api/#minify
const esbuildMinify = (options) => ({
minify: TerserPlugin.esbuildMinify,
terserOptions: genTerserOptions(
{
minify: false,
minifyWhitespace: true,
minifyIdentifiers: false,
minifySyntax: true
},
options
),
parallel: options.parallel
})

// `terserOptions` options will be passed to `swc` (`@swc/core`)
// Link to options - https://swc.rs/docs/config-js-minify
const swcMinify = (options) => ({
minify: TerserPlugin.swcMinify,
terserOptions: genTerserOptions(
{
compress: {
unused: true
},
mangle: true
},
options
),
parallel: options.parallel
})

// `terserOptions` options will be passed to `uglify-js`
// Link to options - https://github.com/mishoo/UglifyJS#minify-options
const uglifyJsMinify = (options) => ({
minify: TerserPlugin.uglifyJsMinify,
terserOptions: genTerserOptions({}, options),
parallel: options.parallel
})

// Currently we do not allow custom minify function
const getMinify = (options) => {
const { minify = 'default' } = options.terser || {}

const minifyMap = {
default: terserMinify,
esbuild: esbuildMinify,
swc: swcMinify,
uglifyJs: uglifyJsMinify
}
return minifyMap[minify](options)
}

module.exports = getMinify
6 changes: 6 additions & 0 deletions packages/@vue/cli-service/lib/options.js
Expand Up @@ -59,6 +59,12 @@ const schema = createSchema(joi => joi.object({
lintOnSave: joi.any().valid(true, false, 'error', 'warning', 'default'),
pwa: joi.object(),

// terser
terser: joi.object({
minify: joi.string().valid('default', 'esbuild', 'swc', 'uglifyJs'),
screetBloom marked this conversation as resolved.
Show resolved Hide resolved
terserOptions: joi.object()
}),

// 3rd party plugin options
pluginOptions: joi.object()
}))
Expand Down
27 changes: 27 additions & 0 deletions packages/@vue/cli-service/types/ProjectOptions.d.ts
@@ -1,6 +1,8 @@
import ChainableWebpackConfig = require('webpack-chain')
import { Configuration as WebpackOptions } from 'webpack'

type PredefinedOptions<T> = T & { [key: string]: any }

type PageEntry = string | string[];

interface PageConfig {
Expand Down Expand Up @@ -153,6 +155,31 @@ interface ProjectOptions {
*/
pwa?: object;

/**
* set terser-webpack-plugin minify and terserOptions
*/
terser?: {
/**
* Supported minify: [default(terser)](https://github.com/webpack-contrib/terser-webpack-plugin#minify), [esbuild](https://github.com/webpack-contrib/terser-webpack-plugin#esbuild), [swc](https://github.com/webpack-contrib/terser-webpack-plugin#swc), [uglifyJs](https://github.com/webpack-contrib/terser-webpack-plugin#uglify-js). currently we do not allow custom minify function
*
* In the non-default case, you should install the corresponding package (eg. `npm i esbuild -D`)
*
*/
minify: 'default' | 'esbuild' | 'swc' | 'uglifyJs';
/**
* `terserOptions` options will be passed to minify
*
* [All options for `terser`](https://github.com/webpack-contrib/terser-webpack-plugin#terseroptions)
*
* [All options for `esbuild`](https://github.com/evanw/esbuild/blob/master/lib/shared/types.ts#L160-L174)
*
* [All options for `swc`](https://swc.rs/docs/config-js-minify)
*
* [All options for `uglifyJs`](https://github.com/mishoo/UglifyJS#minify-options)
*/
terserOptions?: PredefinedOptions<import("terser").MinifyOptions>;
};

/**
* This is an object that doesn't go through any schema validation, so it can be used to pass arbitrary options to 3rd party plugins
*/
Expand Down