談談JavaScript代碼混淆

來源:互聯網
上載者:User

標籤:function   play   return   height   解析   google   amp   指令   小技巧   

概述:

  • 案例:Cesium打包流程,相關技術點和大概流程

  • 原理:代碼最佳化的意義:壓縮 最佳化 混淆

  • 最佳化:如何完善Cesium打包流程

關鍵字:Cesium gulp uglifyjs

字數:2330 | 閱讀時間:7min+


1 Cesium打包流程

       如果沒有記錯,Cesium從2016年初對代碼構建工具做了一次調整,從grunt改為gulp。作為一名業餘選手,就不揣測兩者的差別了。個人而言,gulp和Ant的思路很相似,通過管道串連,都是基於流的構建風格,而且gulp更像是JS的編碼風格,內建一種親切感。

gulp.task(‘task1‘,[‘task0‘], function() {

    return fun_task1();

});

       Task語句是gulp中最常見的,懂了這句話,就等於你看懂指令碼了。這句話的意思是,要執行task1,需要先執行task0,而task1的具體工作都在fun_task1方法中。這就是之前說的基於流的構建風格。有了這句話,在命令列中鍵入:gulp task1,斷行符號執行該指令即可。

       先安裝Node,環境變數等,並安裝npm包後,即可使用gulp打包工具,這裡推薦cnpm。環境搭建好後,命令列中鍵入gulp minify開始打包。完整的過程是build->generateStubs->minify。

Cesium打包流程

       build:準備工作,建立Build檔案夾;將glsl檔案轉為js形式;最主要的是createCesiumJs方法,遍曆Source中所有js指令碼,將所有Object記錄到Source/Cesium.js;其他的是範例,單元測試相關模組。

       generateStubs:用於單元測試,略。

       minify; 首先combineJavaScript主要做了兩件事情,打包Cesium和Workers指令碼,這是打包的最終結果。Gulp根據指令的不同,比如minify下採用uglify2最佳化,而combine對應的參數為none,產生路徑為CesiumUnminified。

       另外,細心的人會發現,combineCesium的實現中有這樣一句話path.relative(‘Source‘,require.resolve(‘almond‘)),這是一個小最佳化,almond是requirejs的精簡包,因此,最終的Cesium.js中包含‘almond指令碼,內建了requirejs的主要方法。

       如上是Cesium打包的主要流程,簡單說主要有3+1類個指令:

  • Clean

    • 清空檔案

  • minify

    • 打包&壓縮

  • combine

    • 只打包,不壓縮

  • JScoverage

    • 單元測試覆蓋率,不瞭解

2 代碼最佳化

       對流程有了一個大概瞭解,下面,我們詳細瞭解一下uglify2過程都做了哪些代碼最佳化,一言以蔽之,壓縮,最佳化,混淆。

       uglify2主要有三個參數:-o,-c,-m,-o參數必選,指定輸出檔案,-c壓縮,-m混淆變數名。如下分別為combine、(uglifyjs -o)、(uglifyjs –c -m -o)的檔案對比,單位是k:

uglify2的壓縮對比

       都在一個屋簷下,差距怎麼就這麼大呢?我們簡單說一下從1~2,2~3之間青取之於藍而勝於藍的過程。

       1~2的過程其實很簡單,就是幹了三件事,去掉注釋, 去掉多餘的空格(分行符號),去掉不必要的分號(;)。就這三件事情,檔案一下子小了一半多,換句話就是平時你寫的代碼有一大半都是廢話,此時你旁邊的AI程式員可能會喃喃道來“你們人類好愚蠢~”。

       2~3則是很多小細節的綜合應用:

  • 去掉一些實際沒有調用的函數(Dead code);

  • 將零散的變數聲明合并,比如 var a; var b;變為var a,b;

  • 邏輯函數的精簡,比如if(a) b(); else c()變為a ? b() : c();

  • 變數名的簡化,比如var strObject;變為var s;

  • ……

       這些小技巧有很多,具體要看不同的壓縮公用程式的考慮優劣,但有些壓縮高效的工具並不穩定,可能會破壞文法規範或語意,所以沒必要為了幾個kb承擔過多的風險,目前比較成熟的工具主要有三個uglify2,google closure以及yuicompressor,具體優劣得自己來體會了,我是按照自己的理解給出的先後順序。最終的效果如下:

Cesium指令碼效果

       這樣的代碼只能用單位“坨”來形容了,人類是無法直接讀懂的,那瀏覽器能讀懂嗎?這是一個好問題!如下是V8引擎對JS文法解析的大概流程:

V8引擎解析JS指令碼

       下面是在我本機Chrome解析Cesium.js指令碼花費時間(指令碼從下載完到瀏覽器解析完的時間差),單位毫秒,因為只測試了一次,可能會有誤差,但基本吻合期望值:

 

JS指令碼解析時間對比

       首先因為是本機測試,指令碼無論是最大的8M還是最小的2.4M,下載速度都很快,因此我們不討論(但實際應用中要考慮)指令碼下載所需時間。

其次,如,多了一個source,這是源碼情況下,這個時間水分比較大,因為是零散的檔案,可以做到按需下載,但因為檔案比較瑣碎,效能也不高。

       結論是,這種JS指令碼最佳化策略對瀏覽器的影響不大,瀏覽器看到最佳化後的代碼,可能會愣一會神,但很快就克服了。

3實戰

       知道了代碼最佳化的大概原理,回顧一下代碼最佳化的目的(壓縮,最佳化,混淆),匹配一下結果是否符合期望值。嗯,其一,指令碼的大小小了,其二,代碼效率也最佳化了,其三,別人也看不懂了。似乎該做的都已經做了,這個指令碼已經很完美了。

 

Format後的效果

       毛爺爺說,與人鬥其樂無窮。確實,前兩點的目的達到了,但第三點,還差很多。如上,和剛才的指令碼是同一個檔案,我只是用Chrome的調試工具format而已。這就是理想和現實之間的差距。

       可見,Cesium預設打包工具在壓縮和最佳化上都沒有問題,但在混淆上並不充分,當然Cesium本身是開源的,也沒必要搞這些。客觀說,JS指令碼是明碼的,所以反編譯只是時間和能力的問題,所以不妨換個態度來看待這個問題,增加反編譯的成本,當該成本大於購買成本即可。

       抱歉,下面的內容因為外在因素,不方便在這說,我寫完之後又刪除了,深表歉意。如果感興趣,不妨在公眾號留言,當然如果你認可超圖的技術,歡迎加入超圖研發WebGL團隊。

       Beneath this mask, there is more than flesh. Beneath this mask, there is an idea. And ideas are bulletproof.

談談JavaScript代碼混淆

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.