启用terser压缩,文件大小可缩小1/10
vue-cli4 默认已配置terser-webpack-plugin, vue-cli4 中的terser默认只在生产环境下有效。
如果需要在其他环境中开启,需要在对应环境的.env配置文件中将NODE_ENV设置为production。
antv terser压缩前文件大小为21.3MB;
antv terser压缩后文件大小为2.3MB。
terser压缩案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>terser测试</div>
<script src="https://cdn.jsdelivr.net/npm/source-map@0.7.3/dist/source-map.js"></script>
<script src="https://cdn.jsdelivr.net/npm/terser/dist/bundle.min.js"></script>
<script>
async function test() {
var cacheFileName = "/tmp/cache.json";
var options = {
mangle: {
toplevel: true,
},
sourceMap: true,
nameCache: {}
};
var code = {
"file1.js":
`function add(first, second) {
function adduuuuuu(forth, fifth) {
console.log('ssdd')
return forth + fifth;
}
return first + second + adduuuuuu(forth, fifth);
}
function devision(first, second) {
return first / second;
}
function multi(first, second) {
return first * second;
}
function sub(first, second) {
return first - second;
}
`,
"file2.js": `console.log(addooooooooo(1 + 2, 3 + 4));`,
"file3.js":
`function add(first, second) {
return first + second;
}
devision(1, 2);
multi(1, 2);
sub(1, 2);
`
};
var result = await Terser.minify(code, options);
console.log(result);
console.log(options);
}
test()
</script>
</body>
</html>
输出的result结果如下:
{
"code": "function o(o,n){return o+n+function(o,n){return console.log(\"ssdd\"),o+n}(forth,fifth)}function n(o,n){return o/n}function t(o,n){return o*n}function r(o,n){return o-n}function o(o,n){return o+n}console.log(addooooooooo(3,7)),n(1,2),t(1,2),r(1,2);",
"map": "{\"version\":3,\"sources\":[\"file1.js\",\"file3.js\",\"file2.js\"],\"names\":[\"add\",\"first\",\"second\",\"forth\",\"fifth\",\"console\",\"log\",\"adduuuuuu\",\"devision\",\"multi\",\"sub\",\"addooooooooo\"],\"mappings\":\"AAAA,SAASA,EAAIC,EAAOC,GAKI,OAAOD,EAAQC,EAJf,SAAmBC,EAAOC,GAEtB,OADAC,QAAQC,IAAI,QACLH,EAAQC,CACnB,CACwBG,CAAUJ,MAAOC,MAC7C,CAEA,SAASI,EAASP,EAAOC,GACrB,OAAOD,EAAQC,CACnB,CAEA,SAASO,EAAMR,EAAOC,GAClB,OAAOD,EAAQC,CACnB,CAEA,SAASQ,EAAIT,EAAOC,GAChB,OAAOD,EAAQC,CACnB,CClBpB,SAASF,EAAIC,EAAOC,GACA,OAAOD,EAAQC,CAClB,CCFjBG,QAAQC,IAAIK,aAAa,EAAO,IDIfH,EAAS,EAAG,GAEZC,EAAM,EAAG,GAETC,EAAI,EAAG\"}",
"decoded_map": null
}
输入的nameCache结果如下:
{
"vars": {
"props": {
"$add": "o",
"$devision": "n",
"$multi": "t",
"$sub": "r"
}
}
}
nameCache(默认为null)-如果您希望在多次调用minify()时缓存mangled的变量和属性名,请传递一个空对象{}或以前使用的nameCache对象。注意:这是一个读/写属性。minify()将读取此对象的名称缓存状态,并在minify过程中更新它,以便用户可以重用或外部持久化它。
实现原理
在terser源码中,定义了一个名称为to_mangle熟组。
js对象表示node,node对象上有个variable,表示当前作用域中的所有变量,每一个变量使用对象表示,key为变量名称,value是一个对象,对象上的mangled_name表示mangle后的变量名称。
在遍历AST时,收集所有node上的
variable,将其存放在to_mangle数组中。遍历后,调用mangle()方法设置mangled_name。
输出的时候,将mangled_name替换原始name