生产环境下运行rake assets:precompile时出现ExecJS::ProgramError错误:意外的标记符号punc«(»,预期标记符号punc«:».

70

部署我的Rails应用程序时,我遇到以下错误:

rake aborted!
   ExecJS::ProgramError: Unexpected token punc «(», expected punc «:» (line: 15, col: 14, pos: 265)

   Error
   at new JS_Parse_Error (/tmp/execjs20150524-4411-1p45n63js:2359:10623)
   at js_error (/tmp/execjs20150524-4411-1p45n63js:2359:10842)
   at croak (/tmp/execjs20150524-4411-1p45n63js:2359:19086)
   at token_error (/tmp/execjs20150524-4411-1p45n63js:2359:19223)
   at expect_token (/tmp/execjs20150524-4411-1p45n63js:2359:19446)
   at expect (/tmp/execjs20150524-4411-1p45n63js:2359:19584)
   at /tmp/execjs20150524-4411-1p45n63js:2359:28513
   at /tmp/execjs20150524-4411-1p45n63js:2359:19957
   at expr_atom (/tmp/execjs20150524-4411-1p45n63js:2359:27269)
   at maybe_unary (/tmp/execjs20150524-4411-1p45n63js:2359:30019)new JS_Parse_Error ((execjs):2359:10623)
   js_error ((execjs):2359:10842)
   croak ((execjs):2359:19086)
   token_error ((execjs):2359:19223)
   expect_token ((execjs):2359:19446)
   expect ((execjs):2359:19584)
   (execjs):2359:28513
   (execjs):2359:19957
   expr_atom ((execjs):2359:27269)
   maybe_unary ((execjs):2359:30019)

这个文件是有效的,在本地主机上可以正常使用。我还尝试在本地运行rake assests:precompile,一切都通过了。最后,我尝试从文件中删除内容、git push并重新部署-仍然出现相同的错误。只有完全删除该文件并重新部署才能解决问题。

欢迎提供任何想法。


你是在说清单文件吗?请明确解释一下。 - Kamesh
哪段CSS代码导致了这个问题?你能提供一下吗?你正在使用哪个版本的execjs? - andreanne.wintheiser
这不是CSS代码,而是Javascript代码。不幸的是我无法提供它,但是在本地主机上使用“rake asset:precompile”可以编译它并且是有效的。我不确定如何检查ExecJS版本,我的Gemfile.lock中有execjs,但没有列出版本号。 - orion3
2
有人能解释一下如何知道错误指的是哪个文件吗?根据这个错误,我怎么确定是哪个实际的JS文件导致了错误? - flyingL123
1
@snitko 如果您选择正确的答案,那对每个人来说都是很好的。看起来Rasovan Skendzic的回答是最好的! - Miguel Peniche
显示剩余8条评论
11个回答

262

我在这里找到了与您遇到的相同问题的帮助。

运行Rails控制台并执行以下操作:

JS_PATH = "app/assets/javascripts/**/*.js"; 
Dir[JS_PATH].each do |file_name|
  puts "\n#{file_name}"
  puts Uglifier.compile(File.read(file_name), harmony: true)
end

它将向您显示Uglifier出现问题的文件和行。


3
这是正确答案。它将找到您的任何错误,无论它们与上述错误是否相似。 - creativereason
5
可以的,翻译如下:“有效!尽管我只需要执行 require 'uglifier' 就可以了。” - Peter P.
2
只需为 dir mask 结尾带有 "" 的 erb 文件添加支持,这可能会为某些人节省时间:"app/assets/javascripts/**/.js*" <-- 结尾有 * - Albert Català
1
我已经多次回到这里,它帮了我很大的忙。在这种情况下,我习惯于编写ES6和Typescript语法,并且一些方法是简写的并使用字符串模板。将其隔离到有问题的文件中是一个重大胜利。 - BradGreens
2
在我的情况下,并不是特定的行出了错误,而是我使用了ES6语法导致一切都崩溃。如果它没有给你一个特定的行作为问题,那么提到需要更新uglify可能是值得的。一旦我更新了uglify,它就给了我一个有用的错误提示,说需要使用harmony:true才能继续进行。 - RonLugge
显示剩余13条评论

33

我猜想在那个js文件中,你有类似以下的代码:

var User = {
    getName() {
        alert("my name");
    }
}

用正确的格式进行替换,

var User = {
    getName: function() {
        alert("my name");
    }
}

对我来说起作用了。

错误明显表明,它期望 ":",但却找到了"("。


这对我来说就是问题所在。除了使用一个变量作为键名之外,还有数组中使用同样的变量名称:不要使用 { id, content },而是使用 { id: id, content: content } - TJ Biddle
2
我的问题出在函数的默认参数上:function test(param1='val1', param2='val1') {}。显然,这只是在ES2015中才成为一种事物。 - Constant Meiring
当你在 ES6 和老式 JavaScript 之间切换上下文时,这个错误惊人地常见! - armchairdj

7

我遇到了同样的问题。

我的情况是某人使用了只支持ES2015以后语法的语法,例如

function someThing(param = true) {
    // do something here
};

尽管我们的环境不支持此功能。

而且错误信息实际上是由Uglifer生成的。


1
是的,当我在运行 gulp --production 时遇到错误,我已经修复了它。 - JS Lee

6

这对我来说非常有效,它告诉我哪一行出错了。谢谢! - Delong Gao

6

在哪里添加这个? - Rhea

5

2019年12月的答案:从版本4.2.0开始(在2019年9月发布),Uglifier现在会显示出漂亮的(带颜色!)调试输出,以展示有问题的代码行。

我遇到了Uglifier :: Error:意外字符'<'错误,即使按照此页面上的所有其他解决方案仍然找不到它。

因此,请转到您的Gemfile,并将Uglifier设置为至少4.2:

# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 4.2'

运行bundle update uglifier来更新它。

然后只需查看输出,它将向您显示类似于以下内容:

在此输入图片描述


1
现在这应该是最佳结果了。更新 uglifier 似乎也没有任何兼容性问题。 - Sebastian Iorga

5

如果Radovan的回答由于库中的问题而无法为您工作,而不是您的代码问题,则可以尝试升级Uglifier并启用ES6编译。

Gemfile.lock

gem 'uglifier', '~> 4.1'

config/environments/production.rb

config.assets.js_compressor = Uglifier.new(harmony: true)

3
在我的情况下,函数定义存在问题,比如说:
function someFunctionName(param1, param2=defaultValue){
  //code 
}

由于上述函数定义不受Uglifier支持,我遇到了错误。默认参数是ES6/ES2015语言规范。
解决上述问题的方法,请参考如何为JavaScript函数设置默认参数值

1
作为回溯无法提供损坏文件信息,对我来说最好的方法是使用git bisect.来识别错误。
它可以帮助您找到引入错误的提交。
假设您在主分支上,首先启动git bisect:
$ git bisect start
$ git bisect bad 

然后你返回到之前的一个可工作的修订版本,假设是20个修订版本以前。

$ git checkout HEAD~20

您运行相同的命令

$ RAILS_ENV=production rake assets:precompile

如果它能正常工作,你就将修订标记为“良好”:

$ git bisect good.

如果git跳转到另一个版本,您需要再次运行相同的命令(assets:precompile),并根据输出结果将其标记为好/坏。

不到1分钟,您应该能够找到引入问题的提交。


1
更新 uglifier gem 到最新版本并更新你的 production.rb 文件。
config.assets.js_compressor = Uglifier.new(harmony: true)

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