DEV Community

Lawrence O. for The DEV Team

Posted on


Asset Pipeline JS Migration

Forem has created a milestone to migrate Javascript initializers in asset pipeline to pack tags and we need YOUR help!

In an effort to migrate away from asset pipeline and to more modern JS management, there are various initializers that need to be migrated to pack tags via Webpacker and initialized in the perspective view/page. If you’re looking to contribute to open source, these are great issues (tagged with ready for dev in the milestone) to work on 😄 This post will help guide you through them.

A Little Background

Using Webpacker in Rails provides several advantages over the traditional asset pipeline. First, Webpacker uses JavaScript modules, which allows for better code organization and improved code reusability. Second, it offers modern frontend build tools, such as Babel and PostCSS, for transforming and compiling assets. Third, it provides faster build times and faster runtime performance through code splitting and lazy loading. Fourth, it offers better integration with JavaScript frameworks such as React, Vue, and Angular. Overall, Webpacker offers a more flexible and modern asset management solution for Rails applications. And while Webpacker is being retired, this initiative is to consolidate our code accordingly before moving our bundler to another solution.

High-Level Summary

As Webpacker is already a current dependency in the application, we can begin by migrating an initializer file from app/assets/javascript to app/javascript. We will then change the references to your JavaScript files in your views and layouts to use pack tags instead of the traditional asset pipeline tags.

These steps are a high-level summary and may require additional steps or modifications based on your specific requirements and initializer purpose. It's always recommended to thoroughly test any changes to the application before submitting a Pull Request.

See Forem Dev Docs for further Webpacker references

Step-by-Step with an Example

In setting out to migrate the initializeCommentDate function(app/assets/javascripts/initializers/initializeCommentDate), we first create the file under
and begin moving the code to the newly created file. While some of the code in asset pipeline makes use of CommonJS standards, Javascript under pack tags makes use of ES6 standards. There may be occasions in which those standards would need to be met (i.e. using let/const over var, etc.). These corrections/updates can be captured and identified through our linting commands.

import { addLocalizedDateTimeToElementsTitles } from "../../utilities/localDateTime";

export function initializeCommentDate() {
  const commentsDates = document
                        .querySelectorAll('.comment-date time');

  if (commentsDates) {
    addLocalizedDateTimeToElementsTitles(commentsDates, 'datetime');
Enter fullscreen mode Exit fullscreen mode

You would also want to migrate any dependencies in which the initializer makes use of. In this case, we migrated addLocalizedDateTimeToElementsTitles from localDateTime as a utility function as well.

Next, and one of the most important steps, is determining where to place the reference to the pack tag. Most initializers are global initializers (i.e. initializeBaseTracking) meaning they are required throughout the application, thus, we place those tags in the application.html.erb file as such:

<%= javascript_packs_with_chunks_tag "base", 
"contentDisplayPolicy", defer: true %>
Enter fullscreen mode Exit fullscreen mode

But there may be initializers that may only get initialized on Article pages, etc. It would be a good idea to determine what view the initializers are initialized for and add the pack tag reference to that specified view.

A great, simplistic way of testing locally whether your new pack initializer is being triggered is by logging to the console the initial call and any known or derived variables from the code. In my case, I log commentsDate and assure the localDateTime is added to a title attribute (See addLocalizedDateTimeToElementsTitles). Those are good signs that the initializer is being initialized!

Lastly, remove the asset pipeline references to the initializer and delete the file under app/assets/javascripts/initializers and that's all there is to this great long-awaited migration!


You can find the code for this example here.

If you have any questions or feedback, please drop them in the comments below. If you’d like to contribute to this great migration please have a look through the ones that aren’t assigned in this milestone and raise your hand on the issue. We look forward to your contributions!

Top comments (1)

jmau111 profile image

You'd probably need an exhaustive audit. I remember some PRs with nasty surprises, which is not uncommon for such open-source platforms with "LTS."

This is huge work @lboogie2004 unless you find some cheat codes. Also, InstantClick can raise issues

Need a better mental model for async/await?

Check out this classic DEV post on the subject.

⭐️🎀 JavaScript Visualized: Promises & Async/Await

async await