在專欄課程里,有位同學提到過一個很有意思的問題:“我沒裝 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 階段會報錯!下面給出兩種常見的出錯場景:
假設 node_modules 里面存在 ES6 的模板字符串語法,那么在生產環境打包的代碼壓縮階段,UglifyJs 會拋出錯誤。
java script和java的區別。
同樣的,你使用 ES6 的箭頭函數也是無法正常的壓縮代碼的。
細心的你一定會發現如果使用的是 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。
我們進一步分析發現 webpack 的 4.26.0 這個版本有一次提交,它的提交內容是對 webpack 內置插件進行了一次切換。
經過這么一次分析,我們可以知道 webpack 4 之所以具備默認壓縮 ES6 代碼的能力,離不開 terser-webpack-plugin 所起的作用!
js截取字符串指定字符?在探究 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 的源碼為例分析下:
然后,我們來一探 terser 和 uglify-js 的差異。對比了之后,發現一個很大的差異是 AST 的支持上面不同。
分析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
版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。
工作时间:8:00-18:00
客服电话
电子邮件
admin@qq.com
扫码二维码
获取最新动态