溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

javascript代碼是怎么被壓縮的

發(fā)布時(shí)間:2020-07-28 15:22:33 來源:億速云 閱讀:198 作者:小豬 欄目:web開發(fā)

這篇文章主要講解了javascript代碼是怎么被壓縮的,內(nèi)容清晰明了,對(duì)此有興趣的小伙伴可以學(xué)習(xí)一下,相信大家閱讀完之后會(huì)有幫助。

隨著前端的發(fā)展,特別是 React , Vue 等構(gòu)造單頁(yè)應(yīng)用的興起,前端的能力得以很大提升,隨之而來的是項(xiàng)目的復(fù)雜度越來越大。 此時(shí)的前端的靜態(tài)資源也越來越龐大,而毫無疑問 javascript 資源已是前端的主體資源,對(duì)于壓縮它的體積至為重要。

為什么說更小的體積很重要呢:更小的體積對(duì)于用戶體驗(yàn)來說意味著更快的加載速度以及更好的用戶體驗(yàn),這也能早就企業(yè)更大的利潤(rùn)。另外,更小的體積對(duì)于服務(wù)器來說也意味更小的帶寬以及更少的服務(wù)器費(fèi)用。

前端構(gòu)建編譯代碼時(shí),可以使用 webpack 中的 optimization.minimizer 來對(duì)代碼進(jìn)行壓縮優(yōu)化。但是我們也需要了解如何它是壓縮代碼的,這樣當(dāng)在生產(chǎn)環(huán)境的控制臺(tái)調(diào)試代碼時(shí)對(duì)它也有更深刻的理解。

如何查看資源的體積

對(duì)于我們所編寫的代碼,它在操作系統(tǒng)中是一個(gè)文件,根據(jù)文件系統(tǒng)中的 stat 信息我們可以查看該文件的大小。

stat 命令用來打印文件系統(tǒng)的信息:

$ stat config.js
 File: ‘config.js'
 Size: 3663      Blocks: 8     IO Block: 4096  regular file
Device: fd01h/64769d  Inode: 806060   Links: 1
Access: (0644/-rw-r--r--) Uid: (  0/  root)  Gid: (  0/  root)
Access: 2020-02-13 13:43:54.851381702 +0800
Modify: 2020-02-13 13:43:52.668417641 +0800
Change: 2020-02-13 13:43:52.691417262 +0800
 Birth: -

stat 打印的信息過大,如果只用來衡量體積,可以使用 wc -c

$ wc -c config.js
3663 config.js

如何壓縮代碼體積?

去除多余字符: 空格,換行及注釋

// 對(duì)兩個(gè)數(shù)求和
function sum (a, b) {
 return a + b;
}

先把一個(gè)抽象的問題給具體化,如果是以上一段代碼,那如何壓縮它的體積呢:

此時(shí)文件大小是 62 Byte , 一般來說中文會(huì)占用更大的空間。

多余的空白字符會(huì)占用大量的體積,如空格,換行符,另外注釋也會(huì)占用文件體積。當(dāng)我們把所有的空白符合注釋都去掉之后,代碼體積會(huì)得到減少。

去掉多余字符之后,文件大小已經(jīng)變?yōu)?30 Byte 。 壓縮后代碼如下:

function sum(a,b){return a+b}

替換掉多余字符后會(huì)有什么問題產(chǎn)生呢?

有,比如多行代碼壓縮到一行時(shí)要注意行尾分號(hào)。這就需要通過以下介紹的 AST 來解決。

壓縮變量名:變量名,函數(shù)名及屬性名

function sum (first, second) {
 return first + second;
}

如以上 first 與 second 在函數(shù)的作用域中,在作用域外不會(huì)引用它,此時(shí)可以讓它們的變量名稱更短。但是如果這是一個(gè) module 中, sum 這個(gè)函數(shù)也不會(huì)被導(dǎo)出呢?那可以把這個(gè)函數(shù)名也縮短。

// 壓縮: 縮短變量名
function sum (x, y) {
 return x + y;
}

// 再壓縮: 去除空余字符
function s(x,y){return a+b}

在這個(gè)示例中,當(dāng)完成代碼壓縮 ( compress ) 時(shí),代碼的混淆 ( mangle ) 也捎帶完成。 但此時(shí)縮短變量的命名也需要 AST 支持,不至于在作用域中造成命名沖突。

更簡(jiǎn)單的表達(dá):合并聲明以及布爾值簡(jiǎn)化

合并聲明的示例如下:

// 壓縮前
const a = 3;
const b = 4;

// 壓縮后
const a = 3, b = 4;

布爾值簡(jiǎn)化的示例如下:

// 壓縮前
!b && !c && !d && !e

// 壓縮后
b||c||d||e

這個(gè)示例更是需要解析 AST 了

AST

AST ,抽象語(yǔ)法樹,js 代碼解析后的最小詞法單元,而這個(gè)過程就是通過 Parser 來完成的。

那么 AST 可以做什么呢?

  • eslint: 校驗(yàn)?zāi)愕拇a風(fēng)格
  • babel: 編譯代碼到 ES 低版本
  • taro/mpvue: 各種可以多端運(yùn)行的小程序框架
  • GraphQL: 解析客戶端查詢

我們?cè)谌粘9ぷ髦薪?jīng)常會(huì)不經(jīng)意間與它打交道,如 eslint 與 babel ,都會(huì)涉及到 js 與代碼中游走。不同的解析器會(huì)生成不同的 AST,司空見慣的是 babel 使用的解析器 babylon ,而 uglify 在代碼壓縮中使用到的解析器是 UglifyJS 。

你可以在 AST Explorer [3] 中直觀感受到,如下圖:

javascript代碼是怎么被壓縮的

那壓縮代碼的過程:code -> AST -> (transform)一顆更小的 AST -> code,這與 babel 和 eslint 的流程一模一樣。

javascript代碼是怎么被壓縮的 

UglifyJS

不要重復(fù)造輪子!

于是我找了一個(gè)久負(fù)盛名的關(guān)于代碼壓縮的庫(kù): UglifyJS3 [4] ,一個(gè)用以代碼壓縮混淆的庫(kù)。那它是如何完成一些壓縮功能的,比如替換空白符,答案是 AST。

webpack 中內(nèi)置的代碼壓縮插件就是使用了它,它的工作流程大致如下:

// 原始代碼
const code = `const a = 3;`

// 通過 UglifyJS 把代碼解析為 AST
const ast = UglifyJS.parse(code);
ast.figure_out_scope();


// 轉(zhuǎn)化為一顆更小的 AST 樹
compressor = UglifyJS.Compressor();
ast = ast.transform(compressor);

// 再把 AST 轉(zhuǎn)化為代碼
code = ast.print_to_string();

而當(dāng)你真正使用它來壓縮代碼時(shí),你只需要面向配置編程即可,文檔參考 uglify 官方文檔 [5]

{
 {
  ecma: 8,
 },
 compress: {
  ecma: 5,
  warnings: false,
  comparisons: false,
  inline: 2,
 },
 output: {
  ecma: 5,
  comments: false,
  ascii_only: true,
 }
}

在 webpack 中壓縮代碼

在知道代碼壓縮是怎么完成的之后,我們終于可以把它搬到生產(chǎn)環(huán)境中去壓縮代碼。終于到了實(shí)踐的時(shí)候了,雖然它只是簡(jiǎn)單的調(diào)用 API 并且調(diào)調(diào)參數(shù)。

一切與性能優(yōu)化相關(guān)的都可以在 optimization 中找到, TerserPlugin 是一個(gè)底層基于 uglifyjs 的用來壓縮 JS 的插件。

optimization: {
 minimize: isEnvProduction,
 minimizer: [
  new TerserPlugin({
   terserOptions: {
    parse: {
     ecma: 8,
    },
    compress: {
     ecma: 5,
     warnings: false,
     comparisons: false,
     inline: 2,
    },
    output: {
     ecma: 5,
     comments: false,
     ascii_only: true,
    },
   },
   sourceMap: true
  })
 ]
}

看完上述內(nèi)容,是不是對(duì)javascript代碼是怎么被壓縮的有進(jìn)一步的了解,如果還想學(xué)習(xí)更多內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI