webpack uglify

weixin_34337265發表於2018-08-14

前言:

前端開發過程中,一般我們會使用 webpack 來做資源的打包壓縮等處理,在資源壓縮的過程中,一般我們會用到 uglifyjs-webpack-plugin 這個外掛,這次我們就來講一下我在使用這個外掛時遇到的一些問題

異常:

  1. SyntaxError: Cannot declare a let variable twice

這個 bug 是在 iPhone 10.3.x 的 Safari 瀏覽器上觸發的,當時是使用了 swiper 這個庫的頁面都崩潰了

解決方法也很簡單,修改配置如下:

new UglifyJsPlugin({
  sourceMap: true,
  uglifyOptions: {
    ecma: 8,
    // safari10: true,
    mangle: { safari10: true }
  }

坑的地方在是根據 uglifyjs的文件 配置成這樣是無效的:

new UglifyJsPlugin({
  sourceMap: true,
  uglifyOptions: {
    ecma: 8,
    safari10: true
  }
  1. TypeError: undefined is not an object (evaluating

這個 bug 是 iPhone 的 Safari 上偶現發生的,同一行程式碼,同樣的裝置,偶現

解決方法也很簡單:

// Changing this:
this.array.forEach(...)
// To this:
this.array && this.array.forEach(...)

根本原因是:


1742848-45faa996be88dd57.png
uglify-es

uglify-es 是什麼時候用到的?壓縮的時候,uglifyjs-webpack-plugin 依賴它,所以這個問題要解決,只需要把 uglify-es 從 3.3.2 降級到 3.2.2 就可以了

這個 issue 從 2017年12月26日 提出,到了 2018年3月12日 才被關閉,算很快了

  1. Cannot read property 'call' of undefined

這個 bug 是在低版本的 Android 裝置上必現的問題,頁面直接 crash,只留下這個報錯

這個 issue 非常有趣,它是 2015年4月9日 被提出來的,社群討論了很多解決方案,很遺憾都無法讓我 work

到了 16 年的時候也沒有解決,社群已經瘋狂了

2016年3月17日

1742848-379545a1cd17deae.png
Please fix the issue~

2016年8月4日

1742848-763323d4209e13bc.png
仍然推測是 DedupePlugin 的問題

2018年1月20日

1742848-89c3e439f8aa9397.png
issue被關閉了,但是問題並沒有解決

這個問題至今也沒有一個明確的答案,雖然 issue 被關閉了,但還是有開發者不斷的來追問

然而我知道問題出在哪。

  1. 因為它只在生產環境觸發,因此極有可能是程式碼壓縮的問題
  2. 我也忘了我是怎麼搜尋這個問題的,只記得得出的結論是 uglify-es 的 bug
  3. 我看了一下 UglifyJS2 的 commit 和 release log,發現什麼也看不懂
  4. 最後只記得是要upgrade uglify-es的版本來解決這個問題

然而這篇文章的第二個 bug,是需要downgrade uglify-es的版本,所以 uglifyjs-webpack-plugin 的這個 bug 是解決不了了,至少現在解決不了。

但我們的程式碼必須壓縮才能上線,並且要保證低版本裝置的相容,怎麼辦?

換一個壓縮外掛:babel-minify-webpack-plugin
它的預設配置也更合理一點,使用很簡單:

new MinifyPlugin(
  {}
)

完。

然而事情並沒有那麼簡單,babel-minify-webpack-plugin 也有它自己的 bug,它對 sourceMap 的支援不友好:issue

在 issue 中我們也找到了解決方法:


1742848-69c7ef2f95e3ee09.png
只支援 cheap-*開頭的 sourceMap

然而在 SSR 的時候,cheap-*開頭的 sourceMap 也是不支援的,解決方法也很簡單:

// webpack.client.config.js
new MinifyPlugin(
  {},
  {
    sourceMap: "cheap-module-source-map"
  }
)
// webpack.server.config.js
new MinifyPlugin(
  {},
  {
    sourceMap: false
  }
)

這樣問題就解決了,server 端本來就不需要 sourceMap,client 端生成的 sourceMap 將就一下也能用,雖然對找 bug 不友好,但是起碼使用者可以 work 了

  1. 其實 uglifyjs-webpack-plugin 也有另一個 bug,它在和 AggressiveSplittingPlugin 搭配使用的時候,會報:Uncaught SyntaxError: Unexpected token 這類錯

解決這個 bug 也很簡單,換成 babel-minify-webpack-plugin 就完了

最後:

為了節約研發成本,還是推薦使用 cli 工具:vue-cli

相關文章