Source maps in Ruby on Rails through sprockets - ruby-on-rails

I'd like to add source map support on a rails 3.2 application I am working on. As far as I know, generating source maps is not supported by Sprockets and from its github page it looks like the feature is planned for 4.0. I am working with Sprockets 2.2 and I think monkey patching is the only way to go. The module Processing under the main Sprockets module gives access to the js_compressor function which can be patched to generate source map for a single file. But, I don't know how to add this when the JS files combine. I am using Uglifier 2.4 as the compressor.
The project has a mixture of CoffeeScript, JS and EJS files. So, I think this is how sprockets would be compiling them together. First, it would convert Coffeescript and EJS to JS, then use the js_compressor to compress individual files and later concatenate them in groups. Now, as the source map for multiple files combined to the same file is a single file. So, I will need to change the compilation process somewhat and make the js_compressor run over the files, once the concatenation is finished. So, can anyone help out with this? Even explaining the sprockets compilation process and the modules used and functions involved would be of great help. I don't care about making source map files for the CoffeeScript code at present. Even mapping to their converted JS files would do.
Also, would like to add if there is some gem which can help with this it would be most welcome.

Rails 4 does not have source maps either.
As far as I know, and as of today, this will only be part of rails 5.
A really nice approach to solve this right now is implemented in discourse by #SamSaffron and explained here:
https://github.com/discourse/discourse/blob/master/lib/tasks/assets.rake
The gist, add a "before" task to the sprockets precompile process, and hack into the compilation process to generate the sourcemapped files and directives.
The nice thing in this approach is that you don't lose stuff from files that are both js and erb (*.js.erb) which is something quite common in rails.
I think that patching the whole sprockets pipeline is a bit of an abuse and risky.

Related

Idiomatic Sass processing in Rails 7

I'm confused about the idiomatic way to process Sass in Rails 7.
The README.md for the importmap-rails repo says:
This frees you from needing Webpack, Yarn, npm, or any other part of the JavaScript toolchain. All you need is the asset pipeline that's already included in Rails.
and The Rails Guide to The Asset Pipeline states that:
Rails can easily work with Sass by adding the sassc-rails gem to your Gemfile, which is used by Sprockets for Sass compilation
But in October 2020 we learned that LibSass is Deprecated, and that we should be using Dart Sass instead.
The sassc-rails gem is based on LibSass.
Hence should we be using something else to process Sass? And if so is the documentation on the Rails 7 asset pipeline misleading?
I'm relatively new to Rails and my naive reading of The README.md and The Asset Pipeline Guide led me to think that we should be using "the asset pipeline that's already included in Rails" to compile Sass and did not need "Yarn, npm, or any other part of the JavaScript toolchain".
What is the Rails 7 idiomatic way to process Sass?
In addition to the answer pasted in by #dumbledad, note that there is a serious disconnect in Rails 7 between JavaScript and CSS. While import maps as a specification and concept can in theory handle both ECMAScript modules and CSS modules, Rails 7 only supports ECMAScript modules and you're left out in the cold with CSS.
TL;DR, import maps are almost useless if you have any third party components that comprise CSS as well as JS components, unless you don't mind manually version-maintaining the same thing via two different package management systems in two different parts of your application. If you're happy with that dual maintenance overhead, then you can keep it lightweight and use import maps along with e.g. dartsass-rails.
See later comments on https://github.com/rails/importmap-rails/issues/107 for an official reply - basically, use jsbundling-rails and cssbundling-rails with a fully Node-based setup if you're going to have any components with both JS and CSS parts, unless you want to version-manage them separately.
You'd remove any gem that gave you those components, e.g. remove Bootstrap
You'd instead manage such dependencies via package.json and Yarn
You'll use bin/dev to run your development server and have CSS & JS compilation
While this much heavier approach is sad compared to either a simple Gem + Sprockets workflow (non-Webpacker) or import maps, and while it seems to have significant drawbacks now that e.g. #import wildcards aren't supported so you have to now hand-maintain lists of files that previously could just be linked as a tree - and so-on, there are sadly a lot of drawbacks compared to e.g. Rails 4-5 ish era simple Sprockets and gems with synchronous on-demand compilation by a single server process in development - it does mean you have access to a dramatically wider range of options for preprocessing, transpilation, generalised NPM / Yarn ecosystem or alternate build mechanisms, and it's now fronted by "vanilla" Yarn and package.json without any weird gems in the middle making things harder to learn.
(Copied directly from DHH's reply to the GitHub Issue.)
There are two ways to use Dart Sass in Rails. Either through
cssbundling-rails with Node. Or with
https://github.com/rails/dartsass-rails, using the standalone Dart
Sass compiler, without node. If you're doing a default Rails 7 app
that uses import maps, you should do the latter.
We need to update the asset pipeline guide and other documentation to
recognize this.
Just dropping it here, as it would help me, when I landed here while looking for answers myself. But the post was not produced at that time. I hope it helps and anyone can participate by writing it.
There is new unfinished guide about asset pipelines and where rails is going.

Integrating ActionCable with Webpacker in Rails 5.1

I am upgrading my app from Rails 5.0 to 5.1, and there is one thing I can't find being mentioned anywhere - usage of Webpacker to process ActionCable JavaScript files.
I realise that Webpacker and the asset pipeline are supposed to work side by side, but now that we have Webpack build into Rails it would be a waste not to use it for files located in assets directory (which is where ActionCable lives), yet I can't find any information on how to do that.
I'm specifically interested in Babel, so I could use ES6. Any ideas?
The problem here is that you need to replace the ActionCable implementation of rails, which is written for sprockets with something that is written in module syntax, to make proper use of webpacker.
Specifically this line in your cable.js
require action_cable
Everything else should be easily portable.
There seem to be a couple of implementations for ActionCable and modules around:
https://www.npmjs.com/search?q=keywords:ActionCable
Specifically this looks exactly what you are searching for:
https://www.npmjs.com/package/actioncable-modules
There seems to be some movement on the side of Rails to use Webpacker as a complete sprocket replacement in Rails 6, so it might be worth waiting, instead of creating something that builds on third party modules.

How to use googlecharts library in rails?

I want to use googlecharts in my rails App, and I decided use it directly without using wrapper library.
Currently I download jsapi file from https://www.google.com/jsapi and rename it to jsapi.js, then move the file to vendor/javascripts/google/jsqpi.js.
Then require the file in application.js.
Now I can use the library I want only to know if this is a right way to use the third party library in rails.
Is there better way than this way?
That is perfectly acceptable. vendor/assets/javascripts is the correct location for third-party javascript files.
Sometimes you can find gems that include third-party javascript libraries and integrate them into the asset pipeline for you (e.g. jquery-ui-rails gem). This is nice because it makes you not responsible for handling the actual files and is easier on your version control software (a single line in your Gemfile vs entire files). You can also update the files with bundler. However, this tends to only be practical for really popular libraries. Sometimes you can find gems for the javascript library you are looking for, but the gem hasn't been updated in ages. Of course, you could always roll your own gem that includes the libraries you want.
Have you taken a look at googlecharts gem
its full of examples

How does Rails and Ember integration work, do all the ember files get combined?

I'v seen some larger emberjs implementations like discourse: https://github.com/discourse/discourse/tree/master/app/assets/javascripts/discourse
Can someone explain to me how this gets integration into rails?
What happens behind the scenes when the asset gets compiled? To the files just get minified and merged or there is more to it?
You need to read about Asset Pipeline.
The directory you linked to above is included by the various require lines in app/assets/javascripts/main_include.js, which is itself included by app/assets/javascripts/application.js.erb.
The gem doing the heavy lifting (the one responsible for interpreting the require lines) is Sprockets.
What happens behind the scenes when the asset gets compiled? To the files just get minified and merged or there is more to it?
Between the asset pipeline docs and sprockets' docs, your very general question should be more than answered. In a nutshell, yes, the files are minified and merged, and yes there is a whole lot more to it.
In addition to reading about the Asset Pipeline and Sprockets (which handle JS minification, etc), also take a look at the ember-rails gem: https://github.com/emberjs/ember-rails
ember-rails allows you to include Ember.JS into your Rails 3.1+ application. The gem will also pre-compile your handlebars templates when building your asset pipeline. It includes development and production copies of Ember.

Sass - can it be compiled at runtime?

I've seen that certain Rails CMSes (like Radiant) have plugins that essentially compile Sass when a page is accessed. Is there a way to do this in a regular rails app? Is doing so performant? Basically, I'm looking at a way to remove the extra step of running Compass to compile my stylesheets.
I've not used compass specifically but there looks like there's a production flag so files are compiled - I couldn't imagine they'd build it to recompile per request in production, Radiant compiles it's css on Application startup and if you then commit those generated CSS files it doesn't try to generate them again AFAIK.
http://compass-style.org/docs/tutorials/production-css/
Sass and Compass automatically integrate with Rails. If you're using Rails 3, all you have to do is add gem "haml" to your Gemfile and all .sass and .scss files in public/stylesheets/sass will get compiled to .css files in public/stylesheets.
Compile per request? I think it could be a hit for performance. You should definitely use a caching strategy in that case. So that it compiles the stylesheet only if it is not in the cache.
You could create a helper method setup_stylesheet that will take care of setting up the css stylesheet. You call this method on the application layout.
setup_stylesheet will check if the css stylesheet is on the cache, and if it is there then use it. If it is not, then compile it.
Another approach:
You could set up an initialiser that will call Compass to compile your SASS stylesheets when the App is launched.
Is doing so performant?
There will be a massive performance hit when compiling at run-time.
As Nex3 (author of Sass gem) pointed out on another forum, there's no need any need to run compass watch.
I strongly advise putting the following into production.rb: Sass::Plugin.options[:never_update] = true - this is especially important if you're on Heroku. (you could also do this in your rack file, where you can also specify other options
Hmm, good luck

Resources