Rails: Precompiled assets missing node modules
I have finally found the problem. It is a very nasty bug of the sass-rails
gem & an unfortunate design of the sprockets
component of Rails.
1) sass-rails
@import
does not seem to work with node_modules
as it does with other assets. While those other assets get compiled into one file, node_modules
only get referenced, loaded by the browser as separate sources, but ultimately not being used by the browser.
2) sprockets
Sprockets' require
statement does only work if it is at the beginning of a file. Or as they put it in their documentation:
Note: Directives are only processed if they come before any application code. Once you have a line that does not include a comment or whitespace then Sprockets will stop looking for directives. If you use a directive outside of the "header" of the document it will not do anything, and won't raise any errors.
However, in my case, I was importing directives from a file that itself was imported from application.sass
.
Add node_modules to the rails asset paths causes an asset compilation error
OK, so it turns out that sprockets will hungrily process any JS it finds in a directory named application!
I found this by changing my uglifier to handle ES6 syntax:
config.assets.js_compressor = Uglifier.new(harmony: true)
And then discovered that the assets compile had produced another JS file:
./public/assets//@schematics/angular/application/index-7cb879a643459c580f46b4127272b2918753e9941c074dcf27faea589ca610de.js
./public/assets//application-f78f0f583e152fa235ca51f99bab70d1aeb59675de57c78bcef18b5a2e8a5a5f.js
The file is coming from here:
$ find ./node_modules/ | grep -E "application/.*.js$"
./node_modules//@schematics/angular/application/index.js
./node_modules//@schematics/angular/application/files/karma.conf.js
./node_modules//@schematics/angular/application/files/protractor.conf.js
Heroku and Precompiled Assets
Compile assets locally
To solve this chicken and egg problem with the database in deploy, do not invoke precompile in production, precompile on development machine for production prior to push. With a functional code base pushed, you can run "$heroku db:xxx" commands on Heroku.
- Turn off precompile assets in production.rb:
config.assets.compile = false
- Precompile assets for production on development machine:
$bundle exec rake assets:precompile RAILS_ENV=production
- Now your code glob will include your precompiled assets, so push it.
$heroku push
On deploy to Heroku, you're looking for this line:
-----> Preparing Rails asset pipeline
Detected manifest.yml, assuming assets were compiled locally
- At this point you can create your production database on Heroku
$heroku db:migrate
I think these steps will solve your problem. Please let me know.
Caveat
Once you disable precompile, you will have to remember to always precompile for production on your dev system prior to deploy to production.
Javascript compilation into asset pipeline
Since you're specifically speaking of js precompile, And I haven't tried this, but it seems these types of precompile js-specific lines should also be commented out in production.rb if you have them. There are the same type of js directives in assets. rb, again I don't know if these need to be cleared or not. (The main point is to do a local asset precompile, before the push to Heroku.)
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
# config.assets.precompile += %w( xxxx.js )
Heroku docs
https://devcenter.heroku.com/articles/rails-asset-pipeline#compiling-assets-locally
Rails precompile assets Yarn executable was not detected
Rails 5.1 comes with SUPPORT for yarn and webpack, but you need to install them yourself.
Yarn is a package manager and webpack is a package.
Follow instruction at https://yarnpkg.com/lang/en/docs/install/ to install Yarn in your system and then add webpack to your project like:
yarn add --dev webpack webpack-dev-server
Additionally, the message you're seeing is warning, rather than straight up error. If you do not need to use any of the fancy js packages, you can just use good ol' asset pipeline
Related Topics
How to Get The System Accent Color for Uwp-Apps
Wicked_Pdf Stylesheet Not Working on Heroku
Webkit CSS Pseudo Elements for Time Field
How Are The Widths of Nested Absolutely Positioned Elements Determined
Editing Angular Material's Table Cell Padding
Empty Div with Red Border Is Visible as a Red Line - How to Hide It Only with CSS
Less CSS - Setting Variable Within Mixin
Material-Ui - Apply Max-Height to Select Children
Force Absolute Div to Listen to Parent's Padding
How to Inherit Only One Element of CSS Shorthand
How to Alternate The Number of Children Between Odd and Even Rows
Use CSS to Alternate Ul Bullet Point Styles
How to Implement a CSS-Only Fallback for Background-Size