blog icon indicating copy to clipboard operation
blog copied to clipboard

uglify 压缩报错问题及 es5-imcompatible-versions

Open sorrycc opened this issue 6 years ago • 42 comments

视频版:youtube | bilibili

缘起

由于维护 roadhog 和 umi,收到构建方面的问题反馈比较多,其中一个常见的是打包时 uglify 压缩的问题。类似下面的报错都是这个引起的,

Failed to minify the bundle. Error: 0.0f3f4c41.async.js from UglifyJs

xx.async.js from UglifyJs Unexpected token: keyword (const)

0.570d21b1.async.js from UglifyJs
Unexpected token: punc ()) [0.570d21b1.async.js:13245,19]

xx.async.js from UglifyJs Unexpected token: operator (>)

为啥会有这个问题?

通常 webpack 在构建时,是不会让 node_modules 下的文件走 babel tranpile 的,一是会慢很多,二是 babel@6 时编译编译过的代码会不安全(据说 babel@7 下没问题了),所以业界有个潜在的约定,npm 包发布前需要先用 babel 转出一份 es5 的代码

但是有些 npm 包不遵守这个约定,没有转成 es5 就发上去,比如 query-string@6。然后压缩工具 uglify 又只支持 es5 的语法,遇到 constlet()=> 类似的语法,就抛错了。

解决

有多个解决方法,但各有利弊。

使用 uglify-es 进行压缩

uglify-es 支持 es6 语法,所以不会报错。但问题是如果你需要在 IE11 及以下,或者其他的低版本浏览器里跑时,就会报错、白屏了。

让 babel 编译 node_modules 下的文件

由于 babel@7 可以保证编译编译过的代码不会出问题,这不失为一个好的解决方案,比如 create-react-app 会在下个版本考虑用这个方案,参考 facebook/create-react-app#3776。问题是会让本来就比较慢的 dev、build 流程雪上加霜。

babel-engine-plugin

跟进 npm 包的 engine 配置做按需编译。缺点是使用者比较少,如果 npm 包开发者不遵循这个规则一样会出问题。

umi/roadhog 提供的 extraBabelIncludes 配置

umi/roadhog 默认也是仅用 babel 编译项目文件,但提供了额外的 extraBabelInclude 配置可以指定 node_modules 下的文件。比如:

{
  "extraBabelIncludes": [
    "node_modules/a",
    "node_modules/b"
  ]
}

问题是无法提前预知,都是出错了一脸那啥,翻 issue 或者提问后才知道。而且找到哪个依赖用了 es6 语法也比较麻烦。

所以,有没有一种能提前预知(用户无感知),并且不降低 webpack 构建速度的方案?

es5-imcompatible-versions

经过讨论,我们建了一个 es5-imcompatible-versions,用于收集 uglify 压缩有问题的 npm 包版本。然后再提供配套工具,自动 resolve 到项目里有问题的 npm 包路径,添加到 babel-loader 的 include 参数里。

然后,

  • 遇到已被收录的 es6 包,会自动走 babel 编译
  • 遇到未被收录的,在 es5-imcompatible-versions 提 PR,被合并发布后,重装 npm 依赖再构建,自动生效

umi

确保 umi 在 1.2.4 或以上,然后在 .webpackrc 里配:

export default {
  es5ImcompatibleVersions: true,
}

roadhog

确保 roadhog 在 2.4.0-beta.3 或以上,然后在 .webpackrc 里配:

export default {
  es5ImcompatibleVersions: true,
}

参考这个使用了 query-string@6 和 get-value@3 的例子,https://github.com/umijs/umi-examples/tree/master/es5-imcompatible-versions


最后,这事情是否能做成,就靠大家一起共建了。

参考

  • https://github.com/umijs/es5-imcompatible-versions
  • https://github.com/sindresorhus/ama/issues/446
  • https://github.com/facebookincubator/create-react-app/issues/3776

sorrycc avatar Apr 13 '18 09:04 sorrycc

uglify-bug-versions => es5-imcompatible-versions ?

afc163 avatar Apr 13 '18 09:04 afc163

@afc163 ok,es5-incompatible-versions

sorrycc avatar Apr 13 '18 09:04 sorrycc

- incompatible
+ imcompatible

afc163 avatar Apr 13 '18 09:04 afc163

是不是构建前这些前置判断也加上:http://2ality.com/2017/04/setting-up-multi-platform-packages.html

afc163 avatar Apr 13 '18 09:04 afc163

酷,经常能收到这样的问题。。以后可以直接贴这篇了

ikobe-zz avatar Apr 14 '18 03:04 ikobe-zz

其实说到底最根本的问题是:

编译太慢!

因为大家觉得npm包应该是只读的,重新编译确实没有太大必要。

但是其实,npm包不光是为了发布,而是为了做模块化代码分离,很多业务模块单独成一个包,并没有想着要publish,而是用lerna在本地进行代码管理,类似于一个文件夹,这个阶段,基础包源码变更是很频繁的,其实比起 "首次编译时间长" 更差的体验是 "每次修改都要重新启动打包编译" 无法HRM .

另外,解决方案的问题是 ,识别是否需要转义,es5-imcompatible-versions 和extraBabelIncludes 用的是 白名单机制 ,其实,有时候源码不一定是es6的, 也有可能是*. ts ,.tsx,.less ,*.vue 我不一定要用babel啊, 碰到这种类型的扩展文件,直接让我转不就好了,反正这种文件也不会太多的。

lusess123 avatar Apr 20 '18 12:04 lusess123

. ts ,.tsx,.less ,.vue 我不一定要用babel啊, 碰到这种类型的扩展文件,直接让我转不就好了

node_modules 下的 .less 是有编译的,不走 css modules。.tsx? 有需要可以提 PR,我觉得全量编译是可以的。

sorrycc avatar Apr 20 '18 13:04 sorrycc

@sorrycc 感谢回复 ……^_^ , 这个PR 只需要去掉 exclude: /node_modules/, 就可以了吧

lusess123 avatar Apr 20 '18 15:04 lusess123

deprecate,见下贴。

更新 umi 对于 es5-imcompatible-versions 的实现。

~~umi-plugin-es5-imcompatible-versions~~

umi 的用户遇到这个问题,可通过添加插件自动解决。

编辑 .umirc.js

export default {
  plugins: [
    'umi-plugin-es5-imcompatible-versions',
  ],
}

参考这个使用了 query-string@6 和 get-value@3 的例子,https://github.com/umijs/umi-examples/tree/master/es5-imcompatible-versions

sorrycc avatar Apr 27 '18 08:04 sorrycc

更新:

umi

确保 umi 在 1.2.4 或以上,然后在 .webpackrc 里配:

export default {
  es5ImcompatibleVersions: true,
}

roadhog

确保 roadhog 在 2.4.0-beta.3 或以上,然后在 .webpackrc 里配:

export default {
  es5ImcompatibleVersions: true,
}

参考这个使用了 query-string@6 和 get-value@3 的例子,https://github.com/umijs/umi-examples/tree/master/es5-imcompatible-versions

sorrycc avatar Apr 28 '18 04:04 sorrycc

D:\ybx2\wx>umi -v 1.2.6 在执行完 umi如上修改, .umirc.js export default { plugins: [ 'umi-plugin-es5-imcompatible-versions', ], } .webpackrc.js export default { es5ImcompatibleVersions: true, } 后问题依旧.只是npm run build 跟 直接 umi build 错误信息不同 1. package.json "scripts": { "build": "umi build", },

D:\ybx2\wx>npm run build

@ build D:\ybx2\wx umi build

D:\ybx2\wx\[email protected]@af-webpack\lib\getUserConfig\index.js:54 throw new Error(msg); ^ Error: Configuration item es5ImcompatibleVersions is not valid, please remove it. at throwError (D:\ybx2\wx\[email protected]@af-webpack\lib\getUserConfig\index.js:54:9)

D:\ybx2\wx>umi build build [================== ] 91%Skipping static resource "D:/ybx2/wx/dist/static/1.b829935f.async.js" (8.9 MB) - max size is 2.1 MB Skipping static resource "D:/ybx2/wx/dist/static/2.ba84922c.async.js" (8.77 MB) - max size is 2.1 MB Total precache size is about 5.38 MB for 35 resources. Build completed in 49.549s

Failed to compile.

Failed to minify the bundle. Error: 1.b829935f.async.js from UglifyJs Unexpected token: name (matches) [1.b829935f.async.js:1102,5] at doneHandler (C:\Users\zhanck\AppData\Roaming\npm\node_modules\umi\node_modules\af-webpack\lib\build.js:91:27)

@sorrycc 该如何配置求教

zhanchengkun avatar May 07 '18 06:05 zhanchengkun

咳咳。。 我这个如何知道是哪个包报错啊?

Failed to minify the bundle. Error: index.06048ed9.js from UglifyJs Unexpected token name «i», expected punc «;» [index.06048ed9.js:198644,11] at doneHandler (E:\workspace\gitlab_repo\manager-xyzy-antd\[email protected]@af-webpack\lib\build.js:91:27) at emitRecords.err (E:\workspace\gitlab_repo\manager-xyzy-antd\[email protected]@webpack\lib\Compiler.js:265:13) at Compiler.emitRecords (E:\workspace\gitlab_repo\manager-xyzy-antd\[email protected]@webpack\lib\Compiler.js:371:38) at emitAssets.err (E:\workspace\gitlab_repo\manager-xyzy-antd\[email protected]@webpack\lib\Compiler.js:258:10) at applyPluginsAsyncSeries1.err (E:\workspace\gitlab_repo\manager-xyzy-antd\[email protected]@webpack\lib\Compiler.js:364:12) at next (E:\workspace\gitlab_repo\manager-xyzy-antd\[email protected]@tapable\lib\Tapable.js:218:11) at Compiler.compiler.plugin (E:\workspace\gitlab_repo\manager-xyzy-antd\[email protected]@webpack\lib\performance\SizeLimitsPlugin.js:99:4) at next (E:\workspace\gitlab_repo\manager-xyzy-antd\[email protected]@tapable\lib\Tapable.js:220:14) at callback (E:\workspace\gitlab_repo\manager-xyzy-antd\[email protected]@copy-webpack-plugin\dist\index.js:126:17) at Compiler.afterEmit (E:\workspace\gitlab_repo\manager-xyzy-antd\[email protected]@copy-webpack-plugin\dist\index.js:220:13) at Compiler.applyPluginsAsyncSeries1 (E:\workspace\gitlab_repo\manager-xyzy-antd\[email protected]@tapable\lib\Tapable.js:222:13) at Compiler.afterEmit (E:\workspace\gitlab_repo\manager-xyzy-antd\[email protected]@webpack\lib\Compiler.js:361:9) at require.forEach.err (E:\workspace\gitlab_repo\manager-xyzy-antd\[email protected]@webpack\lib\Compiler.js:350:15) at E:\workspace\gitlab_repo\manager-xyzy-antd\[email protected]@async\dist\async.js:473:16 at iteratorCallback (E:\workspace\gitlab_repo\manager-xyzy-antd\[email protected]@async\dist\async.js:1064:13) at E:\workspace\gitlab_repo\manager-xyzy-antd\[email protected]@async\dist\async.js:969:16 Read more here: http://bit.ly/2tRViJ9

xgj1988 avatar Jun 30 '18 04:06 xgj1988

umi/roadhog 提供的 extraBabelIncludes 配置

这一段中,键名应该是 extraBabelIncludes 而非 extraBabelIncludes:

reallyimeric avatar Jul 19 '18 02:07 reallyimeric

@reallyimeric 你的意思是没有冒号?

xgj1988 avatar Jul 23 '18 06:07 xgj1988

我使用webpack.config.js 后即使开启es5ImcompatibleVersions 也报了这个错误,不用webpack.config.js复写就不会报错。(这个问题是因为webpack.config.js中接受的第二个参数从原来的node_env的字符串 变成对象导致的。这个api变动不好找,真的蛋疼)

zzh466 avatar Jul 31 '18 09:07 zzh466

image swiper 包编译出错

sixihaoyue avatar Aug 28 '18 04:08 sixihaoyue

incompatible? imcompatible? incompatible是对的吧

OPY-bbt avatar Sep 04 '18 03:09 OPY-bbt

脚手架用了antd Pro,里面应用ckeditor5报es6压缩错误,根据帖子建议,在.webpackrc.js中配置 extraBabelIncludes: [ "node_modules/@ckeditor", ], 但是ckeditor5转es5后使用报错,于是又改为配置 es5ImcompatibleVersions: true, 但是没有效果,报错是Failed to minify the bundle. Error: index.2080360b.js from UglifyJs,这个感觉是es5ImcompatibleVersions中没有收录ckeditor5吗?

flg717 avatar Sep 27 '18 04:09 flg717

uglify只能压缩es5,如果用了es6/7,就会报错。 babel默认只转换项目文件,不转换依赖包(node_modules)。可通过配置加入。 { "extraBabelIncludes": [ "node_modules/a", "node_modules/b" ] } 解决方案: 配置:es5ImcompatibleVersions: true, npm run build,根据log找到有问题的npm包,加入配置文件“extraBabelIncludes”进行babel编译。

pengshaosu avatar Oct 17 '18 06:10 pengshaosu

https://github.com/webpack/webpack/issues/5858#issuecomment-423796350

我们是不是可以试试:https://github.com/webpack-contrib/terser-webpack-plugin

afc163 avatar Oct 17 '18 07:10 afc163

webpack/webpack#5858 (comment)

我们是不是可以试试:https://github.com/webpack-contrib/terser-webpack-plugin

你们使用的是哪种方案? 第三方uglify插件?

pengshaosu avatar Oct 17 '18 07:10 pengshaosu

@afc163 我觉得最终方案还是让 node_modules 也走 babel 转换,顺便把按需打补丁的问题也解决了。

sorrycc avatar Oct 17 '18 07:10 sorrycc

terser-webpack-plugin 可以压缩 es6 代码的,本地测试目前感觉良好。

afc163 avatar Oct 17 '18 07:10 afc163

node_modules 走 babel 会影响调试和构建性能吧。

afc163 avatar Oct 17 '18 07:10 afc163

现在 umi@2 的 uglifyjs 就是到 es6 的,但问题是如果要支持到低版本浏览器,构建时不报错,但运行时仍然会报错,所以只是把问题藏了起来,并没有真正解决。

这也是我为啥在 umi@2 之后加了 umi-plugin-ecma5-validator 这个插件。

sorrycc avatar Oct 17 '18 07:10 sorrycc

terser-webpack-plugin 可以压缩 es6 代码的,本地测试目前感觉良好。

这个压缩后,会不会出现上面老大说的问题;

如果你需要在 IE11 及以下,或者其他的低版本浏览器里跑时,就会报错、白屏了。

pengshaosu avatar Oct 17 '18 07:10 pengshaosu

@sorrycc [email protected] 配置了babel node_modules,依然报错

    "env": {
    "production": {
      "es5ImcompatibleVersions": true,
      "extraBabelIncludes": [
        "node_modules/*"
       ]
     }
  }
Failed to minify the bundle. Error: index.js from UglifyJs
Unexpected token name «p», expected punc «;» [index.js:399,17]
    at doneHandler (E:\sourcecode\project_MedicalServices\01code\msp\node_modules\af-webpack\lib\build.js:91:27)
    at emitRecords.err (E:\sourcecode\project_MedicalServices\01code\msp\node_modules\webpack\lib\Compiler.js:265:13)
    at Compiler.emitRecords (E:\sourcecode\project_MedicalServices\01code\msp\node_modules\webpack\lib\Compiler.js:371:38)
    at emitAssets.err (E:\sourcecode\project_MedicalServices\01code\msp\node_modules\webpack\lib\Compiler.js:258:10)
    at applyPluginsAsyncSeries1.err (E:\sourcecode\project_MedicalServices\01code\msp\node_modules\webpack\lib\Compiler.js:364:12)


pengshaosu avatar Oct 17 '18 07:10 pengshaosu

@sorrycc [email protected] 配置了babel node_modules,依然报错

    "env": {
    "production": {
      "es5ImcompatibleVersions": true,
      "extraBabelIncludes": [
        "node_modules/*"
       ]
     }
  }
Failed to minify the bundle. Error: index.js from UglifyJs
Unexpected token name «p», expected punc «;» [index.js:399,17]
    at doneHandler (E:\sourcecode\project_MedicalServices\01code\msp\node_modules\af-webpack\lib\build.js:91:27)
    at emitRecords.err (E:\sourcecode\project_MedicalServices\01code\msp\node_modules\webpack\lib\Compiler.js:265:13)
    at Compiler.emitRecords (E:\sourcecode\project_MedicalServices\01code\msp\node_modules\webpack\lib\Compiler.js:371:38)
    at emitAssets.err (E:\sourcecode\project_MedicalServices\01code\msp\node_modules\webpack\lib\Compiler.js:258:10)
    at applyPluginsAsyncSeries1.err (E:\sourcecode\project_MedicalServices\01code\msp\node_modules\webpack\lib\Compiler.js:364:12)

解决了!找到使用了es5的npm包,然后换了一个版本

pengshaosu avatar Oct 17 '18 10:10 pengshaosu

es5-imcompatible-versions 在 umijs 2.x以上如何使用呢?

xgj1988 avatar Nov 14 '18 11:11 xgj1988

@xgj1988 https://umijs.org/zh/config/#extrababelincludes

xiaohuoni avatar Nov 15 '18 01:11 xiaohuoni

只能说很赞了 顶一个

BruceChoca avatar Nov 29 '18 05:11 BruceChoca

问的人比较多,录了个视频,https://www.youtube.com/watch?v=z4pWFpPiIoc

sorrycc avatar Dec 06 '18 15:12 sorrycc

@sorrycc I have a PR for sorrycc/roadhog#844 which implements the af-webpack support of TerserJS (documentation)

jrschumacher avatar Dec 26 '18 20:12 jrschumacher

@sorrycc [email protected] 配置了babel node_modules,依然报错

    "env": {
    "production": {
      "es5ImcompatibleVersions": true,
      "extraBabelIncludes": [
        "node_modules/*"
       ]
     }
  }
Failed to minify the bundle. Error: index.js from UglifyJs
Unexpected token name «p», expected punc «;» [index.js:399,17]
    at doneHandler (E:\sourcecode\project_MedicalServices\01code\msp\node_modules\af-webpack\lib\build.js:91:27)
    at emitRecords.err (E:\sourcecode\project_MedicalServices\01code\msp\node_modules\webpack\lib\Compiler.js:265:13)
    at Compiler.emitRecords (E:\sourcecode\project_MedicalServices\01code\msp\node_modules\webpack\lib\Compiler.js:371:38)
    at emitAssets.err (E:\sourcecode\project_MedicalServices\01code\msp\node_modules\webpack\lib\Compiler.js:258:10)
    at applyPluginsAsyncSeries1.err (E:\sourcecode\project_MedicalServices\01code\msp\node_modules\webpack\lib\Compiler.js:364:12)

解决了!找到使用了es5的npm包,然后换了一个版本

如何找到es5的包呢?我再报错信息中看不出来

zjjjjjjjjjjd avatar Mar 23 '19 03:03 zjjjjjjjjjjd

image 我用了 uglify es 版本,详情如图。应为用 babel 的话,压缩了导出会有问题。mark下到这里。

shenqihui avatar May 10 '20 05:05 shenqihui

@sorrycc 移动端项目依赖swiper,在ios9浏览器中白屏,使用如下配置后正常

// .umirc.ts
export default {
  nodeModulesTransform: {
    type: 'none',
    exclude: ['swiper', 'dom7'],
  },
};

swiper 官网说明 如下图

image

Whilconn avatar Jun 07 '20 08:06 Whilconn

image image 不起作用??为什么

baobao12356 avatar Oct 23 '20 12:10 baobao12356

参考这个使用了 query-string@6 和 get-value@3 的例子,https://github.com/umijs/umi-examples/tree/master/es5-imcompatible-versions

这个打开是404 Uploading image.png…

baobao12356 avatar Oct 26 '20 02:10 baobao12356

大佬。已经在es5-imcompatible-versions 里加包了, Uploading image.png… 还是报错 image Uploading image.png…

baobao12356 avatar Oct 26 '20 05:10 baobao12356

TerserWebpackPlugin,webpack5自带

wangmeijian avatar Dec 05 '20 14:12 wangmeijian

@baobao12356 您好,我这边也遇到了这个问题,请问怎么解决的呢?我已经折腾一早上了。。。

AlanKnightly avatar Jan 07 '21 05:01 AlanKnightly