Rails webpacker.yml, extract_css option - ruby-on-rails

According to rails/webpacker documentation, extract_css is default to true in production environment and false in development. From what I observed:
With extract_css true, webpacker will emit a css file from each stylesheet_pack_tag in application.html.erb.
And, with extract_css false, stylesheet_pack_tag return nil & stylesheet that gets imported in js files will get extracted and bundle into blobs and send to browser. Hence, link tags to blob url exist.
So, I assume that using extract_css true yield the same result as using inline styles in header since styles get downloaded to browser with the website document file. If what I understand is true then setting extract_css to true on production should be ok.
Is what I understand about extract_css option correct?

You mostly correct, you can read more about extract_css in css.md or v4-upgrade.md
With extract_css: true, webpacker will emit a single css <link rel="stylesheet"... from each stylesheet_pack_tag.
With extract_css: false, stylesheet_pack_tag return nil & stylesheet that gets imported in js files will get extracted and bundle into blobs and injected into as an inline .
In the end extract_css: false is the one that yields the same result as using inline styles.

I don't have anything to add other than "extract_css" in webpacker.yml has been a source of confusion for me as well. When it is "extract_css: false" in development and production, a stylesheet IS included in the document head (shouldn't this be "extract_css: true"?). And when I use "extract_css: true", styles are not included in the document.

Related

Can't access images and fonts on production Rails

I access some static images (favicon, etc) through /assets/image.jpg.
It works as expected on localhost but when I push in production, I can't access fonts and images.
Css and js are compiled and working fine.
I've added this to my production.rb file but it still doesn't work :
config.serve_static_files = true
config.serve_static_assets = true
config.assets.compile = true
What do I have to write to access them and where ?
Ok, I figured, it was dumb :
In production we have to use rails link helpers to provide assets, for example, you can't access favicon with :
<link rel="shortcut icon" type="image/gif" href="/assets/images/favicon.gif"/>
we have to use
<%= favicon_link_tag 'favicon.gif' %>
because a sha is generated and produces the following link for example
/assets/favicon-02168c53f101e2059920863c64a71d6abc53b4fbec334f2e0b002f7866e63b69.gif

Rails: don't uglify HTML and CSS in test environment (using SLIM and Sass/Compass)?

I'm actively validating the HTML and CSS in request specs. Sadly, the error messages are very long because the HTML and CSS is uglified/compressed in test env.
I tried to remove the uglifier gem from the Gemfile, but this didn't work out. Do I miss some configuration option here? I can't find any for test.rb...
Update
I found that setting Slim::Engine.set_default_options pretty: true solved the problem for the HTML output.
The CSS is still compressed on one line though, I tried stuff like adding output_style = :nested to config/compass.css, setting Sass::Plugin.options[:style] = :expanded (raised an exception), add config.sass.output_style = :nested to test.rb, and setting # config.assets.css_compressor = nil also in test.rb. Didn't solve my problem.
Try setting this in test.rb:
config.assets.debug = true
In case you're using SLIM templating engine, set pretty: true:
Slim::Engine.set_default_options pretty: true
For more info see https://github.com/slim-template/slim#default-options.

Should Rails uglifier uglify (mangle) function names?

My .js files are compressed and variables mangled, but function names are not mangled (running latest Rails 3.2.8 and latest uglify 1.3.0 gem) on Heroku.
According to https://github.com/lautis/uglifier#usage the "mangle" option defaults to true. Below is my config.
From production.rb:
config.assets.compress = true
config.assets.js_compressor = :uglifier
I've also tried
config.assets.compress = true
config.assets.js_compressor = Uglifier.new(:mangle => true, :toplevel => true, :copyright => true)
but with no noticable difference.
As one commenter suggested, I did try changing contents of one my .js files, but didn't make a difference.
Example from output of the compressed precompiled .js file on Heroku:
show_slideout_notification=function(){jQuery(".slideout_notification").slideDown();var e=$(".slideout_notification .countdown
Seems that variable names are mangled, but function names are not.
Any ideas why function names are not mangled? Or is this not wanted behaviour as it would then be difficult to call the functions from my Rails/js code (i.e. javascript onclick events). Or would those onclick calls be renamed to the mangled name too if the function names were mangled?
Thanks :-)
Have you tried to modify the file? According to this the generation of asset files are based on file modification time. Maybe your settings not even being used.
Shouldn't it be like this?
config.assets.js_compressor = Uglifier.new(:mangle => { :toplevel => true }, :output => { :comments => :copyright })

Rails + SASS . How to list all imported files

I would like to stop importing my Sass files with Sprocket and using the #import function of Sass.
It works fine but the files are not imported one by one in developement mode so the debuging is harder.
Is there a way to import all files separately with Sass in developement mode?
You can enable asset debugging in Sprockets by adding the setting to your development.rb:
# Expands the lines which load the assets
config.assets.debug = true
When debug is true, compiled CSS files contain line numbers that tell you where to find the uncompiled CSS:
/* line 5, ../../../app/assets/stylesheets/_colors.scss */
.color-facebook-blue {
color: #3B5998;
}

Conditional javascript require in the asset pipeline

I'm struggling with the asset pipeline. I'm loading dojo from Google CDN putting this in my template:
= javascript_include_tag 'http://ajax.googleapis.com/ajax/libs/dojo/1.6.1/dojo/dojo.xd.js', :'data-dojo-config' => %Q(dojoBlankHtmlUrl:'/blank.html', baseUrl: 'assets/', modulePaths: {custom: 'javascripts/modules'})
I just want a fallback to a local version if running locally or if the CDN is down. I thought of doing this:
script typeof(dojo) === "undefined" && document.write(unescape('%3Cscript src="js/libs/dojo-1.6.1.min.js"%3E%3C/script%3E'));
But I don't like it as it works out of the asset pipeline. I want to keep dojo in vendors/assets/javascripts/dojo. How can I get the fallback to be served by the asset pipeline.
Is there a way do declare conditional require in the asset pipeline. What I want is to run some javascript tests, and depending on the result serve a file.
Thanks
I suggest you use yepnope, a lightweight library for loading libraries like this in parallel (for speed) and it gives you the option to run some other code to test if the library is loaded. For example:
yepnope([{
load: 'http://ajax.googleapis.com/ajax/libs/dojo/1.6.1/dojo/dojo.xd.js',
complete: function () {
if (!window.jQuery) {
yepnope('asset_path('you_local_copy_of_dojo') ');
}
}
}])
(Note: You will need erb tags around the asset_path helper)
The local dojo file would be in the assets/javascript folder, but not included in the application manifest. You need to add the dojo file to the precompile array:
config.assets.precompile += 'your_local_file.js'
And this will make it available to the asset_path helper.
Thanks Richard!
I don't want to have yepnope to load one library. It would be overkill imo. Here is the solution I came up with, based on your help (written in slim):
1/ In vendors/assets/javascripts/, I have my dojo.js.
2/ In config/application.rb:
# Precompile these assets files
config.assets.precompile += ['dojo.js']
3/ In the template:
= javascript_include_tag "http://ajax.googleapis.com/ajax/libs/dojo/#{Settings.dojoVersion}/dojo/dojo.xd.js", :'data-dojo-config' => %Q(dojoBlankHtmlUrl:'/blank.html', baseUrl: 'assets/', modulePaths: {custom: 'javascripts/modules'})
script = "typeof(dojo) === \"undefined\" && document.write(unescape('%3Cscript src=\"#{asset_path('dojo')}\"%3E%3C/script%3E'));".html_safe
I also posted on the Rails Google Group to request the addition of two options to the javascript_include_tag, :test and :local that would take care of all the work. We'll see.

Resources