java script和java的區別,join為什么每個字符都分割了 js_為什么 webpack4 默認支持 ES6 語法的壓縮?

 2023-10-05 阅读 12 评论 0

摘要:在專欄課程里,有位同學提到過一個很有意思的問題:“我沒裝 babel,js 入口里寫了個箭頭函數,運行 webpack 構建命令后,也成功編譯了。這是為什么?”。今天就帶領大家一起去探討下這個話題。在使用 webpack 的時候,很常見的一
在專欄課程里,有位同學提到過一個很有意思的問題:“我沒裝 babel,js 入口里寫了個箭頭函數,運行 webpack 構建命令后,也成功編譯了。這是為什么?”。今天就帶領大家一起去探討下這個話題。

在使用 webpack 的時候,很常見的一個構建優化手段就是縮小構建目標。比如在構建階段只構建 src 里面的模塊代碼,對于 node_modules 里面所引入的三方包不進行構建操作。

發現問題

如果使用的是 webpack 3.x 版本,編寫的構建腳本類似這樣的,我們通過設置loader 里面的 exclude 字段避免由于解析 node_modules 里面的模塊造成的構建耗時:

const path = require('path');
const webpack = require('webpack');
?
module.exports = {entry: './src/index.js',output: {path: path.join(__dirname, 'dist'),filename: 'bundle.js'},module: {rules: [{test: /.js$/,loader: 'happypack/loader',exclude: path.join(__dirname, 'node_modules')}]}plugins: [new webpack.optimize.UglifyJsPlugin()]
};

我們經常會遇到一個問題,假設引入的 npm 包質量不夠高,比如 node_modules 里面有 ES6 的語法,那么 webpack 在 uglify 階段會報錯!下面給出兩種常見的出錯場景:

ES6 的模板字符串

假設 node_modules 里面存在 ES6 的模板字符串語法,那么在生產環境打包的代碼壓縮階段,UglifyJs 會拋出錯誤。

java script和java的區別。

82023d176399ffba36ae2be91b08f9c4.png

ES6 的箭頭函數

同樣的,你使用 ES6 的箭頭函數也是無法正常的壓縮代碼的。

21666b11db5c6bf482f7679db75cc592.png

細心的你一定會發現如果使用的是 webpack 4,這個場景描述的問題將不再出現。webpack 4默認支持 ES6 代碼的壓縮,這個是什么原因呢?

初步分析

如果你有對 webpack 4 的依賴包進行過相關分析,比如直接查閱 package.json 文件或者通過 http://npm.broofa.com/ 網站上進行 webpack 依賴圖分析。不難發現 webpack 4 里面使用了 terser-webpack-plugin 插件替代了之前一直使用的 uglifyjs-webpack-plugin 作為它的內置插件。

js中join方法、以 4.39.3 這個版本為例,可以看到它的 package.json 文件的依賴包括了terser-webpack-plugin。

d577f183343e70a166486165e8bd2ab6.png

我們進一步分析發現 webpack 的 4.26.0 這個版本有一次提交,它的提交內容是對 webpack 內置插件進行了一次切換。

4b9f35cd968edd4cbf1958f254a3b8df.png

經過這么一次分析,我們可以知道 webpack 4 之所以具備默認壓縮 ES6 代碼的能力,離不開 terser-webpack-plugin 所起的作用!

進一步分析

js截取字符串指定字符?在探究 terser-webpack-plugin 插件的原理前,我們先系統的回顧一下代碼壓縮插件的歷史:

  • 當 uglifyjs-webpack-plugin 版本小于 v1.0 時,它使用的是 uglify-js 依賴
  • 但是 uglify-js 并不支持 ES6, 因此在 uglify-js 倉庫的 harmony 分支 Fork 了一個 uglify-es
  • uglifyjs-webpack-plugin 的 v1.x 為了支持 ES6 的壓縮語法,將 uglify-js 依賴切換到了 uglify-es
  • 但是 uglify-es 停止維護了: mishoo/UglifyJS2#3156 (comment)
  • uglify-es 的停止維護導致了 terser 被 fork 出來了,并且 terser 處理了沒有合入的 PRs,最終創建了一個獨立的倉庫: https://github.com/fabiosantoscode/terser
  • 隨后,terser-webpack-plugin 被創建出來, 它基于 terser,并且具備uglifyjs-webpack-plugin 的同等功能 : https://github.com/webpack-contrib/terser-webpack-plugin
  • 由于 uglifyjs-webpack-plugin v2.x 回退到了 uglify-js, 不再支持 ES6。 因此那些希望支持 ES6 語法壓縮的項目必須切換到 terser-webpack-plugin

備注:壓縮插件歷史的來源 https://github.com/webpack/webpack/commit/311a7285d36b38bada46102967c431e93ff48a89

到這里,我們可以得出一個基本的結論:terser-webpack-plugin 基于 terser 因此它具備 ES6 的壓縮能力,uglifyjs-webpack-plugin v2.x 版本基于 uglify-js,無法支持 ES6 的壓縮。

插件依賴是否支持 ES6(Y/N)terser-webpack-pluginterserYuglifyjs-webpack-plugin v1.xuglify-esNuglifyjs-webpack-plugin v2.xuglify-jsN

原理探究

代碼壓縮原理其實挺簡單的,也是 AST 的一個經典的應用案例。它的壓縮過程通常是:

     JS 源代碼 -> AST -> 美化、壓縮 -> 新的 AST -> 壓縮后的代碼 

jquery前后端分離、了解了代碼壓縮的基本流程后,接下來我們看看源碼包含了哪些內容,由于 terser 是從 uglify-es Fork 出來進行修改的,因此它的代碼結構和 uglify-js 基本一致,只不過 terser 使用了 ES6 模塊的靜態分析功能。我們以 terser 的源碼為例分析下:

  • ast.js:JS 的抽象語法樹的描述信息
  • parse.js:Parser,用于從 JS 源代碼分析出 AST
  • minify.js:用于將 AST 優化成更簡短的結構
  • output.js:代碼生成器,從 AST 輸出 壓縮后的代碼,支持 sourcemap 的生成
  • propmangle.js:對變量的長度進行壓縮,通常是單個字符
  • scope.js:分析變量定義/引用位置的信息
  • transform.js:節點遍歷

然后,我們來一探 terser 和 uglify-js 的差異。對比了之后,發現一個很大的差異是 AST 的支持上面不同。

3d88504634e5b10dab8ffb076573dbbf.png

分析AST的差異發現,下面是兩個文件 diff 對比只在 terser 中才有,而這些剛好對應 ES6 的語法。

AST_Arrow,
AST_Await,
AST_BigInt,
AST_Class,
AST_ClassExpression,
AST_ConciseMethod,
AST_Const,
AST_DefaultAssign,
AST_Destructuring,
AST_Expansion,
AST_Export,
AST_ForOf,
AST_Import,
AST_Let,
AST_NameMapping,
AST_NewTarget,
AST_PrefixedTemplateString,
AST_Super,
AST_SymbolMethod,
AST_TemplateSegment,
AST_TemplateString,
AST_Yield

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/3/115052.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息