Sprockets::CircularDependencyError in manifest file using asset pipeline - ruby-on-rails

i am trying to use asset pipeline and want to have more then one manifest file. At present i have application.css manifest file and admin_area.css manifest file. One of the stack answer suggested to remove application.css manifest, however it will not solve my intent.
Current Error msg:
Sprockets::CircularDependencyError in Authenticate#dashboard
projectfolder/app/assets/stylesheets/admin_area.css has already been required
My current rails version is : 4.1.5
And also please suggest solution to have more then one javascript manifest file.
thanks in advance.

If you have require_tree . directive in both your manifests - one of them tries to require another manifests, and another will try to require first, and it leads to circular error.
Instead you should explicitly require assets in your manifests.

Manifest file: If you look at docs, it says
Sprockets uses manifest files to determine which assets to include and serve. These manifest files contain directives - instructions that tell Sprockets which files to require in order to build a single CSS or JavaScript file
so in short rails asset pipeline precompile your all of your assets like css,js in single file(one file for all of your css files and one js file for all of your js). By doing this load time of your pages is significantly reduced because your browser makes fewer requests to get these files individually.
Having More than one manifest files:
In some cases like in your case or if you are making your app compatible with <= IE8 then you might want to have more than one manifest files as IE only allows a some fixed size of your styles and ignore your other styles
To achieve this you follow these steps:
a. Remove require_tree . from your application.css file because it will require all of your styles present in app/assets/stylesheets and hence you should require each file individually.
b. In case of Production you need to precompile your assets and for that you'll have to add your individual files by
#config/application.rb or config/environments/production.rb
Rails.application.config.assets.precompile += ['admin_area.css', 'other.css', 'some_file.js']
Your error:
Sprockets::CircularDependencyError in Authenticate#dashboard projectfolder/app/assets/stylesheets/admin_area.css has already been required
Your error clearly says you have a circular dependency meaning one of your files is trying to load resources of other and other one is trying to load resources of first one making a circular dependency. As #MikDiet already mentioned in his answer that you have require_tree . in both of your css files.

Related

Rails assets usage clarification

I am new to rails and I'm a bit confused about how assets are loaded. I can get things working but I would like to understand what really happens behind the scenes.
I have been reading the documentation but there are things that I don't understand completely.
MANIFEST FILE
First thing that confuses me is the usage of manifest files.
For instance if in my app/assets/javascripts/application.js file I have:
//= require_tree .
Rails documentation says:
tells Sprockets to recursively include all JavaScript files in the
specified directory into the output
What isn't clear to me is which directory? app/assets/javascripts/?
Does that mean that if I add a file in app/assets/javascripts/ it will be loaded and served?
If I add a gem that requires to add a file example.js I need to add to the manifest file:
//= require example.js
But why is this necessary if //= require_tree already loads and serve files in app/assets/javascripts/ which is the location where I have put my example.js? Ok that allows me to specify the order if later I add more requires. But other than that?
HTML FILE
And then the script to be included in application.html.erb
<%= javascript_include_tag ('application'), 'data-turbolinks-track' => true %>
I understand this loads the application.js file mentioned above and therefore the various //= require in it.
Sometimes happens that is required to script the particular file as:
<script src="js/example.js"></script>
Is this scenario wouldn't be <script src="js/example.js"></script> doing the exact same thing of //= require example.js?
PUBLIC VS APP ASSETS
I understand that if I place my example.js file on public/assets folder it won't be compiled but served separately. Why would I do that? Is it reasonable to do it in case a file is not served correctly when concatenated and compiled and works only if served separated? In other words, if I include a .js file on app/assest and it has problems to load or break things, is it worth to try to remove it from there and move it to public/assets or does this just not make sense?
APP ASSETS VS VENDOR ASSETS
On which scenario should I add a file to vendor assets instead of app assets? What is the difference between adding it to a place or another?
And in my vendor/assets/javascripts I have only an empty .keep file. So there'n so such thing as manifest file on app/assets. How are files in this folder referenced then?
For directives that take a path argument, you may specify either a
logical path or a relative path. Relative paths begin with ./ and
reference files relative to the location of the current file.
So //= require_tree . tells sprockets to load any files in app/assets/javascripts/ and concatenate them into application.js.
Is this scenario wouldn't be <script src="js/example.js"></script>
doing the exact same thing of //= require example.js?
No. Rails serves the assets as seperate files in development so that you get a meaningful line number and file reference when errors occur.
In production it concatenates and minifies the assets which is important for performance.
Sprockets does not check your views / layouts for script tags. So the the former would result in two requests.
I understand that if I place my example.js file on public/assets
folder it won't be compiled but served separately. Why would I do
that?
The public directory is placed under the servers web root. Since the files there are served without much intervention its a good place for things like error pages or where you need assets that have a static name without a cache busting fingerprint.
On which scenario should I add a file to vendor assets instead of app
assets? What is the difference between adding it to a place or
another?
/vendor/assets is the place to put assets that are not created by you or which are not part of the application. Both are added to the sprockets load paths so the results are identical. Its rather just a question of code organisation.
https://github.com/rails/sprockets
http://guides.rubyonrails.org/asset_pipeline.html

What is the proper way to link big template assets into rails erb files?

I am developing a rails application starting from webarch template. I know that adding the whole assets folder in the public/ folder will link the assets with my views, but it would not be taking advantage of the assets pipeline functions. The template has a lot of plugins and different options and one generally does not use all of it. The assets folder's size is 30MB.
I though about putting it inside vendor/assets and using it with the asset pipeline but this generates two problems:
I would be serving 30MB of minified code and using a small percentage of it in my app.
I would have to manually rewrite the whole assets folder to use links the way asset pipeline wants it (javascript_include_tag "file" to serve file.js). Of course, I would do this via a script but it still seems like a problem someone should have encountered first.
Since neither vendor/assets and public/ folders seem to be a proper location for these files I would like a better option (or a way to make the later options work better).
A solution to keep your files under asset pipeline when they are too big to reasonably be left in one single minimified asset file is to split your assets by categories, compile those categories in different minimified files, and include them in your views when needed.
I do it for an app that contains several "heavy" javascripts components that are located in different area of my app and are not often used.
1- Organize your file structure
In app/assets/javascrips and app/assets/stylesheets create one directory per category we are going to create. Examples:
app/assets/javascrips/common
app/assets/javascrips/admin
app/assets/javascrips/user_account
2- Create your manifests
In app/assets/javascrips and app/assets/stylesheets create one manifest file per category and have them included the related directory
File app/assets/javascrips/common.js
//= require jquery
//= require_tree ./common
File app/assets/javascrips/admin.js
//= require_tree ./admin
File app/assets/javascrips/user_account.js
//= require_tree ./user_account
3- Add your manifests to rails precompile list
You can do it in config/application.rb file, but when it gets big it is preferable to create an initializer file config/initializers/assets.rb
Rails.application.configure do
config.assets.precompile += %w[common.js admin.js user_account.js]
end
4- Include them in your views and layouts, and set-up your javascript libraries.
Import the assets files into layouts and views. It can be a good idea to create several layouts for different area of your application that would be using common assets files. The methods to use are
stylesheet_link_tag 'manifest_file' and javascript_include_tag 'manifest_file'
And keep in mind you may have to tell your javascript plug-ins they need to use the miniminied file when dynamically loading files. For them you can use a configuration .js.erb file. Example:
File app/assets/javascrips/admin/plug-in_config.js.erb
PLUGIN.config('dynamicFileName', '<%= javascript_path('manifest_file') %>');

How to load vendor asset folder in Rails 4?

I have a plugin with many types of files, and its own tree structure (html, css, js, documentation, images, etc)
Rather than going through the plugin folder, and splitting all the css and js files into the vendor/assets/js/ vendor/assets/css/ folders, I want to just keep the entire plugin folder as is. For example,
vendor/assets/multipurpose_bookshelf_slider/
How do I make sure the paths load properly, and reference them in my manifest files?
Currently, I have some files place as follows (not exhaustive)
/my_app/vendor/assets/multipurpose_bookshelf_slider/css/skin01.css
/my_app/vendor/assets/multipurpose_bookshelf_slider/js/jquery.easing.1.3.js
/my_app/vendor/assets/multipurpose_bookshelf_slider/
/my_app/vendor/assets/multipurpose_bookshelf_slider/
I'm referencing them in
application.js
//= require multipurpose_bookshelf_slider/js/jquery.easing.1.3.js
//= require multipurpose_bookshelf_slider/js/jquery.bookshelfslider.min.js
application.css.scss
#import "css/bookshelf_slider";
#import "css/skin01";
Any folder created directly under assets will be added to the load paths. Files in that folder can be referenced as usual like so:
If you have
vendor/assets/custom/js/file.js
vendor/assets/custom/css/file.css
then vendor/assets/custom/ will be added to the load paths.
Include your files in the following files by doing the following:
application.js
//= require js/file
application.css.scss
#import "css/file";
Once that's done, make sure to restart your local server, since it is upon starting your server that the load paths get recognized.
Note: to see a list of load paths, type in your terminal rails c, then type Rails.application.config.assets.paths.
If the application you're running has the assets-pipeline activated, it should find your assets after expanding the path in your application.rb
config.assets.paths << Rails.root.join("multipurpose_bookshelf_slider")
I prefer D7na's answer but with a bit of improvement in my opinion.
As long as this is related to assets, I think it is better to be placed in the assets.rb file.
assets.rb:
Rails.application.config.assets.paths << Rails.root.join("multipurpose_bookshelf_slider")

Link directly to compiled resource in asset pipeline?

I have a script that's basically a "widget" that users embed.
It's got just simple vanilla javascript and doesn't have any require's to other resources. It's located at /app/assets/javascripts/delivery.js
What I want to do is have the file get compressed/compiled and then let users link directly to it from a script tag, ie. <script src="http://example.com/assets/delivery.js"></script>
But right now...that's a no-go. That file doesn't exist in production.
So, how can I compress that file like any other JS file in the pipeline, and then link directly to it?
If you add
config.assets.precompile += ['delivery.js']
to your application.rb, then delivery.js will be treated as a manifest file: it will be precompiled and served up as delivery.js in production. Manifest files are often just a series of //= require (or //= require_directory) statements, but any javascript they contain will also be added to the generated file.
By default the application.js manifest includes everything - you way want to tweak this so that it doesn't include javascript which is intended only to be served standalone.
First, make sure that your app/assets/javascripts/delivery.js is not among the includes of your top-level "manifest" javascript file, i.e. app/assets/javascripts/application.js. application.js usually includes //= require_tree ., so it includes your delivery.js by default. You need to change that. Replace "require_tree" with individual "require" statements for all your assets that you want to have precompiled and combined in the application.js.
Next, update your environment files (config/environments/production.rb for production env) to include your file in the list of precompiled assets:
config.assets.precompile += %w( delivery.js )
Now you'll have it as a separate file in your public/assets directory, compiled and compressed in the same way as application.js. Just keep in mind that it has a digest attached to it's name similarly to your application.js (unless, of course, you serve the files without digests by setting config.assets.digest = false).

Engine's assets with Rails 3.1

How should one provide assets in an engine in Rails 3.1? Where should they be located and can they be included automatically?
(originally asked by Tomas Celizna)
The paths to the all the engines' assets folders are automatically loaded.
The assets themselves are not loaded by default. This is understandable as the loading is done with require_tree ., which loads all css/js from the current folder (i.e. the main application assets' folder) but doesn't say anything about the engines assets.
The easy solution is to ask the user to require the js/css in application.js/css or wherever else it is needed. As the paths are loaded correctly, the user only need to specify the name of your asset (I'd recommend using the name of your engine). Example:
Appended to main_app/app/assets/javascripts/application.js:
//= require your_engine_name
If you have split your js in different files, your file your_engine_name/app/assets/javascripts/your_engine_name.js could have the following:
//= require_tree .
This will load all js files in your_engine_name/app/assets/javascripts/, as the "." refers to the local folder (in this case the folder of your engine's javascripts).
Note that ActionView::Helpers::AssetTagHelper.register_javascript_expansion appears not to have any effect when config.use_sprockets is set. I hope they'll at least put a warning in that case.
If you have a rake task to install your engine, then you could do the append to application.js.
Another way for the user to include it is to insert <%= javascript_include_tag "your_engine_name" %> in the erb layout.
I don't think there is a way to have it inserted automatically

Resources