Precompile rails AngularJS assets - ruby-on-rails

I am trying to compile my Rails app assets using RAILS_ENV=production bundle exec rake assets:precompile, but this doesn't compile my AngularJS assets, so my console report this:
ActionController::RoutingError (No route matches [GET] "/assets/app/views/products/index.html"):
My AngularJS assets are under "/assets/app/", so I tried to compile the angular folders by adding following into my production.rb but still not working.
config.assets.precompile += %w(app/* bootstrap/* datatable/* ....
I can find the compiled index file under this path:
public/assets/app/views/products/index-2429bd0f8fc0762dcc075e51f0306c5b.html
Any idea?
UPDATE
Also tried config.serve_static_assets = false in production, but it cause more missing assets errors
Thanks

I've worked through this in my app by using constants to get the path structure right.
my angular app is journey (yours would obviously be different)
so I declare the angular app as a module
this.journey = angular.module('journey', [
'ngResource',
'ngRoute'
]);
Then I have a file called constants.js.erb where I declare my templates
journey.constant('INDEX_TEMPLATE', '<%= asset_path('journeys/journey_index.html')%>');
journey.constant('EDIT_JOURNEY_TEMPLATE', '<%= asset_path('journeys/journey_edit.html') %>');
Finally in my services I use the constants declared as the template url
journey.config([
'$routeProvider',
'$locationProvider',
'INDEX_TEMPLATE',
'EDIT_JOURNEY_TEMPLATE',
function ($routeProvider, $locationProvider, INDEX_TEMPLATE, EDIT_JOURNEY_TEMPLATE) {
$locationProvider.html5Mode(false);
return $routeProvider.when('/', {
templateUrl: INDEX_TEMPLATE,
controller: 'JourneyIndexController'
})
}
])
This way I don't have to worry about where the files are or how rails is organising the routing.
Hope this helps

Related

Image Asset Not Loading In Production

I'm running Rails 5.2.2. I recently separated some admin code from my frontend and in the process moved my controllers, views, css & JS to folders in either frontend or admin respectively.
In development, everything works fine. In production, I am unable to load image assets from my css.scss files using the following line background: url(arrow.png) no-repeat left center; (located in app/assets/stylesheets/frontend/application.css.scss).
My assets has the following file structure:
assets/
config/
images/
admin/
frontend/
products/
another_folder/
javascripts/
admin/
frontend/
stylesheets/
admin/
frontend/
I did not have to change any of my image tags in my views once I made these changes for my images in assets/images/products so I figured that I wouldn't have to do that anywhere else either; things just seemed to work. However, in production the arrow.png returns a 404. When I inspect the image request, the link to the image is /assets/frontend/arrow.png. I use the RAILS_ENV=production flag when compiling assets. I have also run rake assets:clobber with the production flag then tried compiling the assets again. I've deleted all browsing data.
Here are my server logs where the image is requested:
I, [2019-08-01T05:06:22.496953 #6733] INFO -- : [8a0b82c0-c4a3-419f-92fd-8f4a89bbe643] Started GET "/assets/frontend/arrow.png" for 35.188.197.210 at 2019-08-01 05:06:22 +0000
F, [2019-08-01T05:06:22.501395 #6733] FATAL -- : [8a0b82c0-c4a3-419f-92fd-8f4a89bbe643]
F, [2019-08-01T05:06:22.503739 #6733] FATAL -- : [8a0b82c0-c4a3-419f-92fd-8f4a89bbe643] ActionController::RoutingError (No route matches [GET] "/assets/frontend/arrow.png"):
UPDATE:
Adding this to a view works fine in production so I can confirm the asset does indeed compile properly.
<%= image_tag("frontend/arrow.png") %>
For Rails 5, please try to change following configuration:
config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present?
to
config.public_file_server.enabled = true
OR
you can set RAILS_SERVE_STATIC_FILES true in your passenger_env_var. That will also work.
Helo is this code works for you?
background: image-url(arrow.png) no-repeat left center;

What is the best way to use webpacker in a Rails engine?

I realise there is some debate about using webpacker in Rails engines but I have a simple usecase and currently have a workaround. Would like to know of a better (the best?) solution.
In this rails engine I have webpacker setup in the "spec/dummy" directory and everything works well in dev:
https://github.com/RealEstateWebTools/property_web_scraper/tree/master/spec/dummy/config/webpack
When the engine is used by a rails app however it will not find the compiled webpack files so each time I have a release ready I compile the webpack files and manually copy them to the vendor directory:
https://github.com/RealEstateWebTools/property_web_scraper/tree/master/vendor/assets/javascripts
I then require that file here:
https://github.com/RealEstateWebTools/property_web_scraper/blob/master/app/assets/javascripts/property_web_scraper/spp_vuetify.js
In my layout I use the above file using the good old sprockets "javascript_include_tag": https://github.com/RealEstateWebTools/property_web_scraper/blob/master/app/views/layouts/property_web_scraper/spp_vuetify.html.erb
In the layout there is a check to see if I'm running the "spec/dummy" app in which case I will user webpacker as it would normally be used in dev.
There must be a better way than this.
Webpacker has been retired
https://github.com/rails/webpacker
Going forward, it's better to switch to jsbundling-rails with webpack.
(I would rather suggest esbuild as it's "10×-100× faster")
But let's do it with webpack:
rails new webpack-in-engine --javascript webpack --css tailwind --database postgresql
In app/javascript/application.js I do:
console.log("hello from application.js")
And it works.
Now with an engine:
rails plugin new admin --mountable
Then depends:
Separate JS
Add an entry to your webpack.config.js:
const path = require("path")
const webpack = require("webpack")
module.exports = {
mode: "production",
devtool: "source-map",
entry: {
application: "./app/javascript/application.js",
admin: "./admin/app/javascript/admin.js"
},
output: {
filename: "[name].js",
sourceMapFilename: "[name].js.map",
path: path.resolve(__dirname, "app/assets/builds"),
},
plugins: [
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1
})
]
}
<%= javascript_include_tag "admin", "data-turbo-track": "reload", defer: true %>
Shared JS
<%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
And in your app/javascript/application.js:
import "./../../admin/app/javascript/admin"
See full repo https://github.com/dorianmariefr/webpack-in-engine
Aside: Also I would rather namespace in the main app than have engines. I think engines are for very specific use cases not namespacing.

Sass import from rails engine not working

I've created a Rails Engine for assets. I don't use sprockets for css. Instead, I rely on sass's #import. This works perfectly fine in the test/dummy app, but in the Rails app that is requiring the engine, it keeps throwing
Sass::SyntaxError: File to import not found or unreadable: gumby.
I've been at this for a while, and originally the path wasn't in the load path for sass. But then I added
config.sass.load_paths << "#{Gem.loaded_specs['gumby_on_rails'].full_gem_path}/app/assets/stylesheets"
to my config/application.rb and now it definitely shows the correct path to the file I'm trying to import. It is the second to the last path listed in the following trace:
Sass::SyntaxError: File to import not found or unreadable: gumby.
Load paths:
CompassRails::SpriteImporter
CompassRails::SpriteImporter
CompassRails::SpriteImporter
CompassRails::SpriteImporter
CompassRails::SpriteImporter
CompassRails::SpriteImporter
CompassRails::SpriteImporter
CompassRails::SpriteImporter
CompassRails::SpriteImporter
/Users/brandon/code/personal/blog_update/app/assets/images
/Users/brandon/code/personal/blog_update/app/assets/javascripts
/Users/brandon/code/personal/blog_update/app/assets/stylesheets
/Users/brandon/code/personal/blog_update/vendor/assets/javascripts
/Users/brandon/code/personal/blog_update/vendor/assets/stylesheets
/Users/brandon/.rvm/gems/jruby-1.7.11#blog/gems/angularjs-rails-1.0.7/vendor/assets/javascripts
/Users/brandon/.rvm/gems/jruby-1.7.11#blog/gems/turbolinks-2.2.2/lib/assets/javascripts
/Users/brandon/.rvm/gems/jruby-1.7.11#blog/gems/jquery-rails-3.1.0/vendor/assets/javascripts
/Users/brandon/.rvm/gems/jruby-1.7.11#blog/gems/coffee-rails-4.0.1/lib/assets/javascripts
/Users/brandon/code/personal/gumby/app/assets/stylesheets
/Users/brandon/code/personal/blog_update/app/assets/stylesheets
The rails engine's tree looks like this
app/
assets/
stylesheets/
gumby/
...
gumby.css.scss
(I know that technically you should namespace all your assets in an engine, but I didn't want to have gumby/gumby, and I feel the chances of a name clash are slim.)
So in the test/dummy app I can import this file via #import 'gumby';, but this fails in the Rails app. With the above exception. How do I get this working?
And by the way, this is a Rails 4.1 app, and the answers to several other "similar" questions are all due to using groups in the Gemfile. Rails 4 got rid of groups so this is not the problem/solution.
So the solution for me was to suck it up and namespace it gumby/gumby. Then I also had to change the config/application.rb to:
config.assets.paths << "#{Gem.loaded_specs['gumby_on_rails'].full_gem_path}/app/assets/stylesheets"
And for some reason modular-scale wasn't being required properly, even though the engine already required it. So I had to change application.css.scss to application.css.scss.erb and put <% require 'modular-scale' %> at the top.
then you should write it like this :
config.sass.load_paths << "#{Gem.loaded_specs['gumby_on_rails'].full_gem_path}/app/assets/stylesheets/gumby"
or try this (untested)
#import_tree 'gumby';

javascript_include_tag Rails 4 generating "/javascripts/" instead of "/assets" in production

I have a Rails 4 application with
<%= javascript_include_tag "modernizr", "data-turbolinks-track" => true %>
in the head. In development, the following HTML is rendered, and modernizr is loaded:
<script data-turbolinks-track="true" src="/assets/modernizr.js?body=1"></script>
In production, the followign HTML is rendered, and modernizr is not loaded (404 not found):
<script data-turbolinks-track="true" src="/javascripts/modernizr.js"></script>
In production, /assets/modernizr.js is found and browsable.
The Rails documentation says that the javascript_include_tag should generate
<script data-turbolinks-track="true" src="/assets/modernizr.js?body=1"></script>
In production, my stylesheet_link_tags are fine, linking to the /assets/ directory.
Why is the javascript_include_tag linking to /javascripts instead of /assets in production, and how can I fix it?
One of the usage statements for AssetUrlHelper indicates it will produce /javascripts/ urls
like what you are seeing:
# asset_path "application", type: :javascript # => /javascripts/application.js
(from asset_url_helper.rb line 117 - [1])
This code looks like it can only be reached if the precompiled asset is missing
so it would appear that your asset compilation is not working (my deployments usually
fail when that happens, so maybe yours isn't even firing).
The same asset_url_helper.rb calls the /javascripts/ part 'extname' and
uses the following map to know how to generate the name:
# Maps asset types to public directory.
ASSET_PUBLIC_DIRECTORIES = {
audio: '/audios',
font: '/fonts',
image: '/images',
javascript: '/javascripts',
stylesheet: '/stylesheets',
video: '/videos'
}
A new Rails 4 app has this in the config/environments/production.rb
# Do not fallback to assets pipeline if a precompiled asset is missed.
config.assets.compile = false
which seems to match the behavior you are seeing.
By default, Rails only precompiles application.js, application.css and any images it finds in the assets path. Therefore, in production mordernizr will not get precompiled and thus the javascript helpers will not be able to find the file.
In order to fix the issue, you can add modernizr to the precompile list by modifying the following config in production.rb
config.assets.precompile += ['modernizr.js']
For more information see the Rails Guides
Be sure to precompile your assets in production by running this command:
RAILS_ENV=production bundle exec rake assets:precompile
The Rails Guide on the asset pipeline can give you more details: http://guides.rubyonrails.org/asset_pipeline.html#precompiling-assets
I have a new application using Rails 4 deployed on Heroku with :
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
my javascript application.(fingerprint).js called from the src: assets/application.js
i think your problem come from something into your production.rb who define assets from another location.
So maybe you can add Moderniz.js to
config.assets.precompile = ['.js', '.css', '*.css.erb']
in config/production.rb
Or simply require modernizr script into your application.js
//= require mordernizr
and remove the modernizr script call into your layout.
<%= javascript_include_tag "modernizr", "data-turbolinks-track" => true %>
Can you check from where your application.js is served into your production environment ?
It may be because this file needs to be in /vendor/assets/javascript instead of /app/assets/javascript. The Vendor folder is for javascript libraries, and the App folder is for your code.
A better solution than adding a tag to your layout would be adding a script reference to your application.js and let the sass compiler compress and attach it to your main javascript file.
If you don't get a definitive answer, check out:
http://guides.rubyonrails.org/asset_pipeline.html#asset-organization

Error compiling CSS asset (Compass + Sass + Heroku)

I have a site running on Heroku using Compass with Saas an is working fine (compiling assets when pushing to Heroku seems to be fine).
I added a new folder inside assets to namespace other styling, like this
/app/assets/stylesheets/site/site1.css
/app/assets/stylesheets/site/site2.css
/app/assets/stylesheets/site/common/base.css.saas
/app/assets/stylesheets/site/site/site1.css.saas
/app/assets/stylesheets/site/site/site2.css.saas
...
The problem is when I visit a page that use site1.css styling I get the following error
Error compiling CSS asset
Sass::SyntaxError: File to import not found or unreadable: ../compass/css3/text-shadow.
Load path: /app
(in /app/app/assets/stylesheets/site/common/base.css.sass)
/app/app/assets/stylesheets/site/common/base.css.sass)
The line that the error refers is this
/app/assets/stylesheets/site/common/base.css.sass
#import "../compass/css3/text-shadow"
I tried both "../compass/css3/text-shadow" and "compass/css3/text-shadow". In both cases I got the same error.
Any idea how to solve this?
Solved.
I needed to specify on production.rb file the additional files to compile
config.assets.precompile +=
Dir["#{Rails.root}/app/assets/stylesheets/site/site/*.*"].collect {|s| "site/" + File.basename(s).gsub(/.scss|.sass/, '') }
Now is working fine.

Resources