Rails 3.1 Pipeline - Exclude JavaScript File

Rails 3.1 Pipeline - Exclude Javascript File

I chose to keep the sprockets functionality by changing

//= require_tree

to

//= require_directory .

This keeps sprockets auto-loading any files in the same directory, but not in any folders further.

This allowed me to move Modernizr.js to the assets/javascripts/top folder and manually load it at the top with:

<%= javascript_include_tag "top/modernizr" %>

and move

<%= javascript_include_tag "application" %>

To the bottom of my application.html.erb file (above the closing body tag)

Exclude *.spec.js files in Rails asset pipeline (application.js)

Please note: this answer is based on the defsprite's one, because it pointed me in the right direction, but reality turned out to be a bit harsher.

Place the following in config/initializers/sprockets.rb to register a new sprockets processor:

class DirectiveProcessor < Sprockets::DirectiveProcessor
def process_require_glob_directive(glob)
each_file(glob) { |fn| process_require_directive(fn) }
end

def process_stub_glob_directive(glob)
each_file(glob) { |fn| process_stub_directive(fn) }
end

private

def each_file(glob)
glob_pattern = "#{@dirname}/#{glob}"
path_prefix = Pathname.new(@dirname)

Dir[glob_pattern].sort.each do |path|
yield Pathname.new(path).relative_path_from(path_prefix).to_s
end
end
end

Rails.application.config.assets.configure do |env|
env.register_processor('application/javascript', DirectiveProcessor)
end

The most notable changes with respect to the original answer include converting absolute paths returned by Dir to relative ones (absolute paths are not accepted by sprockets) and different registration method (Rails.application.assets is nil in my case).

Then, within your application.js (before any require_tree statements) add:

//= stub_glob angular/**/*.spec.js

include a JS file outside the asset pipeline in rails 3.1?

You can put the file in the old pre-3.1 location /public/javascripts and link to it manually.

Exclude certain assets from pipeline in development environment?

I've looked through the source of the sprockets and I found,
that the directive preprocessor always runs before any engine.
So, it's not possible to add any conditional logic into the directives section with ERB or other engine.

  • https://github.com/sstephenson/sprockets/blob/master/lib/sprockets/environment.rb#L51
  • https://github.com/sstephenson/sprockets/blob/master/lib/sprockets/processing.rb#L36
  • https://github.com/sstephenson/sprockets/blob/master/lib/sprockets/context.rb#L174

UPDATE

Joshua Peek, answered on my question:

The answer is yes, but if this is what you are trying to do:

<% if Rails.env.production? %> 
//= require google_analytics_snippet
<% end %>

try this instead:

<% if Rails.env.production?
require_asset "google_analytics_snippet"
end %>

Using Rails 3.1, where do you put your page specific JavaScript code?

I appreciate all the answers... and I don't think they are really getting at the problem. Some of them are about styling and don't seem to relate... and others just mention javascript_include_tag... which I know exists (obviously...) but it would appear that the Rails 3.1 way going forward is to wrap up all of your Javascript into 1 file rather than loading individual Javascript at the bottom of each page.

The best solution I can come up with is to wrap certain features in div tags with ids or classes. In the javascript code. Then you just check if the id or class is on the page, and if it is, you run the javascript code that is associated with it. This way if the dynamic element is not on the page, the javascript code doesn't run - even though it's been included in the massive application.js file packaged by Sprockets.

My above solution has the benefit that if a search box is included on 8 of the 100 pages, it will run on only those 8 pages. You also won't have to include the same code on 8 of the pages on the site. In fact, you'll never have to include manual script tags on your site anywhere ever again - except to maybe preload data.

I think this is the actual answer to my question.

Rails - how to include Javascript files only on certain pages

You can put any Javascript files that you want to load manually in the public/javascripts/lib directory of your application, and they will not be included in the assets pipeline. You can then load them manually on the pages that need them.

For instance, in one project, I use the Chosen jQuery plugin, and I load it like so:

<script type="text/javascript" src="/javascripts/lib/chosen.jquery.min.js"></script>

Rails will source the public files from public/, so you only need to reference your files from there (remove the public/ bit).

This project is fairly large, with 88 controllers, 662 actions, and a total of 38 custom javascript libraries that get used sporadically around the app, including markdown editors, charting libraries, and even jQuery UI.

To manage the sprawl and to keep each page as tight as possible, I have done 2 things: 1) in my controller, I set an instance variable,@page_libs, to list the libs to load, and 2) the layout uses the values in @page_libs to include the specialty Javascript when required.

A controller action might look like this:

def edit
@products = products.find(params[:id])
@page_libs = [:ui, :textile]
end

And the app/views/layouts/application.html.erb includes this in the correct place:

<%- if @page_libs&.include?(:ui) || @page_libs&.include?(:table) %>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js"></script>
<script type="text/javascript" src="/javascripts/lib/chosen.jquery.min.js"></script>
<% end -%>
<%- if @page_libs&.include?(:swiper) %>
<script type="text/javascript" src="/javascripts/lib/idangerous.swiper.min.js"></script>
<% end -%>
<%- if @page_libs&.include?(:table) %>
<script type="text/javascript" src="/javascripts/lib/jquery.handsontable.full.js"></script>
<% end -%>
<%- if @page_libs&.include?(:textile) %>
<script type="text/javascript" src="/javascripts/lib/textile.js" charset="utf-8"></script>
<% end -%>

Note that the first include is for jQuery UI, which I load from a CDN, rather than from my app's public. This technique works just as well with external libraries, as well as those that you host. In fact, most pages in my app only depend on 2 external libraries (jQuery and Underscore.js), but have the option of loading up to 16 other Javascript libraries from external sources. Limiting external libraries on the page can significantly reduce your page load times, which is a direct performance boost for your application.

Sometimes, a Javascript library will include CSS components, as well. Or, you may even have page-specific CSS to include. The same approach can be taken with external stylesheet. These are the corresponding page-specific stylesheet "includes" for the above Javascript libraries:

<%- if @page_libs&.include?(:ui) %>
<link rel="stylesheet" type="text/css" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/themes/smoothness/jquery-ui.css">
<link rel="stylesheet" type="text/css" href="/stylesheets/lib/chosen.min.css">
<% end -%>
<%- if @page_libs&.include?(:swiper) %>
<link rel="stylesheet" type="text/css" href="/stylesheets/lib/idangerous.swiper.css">
<% end -%>

This way, I have a single point in the project to manage the libraries, regardless of how many (or few) are required for a page. I'll probably eventually create a series of custom before_action handlers in the ApplicationController to define which the libraries a page needs included. Something like this:

before_action: :include_library_ui,     only: [:new, :edit]
before_action: :include_library_swiper, only: [:show]

This would clean up the controller actions a bit more and make it easier to identify dependencies. However, given the size of my codebase and the pressing tasks remaining, I haven't taken this leap yet. Maybe it will inspire you to do so to start out.

rails 3.1 asset pipeline: ignore assets from a gem

I guess there is a smart way to achieve your goal using sprockets. Maybe some require_directory instead of require_tree.

But the most direct thing would be to remove theses assets from your assets paths. To achieve this, add this at the very end of your application.rb file (doesn't work in an initializer):

class Engine < Rails::Engine
initializer "remove assets directories from pipeline" do |app|
app.config.assets.paths = app.config.assets.paths - app.config.assets.paths.grep(/nice_regexp_here_to_match_the_dir_where_the_unwanted_files_live/)
end
end

Just tried a hack: put the code in an initializer but require it at the end of your application.rb:

require "config/initializers/your_file'

I prefer very specific code to be visible this way.



Related Topics



Leave a reply



Submit