jwhitley / requirejs-rails

RequireJS support for your Rails 3 or 4 application
MIT License
592 stars 202 forks source link

Not appending `.js` resulting in error from host (403 on S3) #95

Closed pboling closed 11 years ago

pboling commented 11 years ago

When requirejs-rails is making the request for my application.js file it is not appending the .js, and the request fails.

Here is my environment:

∴ bundle show rails
/Users/pboling/.rvm/gems/ruby-1.9.3-head@simple/gems/rails-3.2.11
∴ bundle show requirejs-rails
/Users/pboling/.rvm/gems/ruby-1.9.3-head@simple/gems/requirejs-rails-0.9.1
∴ bundle show uglifier
/Users/pboling/.rvm/gems/ruby-1.9.3-head@simple/gems/uglifier-1.3.0

Here is the error (from Chrome's Inspector, Network tab):

Request URL:http://acq-dev.s3.amazonaws.com/assets/application-128a9695562cf7e7f637dbffbac71a7d
Request Method:GET
Status Code:403 Forbidden

And here is the trace of the assets:precompile I did just prior:

∴ brake assets:precompile --trace
Loaded PostgresDefaultStringLimitOverride!
** Invoke assets:precompile (first_time)
** Invoke requirejs:precompile:external (first_time)
** Invoke requirejs:test_node (first_time)
** Execute requirejs:test_node
** Execute requirejs:precompile:external
/Users/pboling/.rvm/rubies/ruby-1.9.3-head/bin/ruby /Users/pboling/.rvm/gems/ruby-1.9.3-head@global/bin/rake requirejs:precompile:all RAILS_ENV=production RAILS_GROUPS=assets --trace
Loaded PostgresDefaultStringLimitOverride!
** Invoke requirejs:precompile:all (first_time)
** Invoke requirejs:precompile:prepare_source (first_time)
** Invoke requirejs:setup (first_time)
** Invoke assets:environment (first_time)
** Invoke requirejs:precompile:disable_js_compressor (first_time)
** Execute requirejs:precompile:disable_js_compressor
** Execute assets:environment
AssetSync: using default configuration from built-in initializer
** Execute requirejs:setup
** Invoke requirejs:clean (first_time)
** Invoke requirejs:setup 
** Execute requirejs:clean
** Execute requirejs:precompile:prepare_source
** Invoke requirejs:precompile:generate_rjs_driver (first_time)
** Invoke requirejs:setup 
** Execute requirejs:precompile:generate_rjs_driver
** Invoke requirejs:precompile:run_rjs (first_time)
** Invoke requirejs:setup 
** Invoke requirejs:test_node (first_time)
** Execute requirejs:test_node
** Execute requirejs:precompile:run_rjs
** Invoke requirejs:precompile:digestify_and_compress (first_time)
** Invoke requirejs:setup 
** Execute requirejs:precompile:digestify_and_compress
** Execute requirejs:precompile:all
** Execute assets:precompile
/Users/pboling/.rvm/rubies/ruby-1.9.3-head/bin/ruby /Users/pboling/.rvm/gems/ruby-1.9.3-head@global/bin/rake assets:precompile:all RAILS_ENV=production RAILS_GROUPS=assets --trace
Loaded PostgresDefaultStringLimitOverride!
** Invoke assets:precompile:all (first_time)
** Execute assets:precompile:all
** Invoke assets:precompile:primary (first_time)
** Invoke assets:environment (first_time)
** Execute assets:environment
AssetSync: using default configuration from built-in initializer
** Invoke tmp:cache:clear (first_time)
** Execute tmp:cache:clear
** Execute assets:precompile:primary
Loaded PostgresDefaultStringLimitOverride!
** Invoke assets:precompile:nondigest (first_time)
** Invoke assets:environment (first_time)
** Execute assets:environment
AssetSync: using default configuration from built-in initializer
** Invoke tmp:cache:clear (first_time)
** Execute tmp:cache:clear
** Execute assets:precompile:nondigest
AssetSync: Syncing.
Using: Directory Search of /Users/pboling/Documents/RubyMineProjects/simple/public/assets
Uploading: assets/application-86fe09ac641d920ff75bd3137d462901.js
Uploading: assets/application-86fe09ac641d920ff75bd3137d462901.js.gz
Uploading: assets/rails_admin/jquery.colorpicker-c5cb1fdf4445311094a37c16fc930f6c.js
Uploading: assets/rails_admin/jquery.colorpicker-c5cb1fdf4445311094a37c16fc930f6c.js.gz
Uploading: assets/rails_admin/rails_admin-82b0ae763c7d2b0aa5da930edc3f99d0.js
Uploading: assets/rails_admin/rails_admin-82b0ae763c7d2b0aa5da930edc3f99d0.js.gz
Uploading: assets/require-b824ec15f6834b17fbae35c983413a4b.js
Uploading: assets/require-b824ec15f6834b17fbae35c983413a4b.js.gz
AssetSync: Done.
jordandh commented 11 years ago

@pboling I believe this issue is fixed in the master branch but the version number has not been bumped and it placed on rubygems.org.

I had the same problem with no .js extension but using the master branch worked. Sadly this isn't working well on our production servers because of some other issues that don't like a custom gem source.

A new release of requirejs-rails asap would be super helpful.

pboling commented 11 years ago

@jordandh: I suspected as much after looking at the commit messages on master. I even tried using master, but master doesn't work at all for me. Specifically:

** Execute requirejs:precompile:run_rjs
rake aborted!
Asset compilation with node failed.
/Users/pboling/.rvm/gems/ruby-1.9.3-head@simple/bundler/gems/requirejs-rails-6cc90a538ada/lib/tasks/requirejs-rails_tasks.rake:112:in `block (3 levels) in <top (required)>'

The weird thing is that rake file hasn't changed in 6 months, so I'm running the same one in the released version.

pboling commented 11 years ago

The other weird thing is that line of the rake task is attempting to run node, and I do have node installed. So now I am:

  1. updating to the latest brew of node (0.8.17)
  2. I added the suggested directory (/usr/local/share/npm/bin) to my path
  3. opened a new shell
  4. reran assets:precompile and got the same error
** Execute requirejs:precompile:run_rjs
rake aborted!
Asset compilation with node failed.
/Users/pboling/.rvm/gems/ruby-1.9.3-head@simple/bundler/gems/requirejs-rails-6cc90a538ada/lib/tasks/requirejs-rails_tasks.rake:112:in `block (3 levels) in <top (required)>'
pboling commented 11 years ago

Actually, now I am getting this same error on the released version as well as master. Nothing is working for me, but the reason for, and point of, failure keep changing as I fiddle.

pboling commented 11 years ago

It turns out that my problems were caused by these lines in my requirejs.yml:

paths:
  domReady:
    - '//cdnjs.cloudflare.com/ajax/libs/require-domReady/2.0.1/domReady.js'
    - 'domReady'
  jquery:
    - '//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js'
    - '//cdnjs.cloudflare.com/ajax/libs/jquery/1.8.3/jquery.min.js'
    - '//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.3.min.js'
    - 'jquery'

I expected them to work, but Node fails to compile my assets when using them.

Moving them into my main.js in a supplemental require.config fixed it.

require.config
    paths:
      domReady: [ '//cdnjs.cloudflare.com/ajax/libs/require-domReady/2.0.1/domReady', 'domReady' ]
      jquery: [ '//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min', '//cdnjs.cloudflare.com/ajax/libs/jquery/1.8.3/jquery.min', '//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.3.min', 'jquery']

Now the latest release continues to not work due to this bug (in the title), but using the master it works!

gem 'requirejs-rails', github: 'jwhitley/requirejs-rails'
pboling commented 11 years ago

I added all my files to the precompile setting for the asset pipeline in my environment:

  config.assets.precompile += %w(
    main.js
      domReady.js
      jquery-adapter.js
        jquery.js jquery_ujs.js
      foundation-adapter.js
        foundation/jquery.cookie foundation/jquery.event.move foundation/jquery.event.swipe foundation/jquery.foundation.accordion foundation/jquery.foundation.alerts foundation/jquery.foundation.buttons foundation/jquery.foundation.clearing foundation/jquery.foundation.forms foundation/jquery.foundation.joyride foundation/jquery.foundation.magellan foundation/jquery.foundation.mediaQueryToggle foundation/jquery.foundation.navigation foundation/jquery.foundation.orbit foundation/jquery.foundation.reveal foundation/jquery.foundation.tabs foundation/jquery.foundation.tooltips foundation/jquery.foundation.topbar foundation/jquery.offcanvas foundation/jquery.placeholder foundation/modernizr.foundation foundation/app
      home.js
  )

and switched to almond:

  config.requirejs.loader = :almond

Moved application.js.coffee to main.js.coffee, got rid of the require.config in my main.js, and setup main.js as my target for almond in config/requirejs.yml:

modules:
  - name: 'main'
wrap: true
waitSeconds: 15
paths:
  domReady: 'domReady'
  jquery: 'jquery'
  app: 'foundation/app'
  "foundation-adapter": 'foundation-adapter'
  "cookie": 'foundation/jquery.cookie'
  "move": 'foundation/jquery.event.move'
  "swipe": 'foundation/jquery.event.swipe'
  "accordion": 'foundation/jquery.foundation.accordion'
  "alerts": 'foundation/jquery.foundation.alerts'
  "buttons": 'foundation/jquery.foundation.buttons'
  "clearing": 'foundation/jquery.foundation.clearing'
  "forms": 'foundation/jquery.foundation.forms'
  "joyride": 'foundation/jquery.foundation.joyride'
  "magellan": 'foundation/jquery.foundation.magellan'
  "mediaQueryToggle": 'foundation/jquery.foundation.mediaQueryToggle'
  "navigation": 'foundation/jquery.foundation.navigation'
  "orbit": 'foundation/jquery.foundation.orbit'
  "reveal": 'foundation/jquery.foundation.reveal'
  "tabs": 'foundation/jquery.foundation.tabs'
  "tooltips": 'foundation/jquery.foundation.tooltips'
  "topbar": 'foundation/jquery.foundation.topbar'
  "offcanvas": 'foundation/jquery.offcanvas'
  "placeholder": 'foundation/jquery.placeholder'
  "modernizr": 'foundation/modernizr.foundation'
  jquery_ujs: 'jquery_ujs'
  home: 'home'
map:
  "*":
    jquery: 'jquery-adapter'
  "jquery_ujs":
    jquery: 'jquery'
shim:
  'domReady':
    exports: 'domReady'
  'topbar':
    deps: ['jquery']
  'cookie':
    deps: ['jquery']
  'move':
    deps: ['jquery']
  'swipe':
    deps: ['jquery']
  'accordion':
    deps: ['jquery']
  'alerts':
    deps: ['jquery']
  'buttons':
    deps: ['jquery']
  'clearing':
    deps: ['jquery']
  'forms':
    deps: ['jquery']
  'joyride':
    deps: ['jquery']
  'magellan':
    deps: ['jquery']
  'mediaQueryToggle':
    deps: ['jquery']
  'navigation':
    deps: ['jquery']
  'orbit':
    deps: ['jquery']
  'reveal':
    deps: ['jquery']
  'tabs':
    deps: ['jquery', 'forms']
  'tooltips':
    deps: ['jquery']
  'topbar':
    deps: ['jquery']
  'offcanvas':
    deps: ['jquery']
  'placeholder':
    deps: ['jquery']
  'app':
    deps: ['jquery']
  'foundation-adapter':
    deps: ['jquery', 'cookie', 'accordion', 'alerts', 'buttons', 'clearing', 'forms', 'joyride', 'mediaQueryToggle', 'navigation', 'orbit', 'reveal', 'tabs', 'tooltips', 'topbar', 'offcanvas', 'placeholder', 'modernizr', 'app']
  jquery:
    exports: '$'
  foundation:
    exports: '$'
  jquery_ujs:
    deps: ['jquery']
  home:
    deps: ['jquery', 'foundation-adapter']
  priority: ['domReady', 'jquery', 'foundation-adapter']

I got my foundation and jquery adapters both working, though I had to skip some of the foundation plugins for now.

jquery-adapter.js.coffee:

define ['jquery', 'jquery_ujs'], ($) ->
  $

foundation-adapter.js.coffee:

define ['jquery', 'cookie', 'accordion', 'alerts', 'buttons', 'clearing', 'forms', 'joyride', 'mediaQueryToggle', 'navigation', 'orbit', 'reveal', 'tabs', 'tooltips', 'topbar', 'offcanvas', 'placeholder', 'modernizr', 'app'], ($) ->
  $

So it all works with the following caveats:

  1. No CDNs :(
  2. No externally loaded JS in either the requirejs.yml paths, or in individual module definitions.
  3. This means my external js dependencies, like Google Analytics, LaunchRock and Optimize.ly are now loaded as part of the layout and views:

My layout (in part):

    = requirejs_include_tag "main"
    = csrf_meta_tags

    / Google Analytics Tracker
    javascript:
      var _gaq = _gaq || [];
      _gaq.push(['_setAccount', 'blah-blah-blah]);
      _gaq.push(['_trackPageview']);
      (function() {
        var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
      })();
    / Kiss Metrics Tracker
    javascript:
      var _kmq = _kmq || [];
      function _kms(u){
        setTimeout(function(){
          var s = document.createElement('script'); var f = document.getElementsByTagName('script')[0]; s.type = 'text/javascript'; s.async = true;
          s.src = u; f.parentNode.insertBefore(s, f);
        }, 1);
      }
      _kms('//i.kissmetrics.com/i.js');_kms('//doug1izaerwt3.cloudfront.net/...blah...blah...blah.js');

And my view:

    / Begin LaunchRock Widget
    #lr-widget rel="blah-blah-blah"
    = javascript_include_tag "//ignition.launchrock.com/ignition-current.min.js"
    / End LaunchRock Widget

javascript:
  var checkDOMChange, _optimizely;

  _optimizely = function(u) {
    return setTimeout((function() {
      var f, s;
      s = document.createElement("script");
      f = document.getElementsByTagName("script")[0];
      s.type = "text/javascript";
      s.async = true;
      s.src = u;
      return f.parentNode.insertBefore(s, f);
    }), 1);
  };

  checkDOMChange = function() {
    var launchRock;
    launchRock = $(".LR-content");
    if (launchRock && launchRock.length) {
      _optimizely("http://cdn.optimizely.com/js/blah-blah-blah.js");
      launchRock.on('launchrock_signup', function(evt) {
        window.optimizely = window.optimizely || [];
        optimizely.push(["trackEvent", "go_button_clicked"]);
      })
      return false;
    } else {
      return setTimeout(checkDOMChange, 200);
    }
  };

  $(document).ready(checkDOMChange);