UglifyJs打包壓縮問題引起的思考


問題背景

最近做了一個webapp項目,qa用手機測試功能時,在iphone6plus上表現是白屏,其他手機目測是ok的;因為之前在測試其他項目時也發現在這個iphone6上表現與其他手機不太一樣。於是當時以為這個手機出了什么問題,或者其版本過低;就不放在心上。

然而這次白屏的影響還是要加以重視,於是在空閑的時候主動看了下,用VSCosole查看了日志信息,控制台報了一個警告信息:

unexception token const ...

然后看了加載的js源碼,竟然發現一個大坑:

  • 代碼沒有壓縮

  • 部分代碼也沒有編譯成es5

這時心里頓生一陣陣的涼意,辛虧看了一下這個問題,否則發到線上會有重大問題。

uglifyjs為啥會報錯

出現上面的問題,首先會想到的webpack的壓縮代碼插件出問題了,項目中使用uglifyjs-webpack-plugin來壓縮代碼。於是在本地執行發布上線的操作代碼編譯壓縮,果不其然,壓縮類似這樣的錯誤:

ERROR in static/javascripts/test_0_30fbc92.js from UglifyJs
Unexpected token: name (instance) [static/javascripts/test_0_30fbc92.js:2854,6]

具體可以看下圖:

然后定位到指定文件的報錯的位置,發現都是es6的語法:

  • 第一個文件2874行的內容: let instance

  • 第二個文件78行的內容: function loadJS(url, {timeout = 5000, crossOrigin = false } = {}) {

可以看到,這兩個位置都是文件第一次出現es6沒有編譯的位置,其實在此之后還有很多未編譯的es6語法。

可能到這里有人會問,上面壓縮報錯為什么還能在非iphone6p的其他手機上可以正常訪問到呢,可能原因如下:

  • uglifyjs-webpack-plugin雖然報錯但是並不會阻止代碼的產出,從上圖也可以看出代碼已經產出。只不過其內容沒有壓縮

  • 另一個原因我猜是未出現問題的手機上打開瀏覽器已經支持這些es6語法

分析了這么多,為啥uglifyjs-webpack-plugin會報錯呢,因為當前引用uglifyjs-webpack-plugin的版本為0.4.6,它依賴的是uglify-js; 它不支持壓縮 es6,可以參考github的issueIt seems like uglify-js does not support es6?

所以:

uglify-js在壓縮代碼時,遇到es6語法就不會壓縮並且也會報錯。

如果想壓縮e6代碼,可以使用uglify-es,其提供配置屬性ecma來壓縮不同類型的js。

es6為啥沒有編譯

上面分析我們得知,uglify-webpack-plugin之所以沒有壓縮,因為代碼混合es6語法,那么es6語法為啥沒有編譯呢?推測:

在使用babel來編譯es6時,由於webpack錯誤配置的原因導致某些文件不在指定的babel編譯范圍,babel從而會忽略這些js文件的編譯

我們的項目目錄結構如下:

這是個多個微系統共用的一個工程,這些微系統共用的組件大部分相同,他們共用一個webpack配置。

webpack的有關js的配置如下所示:

   {
      test: /\.js$/,
      loader: 'babel-loader',
      include: [
        path.resolve('moudleA'),
        path.resolve('moudleB')
      ]
    }

但是與服務端交互的api目錄、公共組件components目錄以及公共的js方法目錄common目錄沒有配置進上面babel-loader的include數組中,從而babel-loader會忽略這些目錄下的js文件編譯,導致這些目錄下的js文件沒有被babel-loader編譯。從而導致上述問題。

所以,總結一下:

開發過程中遇到任何問題還是需要認真對待一下,保持一顆這就是bug的心態去發現並找出原因所在,才能降低線上出現重大問題的風險。

參考


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM