Skip to content
This repository

assets:precompile task does not detect index files #3993

Closed
rwz opened this Issue December 15, 2011 · 29 comments

10 participants

Pavel Pravosud Jeremy Kemper Piotr Okoński Egor Homakov Magnus Bergmark Julian Paas Dmitry Vorotilin Russell Pickett Paul Ingalls Ilya Katz
Pavel Pravosud

I'm using rails 3.1.3 and having assets packed like this:

app/assets/javascripts/my_cool_stuff/
  index.js
  file1.js.coffee
  file2.js.coffee
  ...

The index.js file contains sprockets require_tree . call.

So in development i can type javascript_include_tag 'my_cool_stuff' and it will actually include my_cool_stuff/index.js and all files from my_cool_stuff folder.

However in production it doesn't work. If you add my_cool_stuff.js to config.assets.precompile and run assets:precompile rake-task it will not compile cause rails will look for the the actual file my_cool_stuff.js and not my_cool_stuff/index.js.

I think this is pretty misleading that you can include folders with index files in development but can not get them compiled for production.

Piotr Okoński

Maybe you should try doing something like that in production.rb:

config.assets.precompile += ['index.js']
Pavel Pravosud

Yeah, right now the only workaround is to use javascript_include_tag 'my_cool_stuff/index' in views and add my_cool_stuff/index.js into config.assets.precompile.

Still, this is confusing that you can include folders in development and can not get this working in production.

Piotr Okoński

I'll try to debug that, anyway where did you find info about the ability to provide directory, instead of a file in javascript_include_tag? Maybe it's an undocumented and unsupported feature?

Egor Homakov

Really, it doesn't seem like supported feature. Rails isn't intended to include your index.js when you include directory that contains index.js. IMO that is not an issue

Pavel Pravosud

Well, it's default sprockets behavior and it also works in views in dev env.

Egor Homakov

please provide some more info. what seems to be a wrong behavior in here?

the thing is - when you precompile assets in dev mode it works per request - javascript_include_tag 'my_cool_stuff' makes browser to request my_cool_stuff/index.js what is followed by compilation the whole tree ( require_tree . the bad practise btw)

but in production sprockets are "off". you request files relying solely on public/assets folder, that is precompiled by rake task using standard 'application.js'

the only way to fix the issue mentioned above. Or you could patch sprockets making them to include **/index.js but why

Pavel Pravosud

Right behavior for me would be applying sprockets to each config.assets.precompile file during running assets:precompile task. So including 'my_cool_stuff.js' into it will actually produce my_cool_stuff.js compile asset from folder.

In other words, provide the same logic, javascript_include_file uses.

This way it will match the development mode behavior and slightly reduce WAT-factor.

Pavel Pravosud

On more time. I think this is wrong, when some code works cool in development, and doesn't work at all in production, because helpers use different logic in these two modes.

Egor Homakov

wait. you substitute proper behavior of sprockets with specififc behavior for javascript_include_file. When you call j_i_f it searches for proper file and founds coolstaff/index.js for you. That has nothing to do with sprockets.
That is why when you add coolstaff folder in assets.precompile array it doesn't add 'index.js' - it is different software and not supposed to work this way.

Egor Homakov

really, I still didn't try it on my part so just if able to - prodive output of j_i_f 'yourfolder' in both prod and dev and what the error happens? is it 'index.js insnt preompiled'?

Pavel Pravosud

No, when i call javascript_include_tag 'my_cool_stuff' it uses sprockets and include my_cool_stuff/index.js and all requirements from it. But when i add my_cool_stuff.js to config.assets.precompile, it uses different logic and ends up doing nothing.

I think it should behave the same way. And use the same search/include logic. It would be sane and lead to better assets-pipeline usability.

Egor Homakov

when i call javascript_include_tag 'my_cool_stuff' it uses sprockets

I would argue with that statement. j_i_t doesnt compile anything for you. j_i_t !== sprockets method, ok?

Pavel Pravosud

Who said anything about compiling? I know how jit works, ok?

Pavel Pravosud

https://github.com/rwz/asset_showcase

Here is the demo repo that illustrates the dev/prod inconsistency. It works in development, but fails in production.

Egor Homakov

nice showcase.

config.assets.precompile += [ 'stuff.js' ]

is there such file 'stuff.js'? I didn't find one in root. but you specify sprockets to compile it

Pavel Pravosud

There is obviously no such file. But the right behavior in that case would be to perform sprockets require, like j_i_t does in development, find stuff folder with index.js inside it, and compile stuff.js from it. So in production javascript_include_tag 'stuff' would actually include this compiled file, and not raise ActionView::Template::Error (stuff.js isn't precompiled)

Egor Homakov

it doesnt seem like right behavior to me. too much of magic, assets.precompile is plain and straight array of files or masks so writing stuff.js you mean file "stuff.js" and nothing more. i try again:
1. you call
<%= javascript_include_tag 'stuff.js' %>
2. it prints requiring your stuff/index.js, nice
3. you try to precompile your folder using +='staff.js' but it fails. You expect it walk tree like j_i_t, dont u? Why, it is different method and algorythm

Pavel Pravosud

Damn, i'm really tired of this shit already.

I type javascript_include_tag 'stuff' in development and it does what i want. I type the same fucking thing in production and get an not precompiled exception. And i have no way to compile it without changing the code.

I want rails either disable indexes discovery in j_i_t/s_l_t helpers in development, or provide a way to compile folders with indexes with rake assets:precompile, so fucking development and production environments behaves the same way.

Cause it's the way it should behave.

Egor Homakov

dude, chill out.do you have an idea what is the difference between dev and prod model in context of sprockets? i am sure you do.
у меня уже кончились слова ) когда делаешь precompile он готовит тебе твои ассеты в public/assets. когда ты в деве он делает прекомпиляцию на каждый твой запрос. хоть на /some/folder/not/listed/in/assetsprecompile . говоря совсем простым языком в проде ты работаешь с заготовленным public/assets а в деве тебе его делают по любому твоему запросу. и у тебя банально не правильно добавлена папка +='stuff.js' поэтому она не прекомпилена. я может и дебил но пропатчь спрокеты как тебе удобно и похоже я только тогда пойму твой поинт

Magnus Bergmark
Mange commented April 17, 2012

I'm with you @rwz.

Let's see if we can get everyone on the same page here.

@homakov:

Sprockets have this great feature that notices when a file you reference is a directory and picks the index.<extension> file from it. It's all documented in the Rails guide for the Asset pipeline. This is documented behavior, and also the way I group top-level files that I want to include in layouts.

Let's apply the discrepancy on another feature (Hypothetical; it actually does work like expected)

When I include "foo.js" in my layout; it discovers the file "foo.js.coffee" and uses that one in development, but when I do this in production mode, it fails

I have "foo.js" in my precompile list but it isn't precompiled at all, just ignored

Well, precompile only looks at the file names on disk. You should put "foo.js.coffee" in the precompile list instead of just "foo.js"

Then I shouldn't be able to just include "foo.js" in development mode either. The precompile list should work the same as the view helper

I hope this highlights why there's a problem in the first place.

Julian Paas
jpaas commented April 30, 2012

I'm with @rwz on this too. It's a bug. The docs clearly state that I can use <%= javascript_include_tag 'stuff.js' %> and that should resolve to javascripts/stuff/index.js. This works in dev but not in production.

Egor Homakov
homakov commented May 01, 2012

@Mange you highlighted different problem - precompile paths lookup is different from include_tag lookup. I'm not sure if it should work in a similar way - they have completely different goals - but if you care it's OK to fix it. I don't think it will impact on existing apps anyhow.

Dmitry Vorotilin
route commented May 01, 2012

I totally agree with guys it is issue.

Magnus Bergmark
Mange commented May 02, 2012

@homakov

@Mange you highlighted different problem - precompile paths lookup is different from include_tag lookup.

No, it is the problem. I'm trying to explain it.

Jeremy Kemper jeremy closed this in df84577 May 02, 2012
Russell Pickett

The merged commit, SHA: df84577, changes the behavior in exactly the opposite of the desired way -- it changes 'index' paths to point at their enclosing directories, instead of changing directory paths to look for the index files inside them. This has not fixed the original bug, and has introduced a new one.

I've submitted a pull request, #6655, that explains this in more detail, backs out the new bug, and actually fixes this bug.

Paul Ingalls

I'm currently trying to add a "static_pages/index.js" to config.assets.precompile and it gets totally ignored. Related?

Pavel Pravosud
rwz commented June 22, 2012

@paulingalls yes, but more to #6737 rather than this.

Jeremy Kemper
Owner

Fixed @ 19987b6

Ilya Katz

I maybe late to the party here, but I came across this today and it makes me think that there is a bit of inconsistency - it would be great to see similar errors in development mode (without precompile) and staging/qa/production (with precompile). if index files are ignored in precompile it will cause a problem in qa/prod but will not be a problem in development. wouldn't it be nice to have similar behavior in both modes. Excluding index is fine as long as it is the same compilation-on-the-fly mode

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.