vue-cli项目非production环境开启terser压缩

132 阅读2分钟

启用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熟组。

image.png

js对象表示node,node对象上有个variable,表示当前作用域中的所有变量,每一个变量使用对象表示,key为变量名称,value是一个对象,对象上的mangled_name表示mangle后的变量名称。 image.png 在遍历AST时,收集所有node上的variable,将其存放在to_mangle数组中。遍历后,调用mangle()方法设置mangled_name

image.png

输出的时候,将mangled_name替换原始name

image.png