将 node_modules 添加到 rails 资产路径导致资产编译错误

Add node_modules to the rails asset paths causes an asset compilation error

如果我在 Rails 5.1 上向我的 config/initializers/assets.rb 添加以下行,我会收到资产编译错误:

assets = Rails.application.config.assets
assets.version = '1.0'
assets.paths << Rails.root.join('node_modules')

当然,该文件确实包含更多行,但我已将其剥离作为尝试调试它的一部分。我还清空了 application.coffeeapplication.scss 文件的所有内容。

这是 --traceRAILS_ENV=production

的编译错误
** Execute assets:precompile
I, [2019-07-26T19:58:48.269791 #86008]  INFO -- : Writing /Users/samuelstickland/development/hubbado_core/public/assets/application-f78f0f583e152fa235ca51f99bab70d1aeb59675de57c78bcef18b5a2e8a5a5f.js
I, [2019-07-26T19:58:48.271029 #86008]  INFO -- : Writing /Users/samuelstickland/development/hubbado_core/public/assets/application-f78f0f583e152fa235ca51f99bab70d1aeb59675de57c78bcef18b5a2e8a5a5f.js.gz
rake aborted!
ExecJS::RuntimeError: SyntaxError: Unexpected token: operator (>)
JS_Parse_Error.get ((execjs):3538:621)
(execjs):4060:48
(execjs):1:102
Object.<anonymous> ((execjs):1:120)
Module._compile (internal/modules/cjs/loader.js:689:30)
Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
Module.load (internal/modules/cjs/loader.js:599:32)
tryModuleLoad (internal/modules/cjs/loader.js:538:12)
Function.Module._load (internal/modules/cjs/loader.js:530:3)
Function.Module.runMain (internal/modules/cjs/loader.js:742:12)
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/execjs-2.7.0/lib/execjs/external_runtime.rb:39:in `exec'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/execjs-2.7.0/lib/execjs/external_runtime.rb:21:in `eval'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/execjs-2.7.0/lib/execjs/external_runtime.rb:46:in `call'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/uglifier-3.2.0/lib/uglifier.rb:195:in `run_uglifyjs'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/uglifier-3.2.0/lib/uglifier.rb:157:in `compile'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/uglifier_compressor.rb:53:in `call'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/uglifier_compressor.rb:28:in `call'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/processor_utils.rb:75:in `call_processor'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/processor_utils.rb:57:in `block in call_processors'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/processor_utils.rb:56:in `reverse_each'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/processor_utils.rb:56:in `call_processors'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/loader.rb:134:in `load_from_unloaded'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/loader.rb:60:in `block in load'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/loader.rb:317:in `fetch_asset_from_dependency_cache'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/loader.rb:44:in `load'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/cached_environment.rb:20:in `block in initialize'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/cached_environment.rb:47:in `load'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/base.rb:66:in `find_asset'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/base.rb:73:in `find_all_linked_assets'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/manifest.rb:142:in `block in find'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/legacy.rb:114:in `block (2 levels) in logical_paths'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/path_utils.rb:228:in `block in stat_tree'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/path_utils.rb:212:in `block in stat_directory'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/path_utils.rb:209:in `each'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/path_utils.rb:209:in `stat_directory'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/path_utils.rb:227:in `stat_tree'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/path_utils.rb:231:in `block in stat_tree'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/path_utils.rb:212:in `block in stat_directory'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/path_utils.rb:209:in `each'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/path_utils.rb:209:in `stat_directory'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/path_utils.rb:227:in `stat_tree'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/path_utils.rb:231:in `block in stat_tree'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/path_utils.rb:212:in `block in stat_directory'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/path_utils.rb:209:in `each'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/path_utils.rb:209:in `stat_directory'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/path_utils.rb:227:in `stat_tree'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/path_utils.rb:231:in `block in stat_tree'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/path_utils.rb:212:in `block in stat_directory'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/path_utils.rb:209:in `each'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/path_utils.rb:209:in `stat_directory'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/path_utils.rb:227:in `stat_tree'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/legacy.rb:105:in `each'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/legacy.rb:105:in `block in logical_paths'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/legacy.rb:104:in `each'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/legacy.rb:104:in `logical_paths'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/manifest.rb:140:in `find'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/sprockets/manifest.rb:186:in `compile'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-rails-3.2.1/lib/sprockets/rails/task.rb:68:in `block (3 levels) in define'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-3.7.2/lib/rake/sprocketstask.rb:147:in `with_logger'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/sprockets-rails-3.2.1/lib/sprockets/rails/task.rb:67:in `block (2 levels) in define'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/rake-12.3.2/lib/rake/task.rb:273:in `block in execute'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/rake-12.3.2/lib/rake/task.rb:273:in `each'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/rake-12.3.2/lib/rake/task.rb:273:in `execute'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/rake-12.3.2/lib/rake/task.rb:214:in `block in invoke_with_call_chain'
/Users/samuelstickland/.rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/monitor.rb:226:in `mon_synchronize'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/rake-12.3.2/lib/rake/task.rb:194:in `invoke_with_call_chain'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/rake-12.3.2/lib/rake/task.rb:183:in `invoke'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/rake-12.3.2/lib/rake/application.rb:160:in `invoke_task'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/rake-12.3.2/lib/rake/application.rb:116:in `block (2 levels) in top_level'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/rake-12.3.2/lib/rake/application.rb:116:in `each'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/rake-12.3.2/lib/rake/application.rb:116:in `block in top_level'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/rake-12.3.2/lib/rake/application.rb:125:in `run_with_threads'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/rake-12.3.2/lib/rake/application.rb:110:in `top_level'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/rake-12.3.2/lib/rake/application.rb:83:in `block in run'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/rake-12.3.2/lib/rake/application.rb:186:in `standard_exception_handling'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/rake-12.3.2/lib/rake/application.rb:80:in `run'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/gems/rake-12.3.2/exe/rake:27:in `<top (required)>'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/bin/rake:23:in `load'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/bin/rake:23:in `<main>'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/bin/ruby_executable_hooks:24:in `eval'
/Users/samuelstickland/.rvm/gems/ruby-2.5.1/bin/ruby_executable_hooks:24:in `<main>'
Tasks: TOP => assets:precompile

我完全不知道这个错误可能来自哪里,因为我不希望由于空应用程序而编译任何内容。coffee/scss,图像除外。

事实上,在 运行 一个没有 node_modules 的 assets:precompile 之后,我只得到以下 JS 和 CSS 文件:

$ find ./public/assets/ -name "*.js"
./public/assets//application-f78f0f583e152fa235ca51f99bab70d1aeb59675de57c78bcef18b5a2e8a5a5f.js
./public/assets//active_admin-f78f0f583e152fa235ca51f99bab70d1aeb59675de57c78bcef18b5a2e8a5a5f.js

这两个都是'empty',只包含(function(){}).call(this);

$ find ./public/assets/ -name "*.css"
./public/assets//active_admin/print-ef81b6a45bca13d9584a56677a4cc64d9cb053c768465f43ef448caf6f220216.css
./public/assets//active_admin-c1ac2e411944e447bcbf94ec2d97a0f2825ec0153bcbda2925f69da7ea6db226.css
./public/assets//application-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.css

此处 application.css 资产完全为空。活跃的管理文件中有很多 CSS。

资产路径中的 node_modules 会导致上面显示的语法错误。

好的,事实证明 sprockets 会贪婪地处理它在名为 application 的目录中找到的任何 JS!

我通过更改我的丑化器来处理 ES6 语法发现了这一点:

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

然后发现assets编译又产生了一个JS文件:

./public/assets//@schematics/angular/application/index-7cb879a643459c580f46b4127272b2918753e9941c074dcf27faea589ca610de.js
./public/assets//application-f78f0f583e152fa235ca51f99bab70d1aeb59675de57c78bcef18b5a2e8a5a5f.js

文件来自这里:

$ find ./node_modules/ | grep -E "application/.*.js$"
./node_modules//@schematics/angular/application/index.js
./node_modules//@schematics/angular/application/files/karma.conf.js
./node_modules//@schematics/angular/application/files/protractor.conf.js