UglifyJS在处理node_modules时抛出意外的令牌:关键字(const)。

95

我开始的一个小项目使用了一个通过npm安装的节点模块声明了const变量。运行和测试这个项目很好,但是当执行UglifyJS时,browserify会失败。

意外的标记:关键词(const)

这里有一个通用的Gulp文件,我之前在几个其他项目中成功地使用过,没有遇到这个问题(即没有使用那个特定的节点模块)。

gulpfile.js

'use strict';

const browserify = require('browserify');
const gulp = require('gulp');
const source = require('vinyl-source-stream');
const derequire = require('gulp-derequire');
const buffer = require('vinyl-buffer');
const uglify = require('gulp-uglify');
const sourcemaps = require('gulp-sourcemaps');
const gutil = require('gulp-util');
const path = require('path');
const pkg = require('./package');
const upperCamelCase = require('uppercamelcase');

const SRC_PATH = path.dirname(pkg.main);
const DIST_PATH = path.dirname(pkg.browser);

const INPUT_FILE = path.basename(pkg.main);
const OUTPUT_FILE = path.basename(pkg.browser);

const MODULE_NAME = upperCamelCase(pkg.name);


gulp.task('default', () => {
  // set up the browserify instance on a task basis
  var b = browserify({
    entries: INPUT_FILE,
    basedir: SRC_PATH,
    transform: ['babelify'],
    standalone: MODULE_NAME,
    debug: true
  });

  return b.bundle()
    .pipe(source(OUTPUT_FILE))
    .pipe(buffer())
    .pipe(derequire())
    .pipe(sourcemaps.init({loadMaps: true}))
    .pipe(uglify())
    .on('error', gutil.log)
    .pipe(sourcemaps.write('.'))
    .pipe(gulp.dest(DIST_PATH))
  ;
});

我尝试通过将那个npm安装的模块中所有的const替换为var来修复这个问题,一切都正常。所以我不明白出了什么问题。

const有什么问题吗?除非有人使用IE10,否则所有主要浏览器都支持这种语法。

有没有办法在不需要更改该Node模块的情况下修复它?

更新

我已经暂时(或永久)用Butternut替换了UglifyJS,并且似乎可以工作。


这是不是与节点版本有关的问题?你需要像节点8+这样的版本才能使用const吗?(不确定它是什么时候引入的) - laurent
我从v4开始就一直在使用const。目前我正在使用8.9.1 LTS。 - Yanick Rochon
好的,那很奇怪。你看到了什么错误信息? - laurent
@this.lau_ 和标题中一样的错误信息,但为了清晰起见,我也在问题中添加了它。 - Yanick Rochon
我的意思是你可以尝试卸载那个UglifyJS版本并安装我安装的那个(如果不是同一个版本)。它应该会告诉你是否需要任何依赖关系。 - James
显示剩余3条评论
8个回答

97

正如ChrisR提到的,UglifyJS根本不支持ES6。

你需要使用terser-webpack-plugin来处理ES6(webpack@5将使用此插件进行代码压缩)。

npm install terser-webpack-plugin --save-dev

然后在你的plugins数组中定义

const TerserPlugin = require('terser-webpack-plugin')

  new TerserPlugin({
    parallel: true,
    terserOptions: {
      ecma: 6,
    },
  }),

来源


1
也许你应该建议使用 npm install --save-dev terser-webpack-plugin 呢。 - Rafa Viotti
2
我非常感激这个答案,因为它提醒了我 terser-webpack-plugin 库下面使用的 terser 库。对于其他人来说,请注意:terser 可以作为独立的 cli 使用,就像 uglify-js 一样(即 webpack 不是必需品),这正是我所需要的。 - John Lee
1
但是我们需要使用webpack才能使用这个解决方案吗? - Enrique
@enrique 取决于你想做什么,如果要构建一个符合实际业务需求的网站,你应该一定要尝试使用webpack。我们在webpack社区遇到过这个问题,所以我的回答得到了很高的评价,但从技术上讲,你不需要webpack来构建ES6代码。 - Ser
Terser 已经被精选到 webpack@4 中,详情请见 https://github.com/webpack/webpack/pull/8392。 - Trivikram
uglifyjs.terser Ubuntu 包对我有效。 - BjornW

42

UglifyJS不支持es6语法。const是es6语法中的一种声明方式,因此会报错。

奇怪的是,您使用的程序包未将其文件转换为es5语法,以供在任何地方使用。

如果您仍然想要使用UglifyJS(例如重用配置),请使用ES6+兼容版本的uglify-es。(警告uglify-es现已被弃用。)

正如Ser所提到的那样,您现在应该使用terser-webpack-plugin


3
你可以使用gulp-uglify-es代替gulp-uglify:https://www.npmjs.com/package/gulp-uglify-es - ChrisR
4
UglifyJS 不支持 es6。谢谢!我在任何地方都找不到这条信息。 - Karl Pokus
如果预算不足以迁移到Webpack,请使用gulp-terser. - Riki137

12

我遇到了相同的问题,使用gulp插件gulp-uglify-es解决了这个问题。

我认为这是最简单的解决方案。

只需安装:

npm i gulp-uglify-es --save-dev

接着在你的代码中只需更改这一行

const uglify = require('gulp-uglify');

变为这样:

const uglify = require('gulp-uglify-es').default;

注意,属性.default非常重要,否则会出现uglify不是函数的错误。

如上所述,并且作为ES6的一部分,const运算符只能由更现代的es6 gulp插件"gulp-uglify-es"处理。

您的其余代码无需更改。

此致敬礼!


已测试并可与“node: v12.14”、“gulp cli v2.2.1”和“gulp local v4.0.2”一起使用。 - jimzcc

2

我刚刚遇到了一个问题,我重构了一个Gulp项目,但是由于某种原因,我无法使用官方的Terser Gulp插件。 这个(gulp-terser)没有任何问题。

最初的回答:

如果你在使用Gulp时遇到了问题,可以尝试使用gulp-terser插件来解决。有些官方插件可能会出现问题,而其他第三方插件可能会更加稳定可靠。


1
通过卸载并重新安装UglifyJS,并确保node_modules对齐,解决了一个升级问题。
npm uninstall uglifyjs-webpack-plugin
npm install uglifyjs-webpack-plugin --save-dev
rm -rf node_modules
npm i

您的回答可以通过添加更多支持信息来改进。请[编辑]以添加更多细节,例如引用或文档,以便他人可以确认您的答案是否正确。您可以在帮助中心中找到有关如何编写好答案的更多信息。 - Community
嗨,我对在删除 node_modules 目录之前使用 npm install uglifyjs-webpack-plugin --save-dev 感到困惑。为什么不先执行 rm -rf node_modules,然后再执行 npm install uglifyjs-webpack-plugin --save-dev,最后再执行 npm i 呢? - cconsta1

0

我并不认为这种方法很好,但在我的情况下,我需要做一次然后忘记它,所以我只是去了babel的网站,在线将es6转换为es5并替换输出!


0

我已经在 PHPStorm 的 GUI 中将 UglifyJS 替换为 YUI Compressor JS。现在它可以正常工作了。


-1

使用uglify-es-webpack-plugin更好

    const UglifyEsPlugin = require('uglify-es-webpack-plugin')



    module.exports = {
    plugins: [
            new UglifyEsPlugin({
                compress:{
                    drop_console: true
                }
            }),
    ] 
    }

8
这是一个观点,请详细阐述为什么它更好。 - ChrisR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接