I enjoy spending time learning new technologies. However, often the biggest drawback of working with new technologies are the inevitable pain points that come with early adoption. I saw this quite a bit when I was getting up to speed with Web3 in “How to Transition from Full-Stack Developer to Web3 Pioneer in 2022.”
As software engineers, we’re accustomed to accepting these early-adopter challenges when giving new tech a test drive. What works best for me is to keep a running list of notes and commands I’ve executed since seemingly illogical steps don’t remain in my memory.
Aside from Web3, I also found this challenge in the JavaScript space, with the semi-standard requirements of using Node.js and Webpack. I wanted to identify a solution where I could just use JavaScript as is without toiling away with Node.js and Webpack. I recently read how the Rails 7 release addressed this very situation. So, that’s the use case I’ll be covering in this article.
To be fully transparent, my experience with Ruby and Ruby on Rails is little to none. I remember watching someone issue some commands to create a fully functional service years ago, and I thought, “Wow, that looks awesome.” But I’ve never spent time playing around with this approach to building services and applications.
I’m pretty sure I saw that demo in early 2006 because Rails first emerged in late 2005. Like I saw in the demonstration, the end result was a service that supported the model-view-controller (MVC) design pattern, a pattern that I was familiar with through my early use of the Spring, Struts, JSF, and Seam frameworks.
Rails maintains a promise to keep things straightforward while adhering to DRY (don’t repeat yourself) practices. To help honor this promise, Ruby uses Gems for engineers to introduce shared dependencies into their projects.
In late 2021, the seventh major version of Rails introduced some exciting features:
That last feature is what drove me to write this article.
At a high level, the importmaps-rails Gem allows developers to import maps into their applications. The use of /bin/importmap
allows engineers to update, pin, or unpin dependencies as needed. This is similar to how Maven and Gradle work in Java-based projects.
This eliminates needing to deal with the complexities related to bundling packages and transpiling ES6 and Babel. Goodbye Webpack! Goodbye Node.js!
Since I hadn’t even touched Ruby on Rails in almost two decades, the first thing I needed to do was follow this guide to install Ruby 3.3 on my MacBook Pro. Once installed, I just needed to install the Ruby plugin as part of my IntelliJ IDEA IDE.
Then, I created a new Ruby on Rails project in IntelliJ called import-map
and specified the use of Importmap
for the JavaScript framework:
With the project created, I first wanted to see how easy it would be to use a local JavaScript library. So, I created a new JavaScript file called /public/jvc_utilities.js
with the following contents:
export default function() {
console.log('*****************');
console.log('* jvc-utilities *');
console.log('* version 0.0.1 *');
console.log('*****************');
}
The default function simply echoes some commands to the JavaScript console.
Next, I created an HTML file (/public/jvc-utilities.html
) with the following contents:
<!DOCTYPE html>
<html>
<head>
<title>jvc-utilities</title>
</head>
<script type="importmap">
{ "imports": { "jvc_utilities": "./jvc_utilities.js"} }
</script>
<script type="module">
import JvcUtilities from "jvc_utilities";
JvcUtilities();
</script>
<h3>jvc-utilities.html</h3>
<p>Open the console to see the output of the
<code>JvcUtilities()</code> function.
</p>
</html>
This example demonstrates how a local JavaScript file can be used with a public HTML file— without any additional work.
Next, I created a new controller called Example
:
bin/rails generate controller Example index
I wanted to use the Lodash library for this example, so I used the following command to add the library to my import-map
project:
bin/importmap pin lodash
To add some JavaScript-based functionality to the controller, I updated javascript/controllers/example_controller.js
to look like this:
import { Controller } from "@hotwired/stimulus"
import _ from "lodash"
export default class extends Controller {
connect() {
const array = [1, 2, 3]
const doubled = _.map(array, n => n * 2)
console.log('array', array) // Output: [1, 2, 3]
console.log('doubled', doubled) // Output: [2, 4, 6]
this.element.textContent = `array=${array} doubled=${doubled.join(', ')}`
}
}
This logic establishes an array of three values, and then it doubles the values. I use the Lodash map()
method to do this.
Finally, I updated views/example/index.html.erb
to contain the following:
<h3>Example Controller</h3>
<div data-controller="example"></div>
At this point, the following URIs are now available:
/jvc-utilities.html
/example/index
Rather than run the Rails service locally, I thought I would use Heroku instead. This way, I could make sure my service could be accessible for other consumers.
Using my Heroku account, I followed the “Getting Started on Heroku with Ruby” guide. Based upon my project, my first step was to add a file named Procfile
with the following contents:
web: bundle exec puma -C config/puma.rb
Next, I used the Heroku CLI to create a new application in Heroku:
heroku login
heroku create
With the create
command, I had the following application up and running:
Creating app... done, ⬢ lit-basin-84681
https://lit-basin-84681-3f5a7507b174.herokuapp.com/ | https://git.heroku.com/lit-basin-84681.git
This step also created the Git remote that the Heroku ecosystem uses.
Now, all I needed do was push my latest updates to Heroku and deploy the application:
git push heroku main
With that, my code was pushed to Heroku, which then compiled and deployed my application. In less than a minute, I saw the following, letting me know that my application was ready for use:
remote: Verifying deploy... done.
To https://git.heroku.com/lit-basin-84681.git
fe0b7ad..1a21bdd main -> main
Then, I navigated to the /example/index
page using my Heroku URL (which is unique to my application, but I have since taken it down): https://lit-basin-84681-3f5a7507b174.herokuapp.com/example/index
This is what I saw:
And when I viewed the JavaScript console in my browser, the following logs appeared:
Navigating to /jvc-utilities.html
, I saw the following information:
When I viewed the JavaScript console in my browser, I saw the the following logs:
Success. I was able to use a self-contained JavaScript library and also the public Lodash JavaScript library in my Rails 7 application—all by using Import Maps and without needing to deal with Webpack or Node.js. Buh-bye, Webpack and Node.js!
My readers may recall my personal mission statement, which I feel can apply to any IT professional:
“Focus your time on delivering features/functionality that extends the value of your intellectual property. Leverage frameworks, products, and services for everything else.” — J. Vester
In this article, I dove head-first into Rails 7 and used Import Maps to show how easily you can use JavaScript libraries without the extra effort of needing to use Webpack and Node.js. I was quite impressed by the small amount of time that was required to accomplish my goals despite it being over two decades since I had last seen Rails in action.
From a deployment perspective, the effort to deploy the Rails application onto the Heroku platform consisted of the creation of a Procfile
and three CLI commands.
In both cases, Rails and Heroku adhere to my mission statement by allowing me to remain laser-focused on delivering value to my customers and not get bogged down by challenges with Webpack, Node.js, or even DevOps tasks.
While I am certain we will continue to face not-so-ideal pain points when exploring new technologies, I am also confident that in time, we will see similar accomplishments as I demonstrated in this article.
As always, my source code can be found on GitLab here.
Have a really great day!