美文网首页
JavaScript 混淆压缩

JavaScript 混淆压缩

作者: ZONE画派 | 来源:发表于2019-01-26 22:35 被阅读31次

JavaScript 混淆压缩

原由

  • JavaScript 是一种解释型脚本语言(代码不进行预编译)。是直接解析源码运行的,也就是“裸奔”的。
  • 运行时需要基于源代码,所以每一个采用了 JavaScript 的设备,都能提取出 JavaScript 源码。代码安全性难以维护。
  • 基于以上原因,需要考虑进行 JavaScript 源码的 “保护” 。
  • 由于 JavaScript 解释型语言的特点,完全加密不太现实,可以考虑的方向是增加代码的“不可读性”。

如何增加 JavaScript 源码的不可读性

  • 增加 JavaScript 代码的不可读性,主要有三个方面:压缩(Compression)、混淆(Obfuscation) 和 加密(Encryption)。

压缩(Compression)

    1. 这一操作的目的,是让最终代码传输量 (不代表代码量, 也不代表文件体积)尽可能小。压缩 JS 的工具,常见的有:YUI Compressor(雅虎)、UglifyClosure Compiler(Google) 等。
    1. 通常在代码压缩的过程中,只改变代码的语法,代码的语义和控制流不会有太大改变
    1. 常见做法是把局部变量缩短化,把一些运算进行等价替换等。代码压缩对于代码保护有一些帮助,但由于语义和控制流基本没变,起不了太大作用
    1. 在压缩层面上,代码不可读只是一种附带伤害,不是最终目的。

混淆(Obfuscation)

    1. 这一操作的目的,是让代码尽可能地不可读,主要用作代码保护。
    1. 让代码不可读,增加分析的难度,这是唯一目的。混淆过后文件体积变大一倍也没关系,代码量变多也没关系,运算慢50% 也没关系。
    1. 常见的做法有:分离常量、打乱控制流、增加无义代码、检查运行环境如果不对就罢工,等等。
    1. 在混淆层面上,代码不可读是最终目的。
    1. 值得一提的是,Google Closure Compiler 的 Advance Level Compression 会压缩类和对象的成员,其压缩结果很难分析,也可以认为是一种混淆,但兼容性不太好。

混淆的例子:

decent-messup

加密(Encryption)

    1. 加密在 Web 界有太多歧义了。这里特指 代码加密将代码明文进行可逆的变换
    1. 一般用eval方法加密,效果与混淆相似,也做到了压缩的效果。
    1. 实际上大部分 JS 加密只是对源码进行了一个字符串变换,没有深入到代码语法层面。

加密的例子:

jsfuck

各种工具效果对比

测试代码


'use strict';

let cal_days_labels = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
let cal_months_labels = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
const cal_days_in_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
let cal_current_date = new Date();
const cal_week_start = 0;   // 0:sun, 1:mon, ...
let cal_is_empty = true;

let cal_year = 2000,
    cal_month = 1,
    cal_day = 1;

function Calendar(year, month, day) {
    cal_day = day;
    cal_month = month;
    cal_year = year;
}

Calendar.prototype.generateHTML = function () {
    let firstDay = new Date(cal_year, cal_month, 1);
    let startingDay = firstDay.getDay();
    startingDay = (startingDay + 7 - cal_week_start) % 7;
    let lMonthLength = cal_days_in_month[(cal_month - 1 + cal_days_in_month.length) % cal_days_in_month.length];
    let monthLength = cal_days_in_month[cal_month];
    if ((cal_month === 1) && ((cal_year % 4 === 0 && cal_year % 100 !== 0) || cal_year % 400 === 0)) {
        monthLength = 29;
    } else if ((cal_month === 2) && ((cal_year % 4 === 0 && cal_year % 100 !== 0) || cal_year % 400 === 0)) {
        lMonthLength = 29;
    }
    let monthName = cal_months_labels[cal_month];
    // document.getElementById("c-capt").innerHTML = `${monthName} ${cal_year}`;
    let html = '';
    for (let i = 0; i < cal_days_labels.length; i++) {
        html += `<div class="dayname">${cal_days_labels[(cal_week_start + i) % 7]}</div>`;
    }
    document.getElementById("c-head").innerHTML = html;
    html = '';
    let day = 1;
    let looping = true;
    let bIsYearMonth = (cal_current_date.getMonth() === cal_month && cal_current_date.getFullYear() === cal_year);
    for (let i = 0; i < 9 && looping; i++) {
        html += '<div class="c-drow">';
        for (let j = 0; j < cal_days_labels.length; j++) {
            if (j < startingDay && i === 0) {
                html += `<div class="day last">${(lMonthLength - startingDay + j)}`;
            } else if (i > 0 || j >= startingDay) {
                if (day <= monthLength) {
                    if(day === cal_day && bIsYearMonth) {
                        html += `<div class="day"><div class="current">${day}</div>`;
                    } else {
                        html += `<div class="day">${day}`;
                    }
                } else if (day > monthLength) {
                    html += `<div class="day next">${(day - monthLength)}`;
                    looping = false;
                }

                ++day;
            }
            html += '</div>';
        }
        html += '</div>';
    }
    document.getElementById("c-days").innerHTML = html;
    cal_is_empty = false;
};

var cal = new Calendar(2018,12,28);
cal.generateHTML();

YUI Compressor (压缩)


"use strict";var cal_days_labels=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];var cal_months_labels=["January","February","March","April","May","June","July","August","September","October","November","December"];var cal_days_in_month=[31,28,31,30,31,30,31,31,30,31,30,31];var cal_current_date=new Date();var cal_week_start=0;var cal_is_empty=true;var cal_year=2000,cal_month=1,cal_day=1;function Calendar(year,month,day){cal_day=day;cal_month=month;cal_year=year}Calendar.prototype.generateHTML=function(){var firstDay=new Date(cal_year,cal_month,1);var startingDay=firstDay.getDay();startingDay=(startingDay+7-cal_week_start)%7;var lMonthLength=cal_days_in_month[(cal_month-1+cal_days_in_month.length)%cal_days_in_month.length];var monthLength=cal_days_in_month[cal_month];if(cal_month===1&&(cal_year%4===0&&cal_year%100!==0||cal_year%400===0)){monthLength=29}else{if(cal_month===2&&(cal_year%4===0&&cal_year%100!==0||cal_year%400===0)){lMonthLength=29}}var monthName=cal_months_labels[cal_month];var html="";for(var i=0;i<cal_days_labels.length;i++){html+='<div class="dayname">'+cal_days_labels[(cal_week_start+i)%7]+"</div>"}document.getElementById("c-head").innerHTML=html;html="";var day=1;var looping=true;var bIsYearMonth=cal_current_date.getMonth()===cal_month&&cal_current_date.getFullYear()===cal_year;for(var _i=0;_i<9&&looping;_i++){html+='<div class="c-drow">';for(var j=0;j<cal_days_labels.length;j++){if(j<startingDay&&_i===0){html+='<div class="day last">'+(lMonthLength-startingDay+j)}else{if(_i>0||j>=startingDay){if(day<=monthLength){if(day===cal_day&&bIsYearMonth){html+='<div class="day"><div class="current">'+day+"</div>"}else{html+='<div class="day">'+day}}else{if(day>monthLength){html+='<div class="day next">'+(day-monthLength);looping=false}}++day}}html+="</div>"}html+="</div>"}document.getElementById("c-days").innerHTML=html;cal_is_empty=false};var cal=new Calendar(2018,12,28);cal.generateHTML();

Google Closure Compiler (压缩)

Google Closure Compiler (压缩) - WHITESPACE_ONLY


var cal_days_labels=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];var cal_months_labels=["January","February","March","April","May","June","July","August","September","October","November","December"];var cal_days_in_month=[31,28,31,30,31,30,31,31,30,31,30,31];var cal_current_date=new Date;var cal_week_start=0;var cal_is_empty=true;var cal_year=2E3,cal_month=1,cal_day=1;function Calendar(year,month,day){cal_day=day;cal_month=month;cal_year=year}Calendar.prototype.generateHTML=function(){var firstDay=new Date(cal_year,cal_month,1);var startingDay=firstDay.getDay();startingDay=(startingDay+7-cal_week_start)%7;var lMonthLength=cal_days_in_month[(cal_month-1+cal_days_in_month.length)%cal_days_in_month.length];var monthLength=cal_days_in_month[cal_month];if(cal_month===1&&(cal_year%4===0&&cal_year%100!==0||cal_year%400===0))monthLength=29;else if(cal_month===2&&(cal_year%4===0&&cal_year%100!==0||cal_year%400===0))lMonthLength=29;var monthName=cal_months_labels[cal_month];var html="";for(var i=0;i<cal_days_labels.length;i++)html+='<div class="dayname">'+cal_days_labels[(cal_week_start+i)%7]+"</div>";document.getElementById("c-head").innerHTML=html;html="";var day=1;var looping=true;var bIsYearMonth=cal_current_date.getMonth()===cal_month&&cal_current_date.getFullYear()===cal_year;for(var i$0=0;i$0<9&&looping;i$0++){html+='<div class="c-drow">';for(var j=0;j<cal_days_labels.length;j++){if(j<startingDay&&i$0===0)html+='<div class="day last">'+(lMonthLength-startingDay+j);else if(i$0>0||j>=startingDay){if(day<=monthLength)if(day===cal_day&&bIsYearMonth)html+='<div class="day"><div class="current">'+day+"</div>";else html+='<div class="day">'+day;else if(day>monthLength){html+='<div class="day next">'+(day-monthLength);looping=false}++day}html+="</div>"}html+="</div>"}document.getElementById("c-days").innerHTML=html;cal_is_empty=false};var cal=new Calendar(2018,12,28);cal.generateHTML();

Google Closure Compiler (压缩) - SIMPLE_OPTIMIZATIONS


var cal_days_labels="Sun Mon Tue Wed Thu Fri Sat".split(" "),cal_months_labels="January February March April May June July August September October November December".split(" "),cal_days_in_month=[31,28,31,30,31,30,31,31,30,31,30,31],cal_current_date=new Date,cal_week_start=0,cal_is_empty=!0,cal_year=2E3,cal_month=1,cal_day=1;function Calendar(c,f,d){cal_day=d;cal_month=f;cal_year=c}Calendar.prototype.generateHTML=function(){var c=(new Date(cal_year,cal_month,1)).getDay();c=(c+7-cal_week_start)%7;var f=cal_days_in_month[(cal_month-1+cal_days_in_month.length)%cal_days_in_month.length],d=cal_days_in_month[cal_month];1===cal_month&&(0===cal_year%4&&0!==cal_year%100||0===cal_year%400)?d=29:2===cal_month&&(0===cal_year%4&&0!==cal_year%100||0===cal_year%400)&&(f=29);for(var a="",b=0;b<cal_days_labels.length;b++)a+='<div class="dayname">'+cal_days_labels[(cal_week_start+b)%7]+"</div>";document.getElementById("c-head").innerHTML=a;a="";b=1;for(var h=!0,k=cal_current_date.getMonth()===cal_month&&cal_current_date.getFullYear()===cal_year,g=0;9>g&&h;g++){a+='<div class="c-drow">';for(var e=0;e<cal_days_labels.length;e++){if(e<c&&0===g)a+='<div class="day last">'+(f-c+e);else if(0<g||e>=c)b<=d?a=b===cal_day&&k?a+('<div class="day"><div class="current">'+b+"</div>"):a+('<div class="day">'+b):b>d&&(a+='<div class="day next">'+(b-d),h=!1),++b;a+="</div>"}a+="</div>"}document.getElementById("c-days").innerHTML=a;cal_is_empty=!1};var cal=new Calendar(2018,12,28);cal.generateHTML();

Google Closure Compiler (压缩) - ADVANCED_OPTIMIZATIONS


var a="Sun Mon Tue Wed Thu Fri Sat".split(" "),b=[31,28,31,30,31,30,31,31,30,31,30,31],c=new Date,d=2E3,e=1,f=1;new function(){f=28;e=12;d=2018};var g=(new Date(d,e,1)).getDay();g=(g+7-0)%7;var h=b[(e-1+b.length)%b.length],k=b[e];1===e&&(0===d%4&&0!==d%100||0===d%400)?k=29:2===e&&(0===d%4&&0!==d%100||0===d%400)&&(h=29);for(var l="",m=0;m<a.length;m++)l+='<div class="dayname">'+a[(0+m)%7]+"</div>";document.getElementById("c-head").innerHTML=l;l="";for(var n=1,p=!0,q=c.getMonth()===e&&c.getFullYear()===d,r=0;9>r&&p;r++){l+='<div class="c-drow">';for(var t=0;t<a.length;t++){if(t<g&&0===r)l+='<div class="day last">'+(h-g+t);else if(0<r||t>=g)n<=k?l=n===f&&q?l+('<div class="day"><div class="current">'+n+"</div>"):l+('<div class="day">'+n):n>k&&(l+='<div class="day next">'+(n-k),p=!1),++n;l+="</div>"}l+="</div>"}document.getElementById("c-days").innerHTML=l;

Uglify (压缩)


"use strict";function Calendar(a,e,l){cal_day=l,cal_month=e,cal_year=a}var cal_days_labels=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],cal_months_labels=["January","February","March","April","May","June","July","August","September","October","November","December"],cal_days_in_month=[31,28,31,30,31,30,31,31,30,31,30,31],cal_current_date=new Date,cal_week_start=0,cal_is_empty=!0,cal_year=2e3,cal_month=1,cal_day=1;Calendar.prototype.generateHTML=function(){var a=new Date(cal_year,cal_month,1),e=a.getDay();e=(e+7-cal_week_start)%7;var l=cal_days_in_month[(cal_month-1+cal_days_in_month.length)%cal_days_in_month.length],c=cal_days_in_month[cal_month];1===cal_month&&(cal_year%4==0&&cal_year%100!=0||cal_year%400==0)?c=29:2===cal_month&&(cal_year%4==0&&cal_year%100!=0||cal_year%400==0)&&(l=29);for(var _=(cal_months_labels[cal_month],""),t=0;t<cal_days_labels.length;t++)_+='<div class="dayname">'+cal_days_labels[(cal_week_start+t)%7]+"</div>";document.getElementById("c-head").innerHTML=_,_="";for(var n=1,r=!0,d=cal_current_date.getMonth()===cal_month&&cal_current_date.getFullYear()===cal_year,s=0;s<9&&r;s++){_+='<div class="c-drow">';for(var y=0;y<cal_days_labels.length;y++)y<e&&0===s?_+='<div class="day last">'+(l-e+y):(s>0||y>=e)&&(n<=c?_+=n===cal_day&&d?'<div class="day"><div class="current">'+n+"</div>":'<div class="day">'+n:n>c&&(_+='<div class="day next">'+(n-c),r=!1),++n),_+="</div>";_+="</div>"}document.getElementById("c-days").innerHTML=_,cal_is_empty=!1};var cal=new Calendar(2018,12,28);cal.generateHTML();

JsMin (压缩)


'use strict';var cal_days_labels=['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];var cal_months_labels=['January','February','March','April','May','June','July','August','September','October','November','December'];var cal_days_in_month=[31,28,31,30,31,30,31,31,30,31,30,31];var cal_current_date=new Date();var cal_week_start=0;var cal_is_empty=true;var cal_year=2000,cal_month=1,cal_day=1;function Calendar(year,month,day){cal_day=day;cal_month=month;cal_year=year;}Calendar.prototype.generateHTML=function(){var firstDay=new Date(cal_year,cal_month,1);var startingDay=firstDay.getDay();startingDay=(startingDay+7-cal_week_start)%7;var lMonthLength=cal_days_in_month[(cal_month-1+cal_days_in_month.length)%cal_days_in_month.length];var monthLength=cal_days_in_month[cal_month];if(cal_month===1&&(cal_year%4===0&&cal_year%100!==0||cal_year%400===0)){monthLength=29;}else if(cal_month===2&&(cal_year%4===0&&cal_year%100!==0||cal_year%400===0)){lMonthLength=29;}var monthName=cal_months_labels[cal_month];var html='';for(var i=0;i<cal_days_labels.length;i++){html+='<div class="dayname">'+cal_days_labels[(cal_week_start+i)%7]+'</div>';}document.getElementById("c-head").innerHTML=html;html='';var day=1;var looping=true;var bIsYearMonth=cal_current_date.getMonth()===cal_month&&cal_current_date.getFullYear()===cal_year;for(var _i=0;_i<9&&looping;_i++){html+='<div class="c-drow">';for(var j=0;j<cal_days_labels.length;j++){if(j<startingDay&&_i===0){html+='<div class="day last">'+(lMonthLength-startingDay+j);}else if(_i>0||j>=startingDay){if(day<=monthLength){if(day===cal_day&&bIsYearMonth){html+='<div class="day"><div class="current">'+day+'</div>';}else{html+='<div class="day">'+day;}}else if(day>monthLength){html+='<div class="day next">'+(day-monthLength);looping=false;}++day;}html+='</div>';}html+='</div>';}document.getElementById("c-days").innerHTML=html;cal_is_empty=false;};var cal=new Calendar(2018,12,28);cal.generateHTML();

JSPacker (混淆加密)


eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--){d[e(c)]=k[c]||e(c)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('\'1d 1c\';3 n=[\'18\',\'19\',\'1h\',\'1m\',\'1l\',\'1k\',\'1q\'];3 M=[\'1n\',\'X\',\'W\',\'V\',\'T\',\'U\',\'Y\',\'S\',\'14\',\'13\',\'11\',\'10\'];3 l=[d,D,d,p,d,p,d,d,p,d,p,d];3 r=x z();3 s=0;3 L=F;3 a=15,b=1,u=1;J v(A,O,5){u=5;b=O;a=A}v.R.E=J(){3 P=x z(a,b,1);3 g=P.Z();g=(g+7-s)%7;3 t=l[(b-1+l.m)%l.m];3 h=l[b];f(b===1&&(a%4===0&&a%B!==0||a%K===0)){h=N}o f(b===2&&(a%4===0&&a%B!==0||a%K===0)){t=N}3 1j=M[b];3 6=\'\';q(3 i=0;i<n.m;i++){6+=\'<8 e="1i">\'+n[(s+i)%7]+\'</8>\'}I.H("c-1p").y=6;6=\'\';3 5=1;3 w=F;3 Q=r.1o()===b&&r.16()===a;q(3 k=0;k<9&&w;k++){6+=\'<8 e="c-1g">\';q(3 j=0;j<n.m;j++){f(j<g&&k===0){6+=\'<8 e="5 1a">\'+(t-g+j)}o f(k>0||j>=g){f(5<=h){f(5===u&&Q){6+=\'<8 e="5"><8 e="17">\'+5+\'</8>\'}o{6+=\'<8 e="5">\'+5}}o f(5>h){6+=\'<8 e="5 1b">\'+(5-h);w=C}++5}6+=\'</8>\'}6+=\'</8>\'}I.H("c-1f").y=6;L=C};3 G=x v(1e,12,D);G.E();',62,89,'|||var||day|html||div||cal_year|cal_month||31|class|if|startingDay|monthLength|||_i|cal_days_in_month|length|cal_days_labels|else|30|for|cal_current_date|cal_week_start|lMonthLength|cal_day|Calendar|looping|new|innerHTML|Date|year|100|false|28|generateHTML|true|cal|getElementById|document|function|400|cal_is_empty|cal_months_labels|29|month|firstDay|bIsYearMonth|prototype|August|May|June|April|March|February|July|getDay|December|November||October|September|2000|getFullYear|current|Sun|Mon|last|next|strict|use|2018|days|drow|Tue|dayname|monthName|Fri|Thu|Wed|January|getMonth|head|Sat'.split('|'),0,{}))

WEB 设备的 JS 混淆压缩

  • 第一优先性能,第二优先代码的私密性。
  • 由此可见为了加强代码的不可读性,采用混淆压缩 JS 代码的形式不太可取。
  • 综合上面的所说的方法,采用 Closure Compiler(Google) 方式对 JS 代码进行处理。
  • 其中主要采用 Closure Compiler 的压缩机制(附带部分混淆的效果)。

简述 Closure Compiler(Google)

  • 由 Google 公司推出。其(高级模式,Advanced)可以从语义层次对 JS 代码进行处理,完全重新改造 JS 代码,去掉不会执行到的 JS 代码。获得最大的压缩率。所以 Google 称其为 "Compiler" ,而不是 "Compressor"
  • Google Closure Compiler 支持将多个 JS 文件合并压缩为一个文件,能够通过语法分析获得更高的压缩率。
  • Google Closure Compiler 提供三个运行形式:在线工具源代码离线工具。(详细链接请查看附录)
  • Google Closure Compiler 提供三种压缩方式:Whitespace onlySimpleAdvanced

以这段代码为例:


function sayHello(name) {
    alert('Hello, ' + name);
}
sayHello('Yuki');

  • Whitespace onlyWHITESPACE_ONLY ):只删除空白、注释
  • 约束条件:不认可 JS 1.5 以上版本的语言特性。

function sayHello(name){alert("Hello, "+name)}sayHello("Yuki");

  • SimpleSIMPLE_OPTIMIZATIONS ):在 WHITESPACE_ONLY 基础上将局部变量和参数转成短名称
  • 约束条件:完全禁用 with 和 eval。

function sayHello(a){alert("Hello, "+a)}sayHello("Yuki");

  • AdvancedADVANCED_OPTIMIZATIONS ):更加激进的重命名、移除垃圾代码、内联函数。
  • 约束条件:【但是有破坏代码逻辑,运行结果的风险。需要安装规则要求修改代码,保证代码的结果】

alert("Hello, Yuki");

  • 例子 1 - 原代码:

var data = {
    user: "Yuki",
    age: "18"
};

if ("user" in data) {
    alert(data.age);
}

  • 例子 1 - Advanced 压缩后:

var a={b:"Yuki",a:"18"};"user"in a&&alert(a.a);

  • 例子 2 - 原代码:

var data = {
    user: "Yuki",
    age: "18"
};

if (data.user) {
    alert(data.age);
}

  • 例子 2 - Advanced 压缩后:

alert("18");

  • 例子 3 - 原代码:

var data = {
    "user": "Yuki",
    "age": "18"
};

if ("user" in data) {
    alert(data.age);
}

  • 例子 3 - Advanced 压缩后:

alert("18");

使用 Google Closure Compiler 离线工具

  • 基于方案特点,采用 Google Closure Compiler 离线工具进行 JS 代码的压缩。
    1. 需要下载 closure-compiler 的 jar 包。(建议下载最新版本)
    1. 在服务器运行前,需要设置 java 环境。
    1. 可以在终端输入 "java" ,测试是否支持 java 命令。

export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_111
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH

  • 使用 Google Closure Compiler 离线工具 closure-compiler.jar
  • 常用命令:
说明 命令 参考命令 备注
查看帮助 --help java -jar compiler.jar --help compiler.jar 为你的 jar 文件名称
设置输出文件 * --js_output_file java -jar compiler.jar --js_output_file=out.js 还需要设置输入文件
设置输入文件 * --js java -jar compiler.jar --js_output_file=out.js --js=in1.js in2.js in3.js
设置优化等级 * --compilation_level java -jar compiler.jar {输入输出文件} --compilation_level=ADVANCED_OPTIMIZATIONS 默认等级为:SIMPLE_OPTIMIZATIONSWHITESPACE_ONLYSIMPLE_OPTIMIZATIONSADVANCED_OPTIMIZATIONS
设置所有文件定义的编码格式 --charset java -jar compiler.jar {输入输出文件} --charset=...
设置报错模式 --warning_level java -jar compiler.jar {输入输出文件} --warning_level=QUIET QUIETDEFAULTVERBOSE
设置调试选项 --debug java -jar compiler.jar {输入输出文件} --debug=...
设置格式化输出 --formatting java -jar compiler.jar {输入输出文件} --formatting=RETTYPRINT RETTYPRINTPRINTINPUT_DELIMITER
打印语法分析树 --print_tree java -jar compiler.jar {输入输出文件} --print_tree=...

附录

相关文章

  • JavaScript 混淆压缩

    JavaScript 混淆压缩 原由 JavaScript 是一种解释型脚本语言(代码不进行预编译)。是直接解析源...

  • 关于Web性能优化

    [Yahoo前端优化十四条军规] · 压缩源码与图片 JavaScript文件源文件可以采用混淆压缩方式,css文...

  • APK加固方式

    一:代码混淆 Proguard是一个代码优化和混淆工具。能够提供对Java类文件的压缩、优化、混淆,和预校验。压缩...

  • JavaScript source map

    我知道现在前端的JavaScript多数时候放在生产环境的时候,去进行压缩和混淆。 那如何在生产环境用debug ...

  • Vue 入门 | webpack 基本使用

    webpack的主要功能 它提供了友好的前端模块化开发的支持,以及代码压缩混淆、处理浏览器端javascript ...

  • Android组件化架构 - 7. 混淆

    1. 混淆(proGuard) 有压缩Shrinking, 优化Optimization, 混淆Obfuscati...

  • js混淆

    js混淆工具--开源项目 Uglifyjs(开源) uglifyjs是一个开源的js 压缩工具,主要用于压缩,混淆...

  • Android实践:使用ProGuard压缩和混淆Apk

    本文主要讨论对apk文件的压缩和混淆中的细节问题以及分析在压缩混淆过程中遇到的问题的原因. ProGuard压缩混...

  • Android 混淆压缩

    一.为什么要混淆压缩? 原因主要有三 增加反编译的成本 资源压缩 减少apk体积 代码压缩 规避64k方法限制 二...

  • Android混淆——了解这些就够了

    Csdn 混淆介绍 Proguard是一个Java类文件压缩器、优化器、混淆器、预校验器。压缩环节会检测以及移除没...

网友评论

      本文标题:JavaScript 混淆压缩

      本文链接:https://www.haomeiwen.com/subject/erpwjqtx.html