Idiomatic Sass processing in Rails 7 - ruby-on-rails

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.

Related

rails 7 with sprockets, enable origin file in compiled css in development

I just started a new rails 7 project with --css bootstrap, but I'm finding that starting the server with bin/dev the compiled css does no longer (as in previous rails versions) output a comment with the file name and line number of the file where to find each scss class definition.
I'm actually rather confused on how the new rails works with scss and css, it doesn't seem that the css is compiled at all. I couldn't find any good resources for understanding how it works. any suggestions?
Thanks,
Sprockets doesn't seem to generate sourcemaps by default.
You can try opening up this file:
config/environments/development.rb
And adding the line:
config.assets.debug = true
What are the contents of you din/dev file?
Also rails 7 got rid of webpack:
Webpacker has served the Rails community for over five years as a
bridge to compiled and bundled JavaScript. This bridge is no longer
needed for most people in most situations following the release of
Rails 7. We now have three great default answers to JavaScript in
2021+, and thus we will no longer be evolving Webpacker in an official
Rails capacity.
Rails 7 now uses importmaps, so depending on your gem file you might have to use css-bundling. Look into that and dartsass along with propshaft, which replaces sprockets which they are thinking about doing in the future, to get a better idea.
Will Propshaft replace Sprockets as the Rails default? Most likely,
but Sprockets need to be supported as well for a long time to come.
Plenty of apps and gems were built on Sprocket features, and they
won't be migrating soon. Still working out the compatibility story.
This is very much alpha software at the moment.

Adding Lodash to a new Rails 5.2 app with webpacker

So, using Rails 5.2beta (gem install rails --pre), if you create a new app via rails new myapp --webpack=react... how would I go about incorporating Lodash into my flow from there?
I've mucked around with babel-plugin-lodash and lodash-webpack-plugin to no avail.
The compile doesn't fail if I do something like import { _pick, _map } from 'lodash/array'; ... but those variables are undefined when trying to use them.
I'm a bit lost as I'm both new to webpacker & webpack, and a lot of existing examples seem to target an older version of webpack?
Anyway, thank you for any help...
UPDATE:
Ok, looks like you can just do import map from "lodash/map"
So where are you trying to use lodash from? By this I mean are you sure the files are getting compiled / processed by Webpacker, or are they getting processed via the Asset Pipeline?
On my webpacker project I realized that there's a problem: that yes, regular old Javascript compiled with the Asset Pipeline won't know about the NPM Modules included via Webpack. (or at least the require statements wouldn't work).
Because of this I made a hard rule: all javascript goes where webpacker expect it (app/javascript) and no Javascript goes in app/assets. We only use the asset pipeline for CSS (which works great in our case, as I still don't think React - our frontend framework of choice - has a good story around site wide CSS).

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.

Source maps in Ruby on Rails through sprockets

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.

Should I port my existing Jammit asset pipeline to the new Rails 3.1 version?

We've implemented Jammit for asset caching, compression and optimization in our Rails application. It's fully integrated with our continuous integration process and works well. That said, I am seeing 3.1 introduces a new canonical asset pipeline based on Sprockets.
Are there advantages to the Sprocket based approach that would merit porting our system? I do not want to spend time converting our system if there are no benefits.
I have already used Sprocket and Jammit and the main advantage of the Rails 3.1 approach is the complete and native integration of Sprocket, not the gem itself. I'm not a specialist but both gems are great and, for me, equivalent.
The rails 3.1 assets pipeline provide a clean architecture for js and css files and the native use of associated gems (sass, coffee-script, sprocket). If in your app you already have a clean tree for your files and a great integration of your gems, don't change anything !

Resources