Ruby on Rails执行rake assets:precompile时Uglifier::Error错误如何修复?
问题描述
我在命令行执行rake assets:precompile RAILS_ENV=production命令时,遇到了资源预编译失败的问题,完整错误信息如下:
rake aborted! Uglifier::Error: Unexpected token: operator (<) /usr/local/rvm/gems/ruby-2.3.4/gems/uglifier-4.1.4/lib/uglifier.rb:234:in parse_result' /usr/local/rvm/gems/ruby-2.3.4/gems/uglifier-4.1.4/lib/uglifier.rb:216:in run_uglifyjs' /usr/local/rvm/gems/ruby-2.3.4/gems/uglifier-4.1.4/lib/uglifier.rb:168:in compile' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/compressing.rb:65:in block in js_compressor=' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/legacy_proc_processor.rb:31:in call' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/processor_utils.rb:75:in call_processor' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/processor_utils.rb:57:in block in call_processors' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/processor_utils.rb:56:in reverse_each' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/processor_utils.rb:56:in call_processors' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/loader.rb:134:in load_from_unloaded' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/loader.rb:60:in block in load' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/loader.rb:317:in fetch_asset_from_dependency_cache' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/loader.rb:44:in load' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/cached_environment.rb:20:in block in initialize' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/cached_environment.rb:47:in load' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/base.rb:66:in find_asset' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/base.rb:73:in find_all_linked_assets' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/manifest.rb:142:in block in find' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/legacy.rb:114:in block (2 levels) in logical_paths' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/path_utils.rb:228:in block in stat_tree' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/path_utils.rb:212:in block in stat_directory' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/path_utils.rb:209:in each' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/path_utils.rb:209:in stat_directory' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/path_utils.rb:227:in stat_tree' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/legacy.rb:105:in each' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/legacy.rb:105:in block in logical_paths' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/legacy.rb:104:in each' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/legacy.rb:104:in logical_paths' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/manifest.rb:140:in find' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/sprockets/manifest.rb:185:in compile' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-rails-3.2.1/lib/sprockets/rails/task.rb:68:in block (3 levels) in define' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-3.7.1/lib/rake/sprocketstask.rb:147:in with_logger' /usr/local/rvm/gems/ruby-2.3.4/gems/sprockets-rails-3.2.1/lib/sprockets/rails/task.rb:67:in block (2 levels) in define' /usr/local/rvm/gems/ruby-2.3.4/gems/rake-12.3.0/exe/rake:27:in <top (required)>' /usr/local/rvm/gems/ruby-2.3.4/bin/ruby_executable_hooks:15:in eval' /usr/local/rvm/gems/ruby-2.3.4/bin/ruby_executable_hooks:15:in <main>' Tasks: TOP => assets:precompile (See full trace by running task with --trace)
修复方案
这个错误是Uglifier(Ruby生态里的JS压缩工具)在处理JavaScript文件时碰到了无效语法,核心问题是<符号出现在了不符合JS语法规则的位置。下面是一步步的排查和修复方法:
1. 检查JS文件里的HTML模板或未转义代码
最常见的原因是你在JS文件里直接写了HTML片段却没正确处理,比如:
// 错误写法:直接把HTML当JS代码写 const userTemplate = <div class="user">{username}</div>;
这种情况要把HTML包裹成字符串:
// 正确写法:用引号把HTML转为字符串 const userTemplate = '<div class="user">' + username + '</div>'; // 或者用ES6模板字符串 const userTemplate = `<div class="user">${username}</div>`;
要是你用了React的JSX语法,那得确保JSX文件已经被Babel编译成标准JS再交给Uglifier处理,不然Uglifier识别不了JSX里的<符号。
2. 定位具体出错的JS文件
你可以执行带--trace参数的预编译命令,拿到更详细的调用栈:
rake assets:precompile RAILS_ENV=production --trace
这个命令会告诉你Uglifier在处理哪个文件时崩溃,这样你就能精准排查那个文件的语法问题。要是还是找不到,就试试注释掉最近新增或修改的JS文件,逐个排除,找到出错的代码段。
3. 调整Uglifier配置支持ES6+语法
如果你的JS代码用了ES6及以上的语法,而当前Uglifier的默认配置不支持,就会触发语法错误。你可以在config/environments/production.rb里修改Uglifier的配置:
# 针对你的Uglifier 4.1.4版本,开启ES6支持 config.assets.js_compressor = Uglifier.new(ecma: 2015)
这样Uglifier就能正确解析ES6语法了。
4. 检查第三方JS库是否损坏或语法不兼容
有时候引入的第三方库文件可能损坏,或者本身用了Uglifier不支持的语法。你可以:
- 重新下载替换
vendor/assets/javascripts或app/assets/javascripts里的第三方库; - 验证所有JS文件的语法,比如用ESLint之类的工具扫描一遍,找出语法错误。
内容的提问来源于stack exchange,提问作者Steven Guevarra
相关产品推荐
相关产品推荐

