How use rails 5.1+ without yarn and webpack? - ruby-on-rails

I update my rails app to pass at 5.1.X to day,
but surprise, my config to minify JS and CSS dosn't work anymore...
config.assets.js_compressor = Uglifier.new(output: {comments: /^!/})
** Invoke yarn:install (first_time)
** Execute yarn:install Yarn executable was not detected in the system. Download Yarn at https://yarnpkg.com/en/docs/install
** Execute assets:precompile rake aborted! Uglifier::Error: Invalid assignment
If I comment out the line, it works, but JS is not minified and there is inaccessible on site... like all others assets, but there are present in cache in /public folder... I don't understand why asset pipeline doesn't work now?!
So how can I stay with classic asset pipeline and disabled yarn call ?

I have been looking into this and as it is a very new issue, I would think about posting also an issue on Uglifier github page. I do not understand why Uglifier is causing problem to yarn as asset pipeline files are in app while yarn will keep them in node_modules.
I believe the issue here is that Uglifier already works on production files (in fact that is a production setting) and the asset pipeline will be working with yarn. You can require files in your application.js and .scss from the yarn node_modules folder, they will be included in your assets.
in this guide you can find out how rails requires the different components
active_record/railtie
action_controller/railtie
action_view/railtie
action_mailer/railtie
active_job/railtie
action_cable/engine
rails/test_unit/railtie
sprockets/railtie
I gave a very quick look at this, could not find anything relevant to yarn in railties/lib/rails/all.rb so I decided to search the rails repository for yarn keyword and find out this file
# Be sure to restart your server when you modify this file.
# Version of your assets, change this if you want to expire all your assets.
Rails.application.config.assets.version = '1.0'
# Add additional assets to the asset load path.
# Rails.application.config.assets.paths << Emoji.images_path
<%- unless options[:skip_yarn] -%>
# Add Yarn node_modules folder to the asset load path.
Rails.application.config.assets.paths << Rails.root.join('node_modules')
<%- end -%>
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in the app/assets
# folder are already added.
# Rails.application.config.assets.precompile += %w( admin.js admin.css )
so maybe you should search for this option\[:skip_yarn\]?
I wish you good luck
Fabrizio

Related

Ruby on Rails 4.2 Asset pipeline not minifying/compressing the application-fingerprinted.js JS file

I have a ruby on Rails 4.2 app and am facing a "hair-tearing" issue for long 2 days about my asset pipeline. My prod is hosted on Heroku and I directly mention this here as I think it might be relevant I have them gem 'rails_12factor', group: :production
I read and tried the suggestions of the (too) numerous SO questions about Rails assets not compiling but none worked as I'll describe further down.
The issue observed which led me to this SO question is that my my javascript application.js file was NOT minified in production.
How do I know? the white spaces are still here, the comments have not been removed, well the applciation.js, contrary to my application.css, is just a concatenatation of all js files but NO compressing/minifying has been done.
Most questions on SO deal with issues where neither images, css or js is minified/precompilied but my situation is peculiar to the extent that images, css are precompiled/minified, but only js is a problem and is not minified.
Is there a problem with my js? (see below for some experiments I tried to find out the reason of the bug) Seems not
My set up below will show you how I deal with assets (to the extent of my beginner understanding) : I use guard to constantly monitor any change and precompile stuff and put the resulting/generated application-tr56d7.css (fingerprinted) and application-45dsugdsy67.js ((fingerprinted) inside public/assets and then when I deploy on git, it pushes all changes , including the precompiled/minified files and then when I push to Heroku, my production asset settings say to Rails to deploy my already precompiled assets. I'm a beginner and struggled with understanding all the numerous dev/prod environment assets settings but I think that is what is defined in the code you'll find further down.
I know all this process it's working because everytime i change a file when I can find a new application-tr56d7.css and a new application-45dsugdsy67.js(examples of course) (along with a new css.gz and.js.z which must be the binary stuff)
Every time I change a js file for example, guard make his job and I can read something like:
I, [2018-02-09T09:53:41.140165 #130534] INFO -- : Writing /home/mathieu/rails_projects/my_app/public/assets/application-af0ab4a348e4f5545c844cfac02a0670.js
The new generated application.css and application.js files can then be found in public/assets folder: for example
/public/assets/application-1021e7d2ea120fe40c67ec288f1c6525.js
/public/assets/application-1021e7d2ea120fe40c67ec288f1c6525.js.gz (binary: just a list of numbers...)
/public/assets/application-753e1d0958f76ae233a460ad47606790.css
/public/assets/application-753e1d0958f76ae233a460ad47606790.css.gz (binary: just a list of numbers...)
So when I observed that in production the css was application-753e1d0958f76ae233a460ad47606790.css minified but not the application-1021e7d2ea120fe40c67ec288f1c6525.js js, I went to see on
public/assets and here too I noticed the same thing:
the css files generated by guard such as /public/assets/application-753e1d0958f76ae233a460ad47606790.css css are minified
but the js files genrated by gyard are NOT minified
So I think that, but I'm not sure, it's not a Heorku specific problem, it's just that even before pushing it to Heroku, my js file hosted on public/assets should be but is not minified.
What i tried to debug this (spoiling the suspenese:all failed):
tried to say explicitly in assets.rb to compile application.js not work => Result: js still not minified locally and not on production website on heroku
# It is recommended to make explicit list of assets in config/application.rb
config.assets.precompile = ['application.js']
tried cleaning all old stuff by rake :assets clobber => Result: js still not minified locally and not on production website on heroku
tried cleaning old stuff by changing version
assets.rb: changed => Result: js still not minified locally and not on production website on heroku
config.assets.version = '1.0'
into
config.assets.version = '1.1'
tried to change all the various dev and prod asset settings => Result: js still not minified locally and not on production website on heroku
config.serve_static_assets = true and tried false
tried also so many different settings for both files but none worked.
tried to compile in local and in prod => Result: js still not minified locally and not on production website on heroku
rake assets:precompile RAILS_ENV=production --trace
Also tried local:
rake assets:precompile
2 weirdest attempt:
after all my attempts at making this work by modifying the asset pipeline settings which all failed, I thought maybe there 's a tricky javascript error somewhere breaking silently the minification/compressing made by guard (which also be silent in terms of page load as no error appear on chrome dev tools when i load my pages but who knows...read on some SO questions some strange effect of comments on the asset pipeline)', so
I decided to comment ALL my js files inside assets/javascripts/! nothing left: and even removed the js that ends up in the pipeline but injected by a gem (so not visible in my folder app/assets/javascripts) such as jquery gem: and create 2 very basic js files
that would be the only remaining files...
well still : => Result: js still not minified locally and not on production website on heroku
Did again the same test as above but here went even further: I emptied (deleted all the content) of all the js files inside my assets/javascripts and removed form application.js all the gems to only leave require directory , and then created 2 very simple js files to check if it was minified now....
and still same result: js still not minified locally and not on production website on heroku
A test that kind of worked
doing rake assets:clobber then the push (git add, git commit, git push, git push heroku paster) DOES compile the js BUT unfortunately it creates other issues: it sends to the production an OLD version of the js (I know because i put a alert message inside the js and it's not the latest one!). What does it reveal about the bug that rake assets:clobber kind of debug it?
EDIT
I made it work but with quite a demanding process:
leveraging some people saying there is no compilation if you don't change css or js (see https://stackoverflow.com/a/7988689/1467802), I tweaked the previous process: (change sth in the js file, rake assets:clobber, git add, git commit, git push, git heroku master) and it works: it cpmpiles and sends the latest js file!
Isn't there any way not to have to remeber eveyr time to change sth inside the js to ensure compilation ?
I'm out of ideas. Maybe my settings are just wrong and as a beginner, I'm missing something obvious.
The weirdest poart is: my cs is minified! why not the js????
My codebase
/config/environments/development.rb
MyApp::Application.configure do
# Do not compress assets
config.assets.compress = false
# Expands the lines which load the assets
config.assets.debug = true
config.serve_static_files = false
end
/config/environments/production.rb
MyApp::Application.configure do
# Disable Rails's static asset server (Apache or nginx will already do this)
config.serve_static_files = false
# Compress JavaScripts and CSS
# config.assets.compress = true removed when switch from Rails 3.2 to Rails 4
config.assets.js_compressor = :uglifier
config.assets.js_compressor = Uglifier.new(
# Remove all console.* functions
:compress => { :drop_console => true }
) if defined? Uglifier
config.assets.css_compressor = :sass
# Don't fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = false
# Generate digests for assets URLs
config.assets.digest = true
config.force_ssl = true
end
/config/initializers/assets.rb
Rails.application.configure do
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
# related to deployment pb with active admin
config.assets.precompile += %w[admin/active_admin.css admin/active_admin.js]
# for ckeditor: github.com/galetahub/ckeditor
config.assets.precompile += %w( ckeditor/* )
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
end
/config/application.rb
require File.expand_path('../boot', __FILE__)
require "active_record/railtie"
require "action_controller/railtie"
require "action_mailer/railtie"
require "active_resource/railtie"
require "sprockets/railtie"
if defined?(Bundler)
# If you precompile assets before deploying to production, use this line
Bundler.require(*Rails.groups(:assets => %w(development test)))
end
module MyApp
class Application < Rails::Application
config.autoload_paths += %W(#{config.root}/lib)
# Enable the asset pipeline
config.assets.enabled = true
end
end
/Guardfile
# More info at https://github.com/guard/guard#readme
require 'active_support' # edded this due to a bug where guard did not load github.com/rails/rails/issues/14664
require 'active_support/core_ext'
require 'active_support/inflector'
# Make sure this guard is ABOVE any other guards using assets such as jasmine-headless-webkit
# It is recommended to make explicit list of assets in `config/application.rb`
# config.assets.precompile = ['application.js', 'application.css', 'all-ie.css']
# update dec 2014- added :runner => :cli because of a know bug on guard rail assets
# if bug is solved i can remove the part :runner=> cli
guard 'rails-assets', :run_on => [:start, :change], :runner => :cli do
watch(%r{^app/assets/.+$})
watch('config/application.rb')
end
assets/javascripts/application.js
//= require jquery
//= require jquery.turbolinks
//= require jquery_ujs
//= require jquery.cookie
//= require cloudinary-jquery.min
//= require twitter/bootstrap
//= require paloma
//= require html5shiv-printshiv
//= require storageService
//= require turbolinks
//= require_directory .
Terminal process when deploying after, for example chagning some js files and waiting guard has notified me it has finished its precompilaiton job:
git add --all
git commit -a -m "fix issue with asset pipeline"
git push
git push heroku master
I know what I am going to say is not conventional, but your aproach hasn't been so explicit, you should try adding the explicit compress call you have made false in development
/config/environments/production.rb
MyApp::Application.configure do
# Compress assets please
config.assets.compress = true
# ... other stuff
end
After that clean your assets and regenerate them with
$ bundle exec rake assets:clobber
$ RAILS_ENV=production bundle exec rake assets:precompile
If I understand this correctly, you can replicate this issue locally, so the Heroku factor is irrelevant.
However, it sounds like you are compiling the assets locally, committing them to repository, then pushing to Heroku. First of all, I'd avoid this and lean on letting Heroku do the static asset compilation during deploy.
Regardless, if I understand correctly that this is what you are doing, I think it may because when you run rake assets:precompile, you may be compiling them in dev mode, which will use your config/development.rb configuration, which has config.assets.compress = false. I'm not sure why some of your files are compressed while others aren't, other than it may simply be related to how recently you've modified the source files.
In any case, try running:
$ rake assets:clean
$ rake assets:precompile RAILS_ENV=production
I suspect you will have issues booting the app in production mode locally (e.g. if you don't have database credentials configured appropriately or something), which is another reason why I would not precompile assets locally prior to deploy. However, this may prove or disprove if the active environment is a factor in your issues.
In fact, you could try running this on the Heroku dyno instead, which will be setup for production already:
(local)$ heroku run bash
(heroku)$ rake assets:clean assets:precompile RAILS_ENV=production
(heroku)$ less public/assets/application-*.js # see if this is compressed
Let me know what you discover here and I can revise my answer if that doesn't change the equation for you

Rails asset precompilation happening even if there is no change in assets

I am running a rails stack on AWS Opsworks. In before_symlink.rb deploy hook, I have the following code.
rails_env = new_resource.environment["RAILS_ENV"]
shared_path = "#{new_resource.deploy_to}/shared"
# create shared directory for assets, if it doesn't exist
directory "#{shared_path}/assets" do
mode 0770
action :create
recursive true
not_if do
Dir.exists?("#{shared_path}/assets")
end
end
# symlink current deploy's asset folder to shared assets each deploy
link "#{release_path}/public/assets" do
to "#{shared_path}/assets"
end
# precompile assets into public/assets (which is symlinked to shared assets folder)
execute "rake assets:precompile" do
cwd release_path
command "bundle exec rake assets:precompile --trace"
environment 'RAILS_ENV' => rails_env
end
The problem is that assets are precompiled all the time even if there is no change, inspite of being in a symlinked shared folder. I am running on Rails 4.1.2 and I guess Rails is intelligent enough to compile only changed assets after Rails 4? Why is this happening?
UPDATE
This is now solved.
I missed out symlinking /tmp/cache to /shared/tmp/cache. This is where sprockets stores cached files.
Updated code.
# Precompile assets. Assets are compiled into shared/assets and shared between deploys.
rails_env = new_resource.environment["RAILS_ENV"]
shared_path = "#{new_resource.deploy_to}/shared"
# create shared directory for assets, if it doesn't exist
directory "#{shared_path}/assets" do
mode 0770
action :create
recursive true
not_if do
Dir.exists?("#{shared_path}/assets")
end
end
#create shared directory to store sprockets cache
directory "#{shared_path}/tmp/cache" do
mode 0770
action :create
recursive true
not_if do
Dir.exists?("#{shared_path}/tmp/cache")
end
end
# symlink current deploy's asset folder to shared assets each deploy
link "#{release_path}/public/assets" do
to "#{shared_path}/assets"
end
# symlink current deploy's sprockets cache folder to shared cache folder on each deploy
link "#{release_path}/tmp/cache" do
to "#{shared_path}/tmp/cache"
end
# precompile assets into public/assets (which is symlinked to shared assets folder)
execute "rake assets:precompile" do
cwd release_path
command "bundle exec rake assets:precompile --trace"
environment 'RAILS_ENV' => rails_env
end
OpsWorks rebuilds your entire rails app upon each deployment and keeps a number of backup copies. It should create it in a path like:
/srv/www/yourappname/current
You can confirm this by ssh into your server. If you go to path
ls -la /srv/www/yourappname/releases
You should see a number of folder with datetime stamps names.
If you look at contents they will each contain your entire rails app.
This makes it easy to roll back if something goes wrong during deployment.
Since each folder is basically a new install of your app, asset pre-compilation needs to happen otherwise the current version won't have any assets. This type of deployment doesn't just have the same directory do a
git pull origin master
UPDATE: It looks like this was an issue with Sprockets that was resolved in this pull request so make sure your gem sprockets version includes this commit. It looks like it was included in v4.0.0beta1 & v4.0.0beta2 so try that or if not, try downgrade to >=2.12.4 as per this comment

rails asset pipeline production precompile

I have a directory projName/vendor/assets/bootstrap/css/
I am in production mode.
production.rb contains: config.assets.precompile << /(^[^_\/]|\/[^_])[^\/]*$/
when I run rake assets:precompile
I get
projName/public/assets/css/ but I want projName/public/assets/bootstrap/css/
I do not understand why the bootstrap directory is not there.
Actually all the top level directories under vendor/assets and app/assets are missing in public assets/
Compiled assets are written to the location specified in config.assets.prefix. By default, this is the public/assets directory.
To understand this you have to first understand what precompiling is and does. Let me explain
When you run (a rake task)
rake assets:precompile
it will create a public folder inside your application folder which will compile all your asset manifests (ie. your application.css and application.js)
How exactly does this happen ?? -> Rails comes bundled with a rake task which will compile all this. That rake task is what is shown above.
Compiled assets are written to the location specified in config.assets.prefix. By default, this is the public/assets directory.
The default matcher for compiling files includes application.js, application.css and all non-JS/CSS files (this will include all image assets automatically) from app/assets folders including your gems.
And thats exactly what that regex means (to include everything in your app/assets folder), you can also explicitly provide it as shown in the answer above.
Hope this helped.
Here are few links for your reference
http://guides.rubyonrails.org/asset_pipeline.html#precompiling-assets
http://dennisreimann.de/blog/precompiling-rails-assets-for-development/
What does that regex mean? If you want to precompile everything, try this.
config.assets.precompile = ['*.js', '*.css']
Actually, if you want to precompile everything, try this:
def precompile?(path)
%w(app lib vendor).each do |asset_root|
assets_path = Rails.root.join(asset_root, 'assets').to_path
return true if path.starts_with?(assets_path)
end
false
end
# Precompile all assets under app/assets (unless they start with _)
Rails.application.config.assets.precompile << proc do |name, path|
starts_with_underscore = name.split('/').last.starts_with?('_')
unless starts_with_underscore
path = Rails.application.assets.resolve(name).to_path unless path # Rails 4 passes path; Rails 3 doesn't
precompile?(path)
end
end
(Based on the code in the Rails Guide.)

Precompiling a .css file

I have a board controller and I have made a board.css file for it.
When I push to heroku I'm getting an error saying board.css is not precompiled. Based on this question I have added
config.assets.precompile += %w( *.css *.js )
to my production.rb file.
This still has not fixed it. What am I missing here?
Open up config/environments/production.rb and make sure the following option is set to true:
# Don't fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = true
Then run:
rake assets:precompile --trace RAILS_ENV=production
Source
Do you have an assets manifest in your /assets folder?
Default manifest file are /assets/application.js and /assets/application.css.
A manifest file describes all the resources will be precompiled and looks like this:
/*
* This is a manifest file that'll automatically include all the stylesheets available in this directory
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
* the top of the compiled file, but it's generally better to create a new file per style scope.
*= require_self
*= require_tree ./dir
*= require_tree .
*/
This CSS manifest precompiles itself, all css files in assets/dir and /assets folders.
So make sure you have a manifest file and it requires board.css with a matching path.
When you set config.assets.precompile += %w( *.css *.js )
in production.rb you are telling Rails that all files in /assets folder are manifest file.
IMHO this is not correct and you have to add only custom manifest files.
Default manifests are already included:
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
About others solutions there's something to say. If you set:
# Don't fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = true
It means that you are not forced to have precompiled assets.
The trick works because your app will not raise an error, but you still get an app without precompiled assets and you'll pay this in page load time. For this reason this option should always be disabled in production environment.
So when you enable it, calling rake assets:precompile will not guarantee you are going to use a precompiled assets.
Finally remember that Heroku always run rake assets:precompile when you deploy your app, so unless you are running your app locally with production environment you don't need to manually precompile your assets.

Rails asset pipeline - JS and CoffeeScript

I have both .js and .coffee files in my /app/assets/javascripts/ folder. The .coffee files will not run unless I call rake assets:precompile, which is a pain because I have to do rake assets:clean and precompile them again whenever I make a change.
Also, the precompiled .js file is included in addition to the source files, which causes double event handlers and all that good stuff.
My understanding is that the coffeescript should be compiled to javascript upon each request if it's not precompiled, but it doesn't seem to be doing so. I can't find the compiled script loading in Firebug, and I don't see its behavior, at least.
My /config/application.rb has the following line configured:
# Enable the asset pipeline
config.assets.enabled = true
What else is there to check?
I am using Rails 3.2.3.
If you precompile on your local machine, then you can commit these generated assets into the repository and proceed with deployment. No need to compile them on production machine.
But it introduces a problem: now when you change source files (coffescript / scss), the app won't pick up the changes, because it will serve precompiled files instead. rake assets:clean deletes these precompiled files.
from https://stackoverflow.com/a/9335864/643500
What I usually do if I want the assets to precompile on the production server to pickup the new changes every build is just clean the assets - once of course unless you re-precompile them
rake assets:clean
When the changes are made and you don't want to precompile them every build do
rake assets:clean
rake assets:precompile

Resources