While working on a Rails application, your code base will grow a collection of different file types including:
Ruby (business logic)
HTML fragments (layouts and views)
CSS/Sass/SCSS (styles)
JavaScript (client-side behavior)
Static media (images, fonts, videos)
Except for the Ruby part, all these files are shipped to the browser. In this card we'll focus specifically on CSS, JS, fonts and static media files which are often summed up as assets.
You might already have noticed that Rails modifies those assets before delivering them to the client. For example, you'll never see SASS anywhere in your browser. Rails offers various asset processing and delivery mechanisms which will be covered in this card.
Goals
For each frontend management system listed below, understand how they achieve:
Asset concatenation
Are they bundling many small JavaScript or CSS files into one single file?
If yes, how can we define a "manifest" or "pack" that defines which files should be included in the build?
Can our JavaScripts use import or require to load another file?
Fingerprinting
Can it fingerprint the build output to improve caching?
What are "expiry" or "cache-control" headers? How do those work for our applications?
How can static images be referenced e.g. in stylesheets without any knowledge of the current fingerprint?
/* your code */
background-image: url(logo.png)
/* the same style inspected within the browser (Webpack example) */
background-image: url(packs/assets/logo-9929e2bc15378bb351e3.png)
How are those file references stored within the local file system?
How can your assets be transpiled, e.g. from Sass to CSS or from ESNext to ES2015?
Can we define our own postprocessing steps? E.g. a transformation that finds and replaces some string in all .js files.
Note that all of the above is solved in every frontend management system below. They use different paradigms to tackle the underlying problems and differ mainly regarding:
the syntax to require or import other files
the syntax and location of their configuration files
e.g. to define the target ES level of the JS transpilation or to add a custom postprocessing step to add CSS vendor prefixes
the location of libraries, manifests and packs
You should know how to import files and spot the different locations for each management system.
Overview: Frontend Management Systems
Over time, we adapted various asset management systems. You already got to know esbuild, which is used in your MovieDB and our most recent applications. This is our preferred solution and should be your main focus while working on this card.
As we maintain more than a hundred applications, many of them still use the asset pipeline and Webpacker. You should roughly understand how they work, but don't invest more than a day to skim over the asset pipeline and webpacker.
Rails 1-7 with the Asset Pipeline (Sprockets)
The asset pipeline is Rails' original mechanism on how stylesheets, javascripts and images from your /assets folder are processed and delivered to the browser
Used in all our projects from 2009-2019, for example makandracards
Because of its simplicity, we might still use it in projects with a very narrow scope
Has no separate build process in development. Instead the Rails server directly compiles the asset whenever it renders a javascript_tag, stylesheet_tag or image_tag.
It still has issues on integrating well with vendor libraries or the npm ecosystem:
import and export statements (ESM) are not supported
because of this, you can only add libraries that are packed in a single file and register themselves globally on the window object
Why are image-url and font-url necessary for sass urls?
When importing variables or mixins into a .sass file, we need to use @import other_file.
Note that we cannot use //= require 'other_file'
//= require is a sprockets statement that would copy and duplicate the content file in your bundle each time you use it.
only SASS @imports are aware of the current state of your variable definitions
Have a look at the goals section above focusing on the asset pipeline
Rails 5+ with Webpacker
Webpacker has many more moving parts than the asset pipeline, but allowed us to use ES6 modules and npm packages (through yarnShow archive.org snapshot) a lot earlier than it was introduced for sprockets. Even after that sprockets is still missing many modern bundling features and has issues with library support. Webpacker is a wrapper around a JavaScript project called webpackShow archive.org snapshot
Used in all our projects from 2019-2022, for example Studyflix
Import maps let you import JavaScript modules using logical names. You can build modern JavaScript applications using ESM libraries without the need for transpiling or bundling. This frees you from needing Webpack and Yarn.
This is an experimental solution that could become the default in future Rails versions.
It lacks any transpilation/transformation and bundling features. They reason that bundling is no longer necessary with HTTP/2, but in practice we still need some form of minification etc.
Don't spend more than 15 minutes looking at this approach as we're currently not using it. You should mainly know that it exists.