Skip to Content
Course content

140: Asset Pipeline vs Import Maps

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I've been staring at a Rails project from a few years ago, and I'm reminded of why I used to dread adding a single JavaScript library. I wanted to add a simple data visualization to a dashboard, and suddenly I was diving into a rabbit hole of yarn install, node_modules taking up 400MB of disk space, and the dreaded "Compilation failed" error during deployment. This is the world of the traditional Asset Pipeline (Sprockets) and its successor, Webpacker.

The friction of the "Build Step"

Let's look at how we used to do it. If I wanted to use Chart.js in the old pipeline, I'd have to install it via npm or yarn, import it into a application.js file, and then rely on a bundler to minify, mangle, and concatenate everything into one giant blob of JS that the browser could understand.

# The old flow (simplified)
yarn add chart.js
// in application.js
import Chart from 'chart.js/auto';

It works, but there's a mental tax. Every time I change a line of JS, I'm waiting for a watcher process to recompile. If the watcher crashes—which it often did—I'm left wondering why my changes aren't appearing in the browser. I'm essentially running a Node.js project inside a Ruby project. It feels like two different worlds fighting for control of the public/assets folder.

Trying a different path with Import Maps

I decided to start a fresh Rails 7 app to see if the new "Import Map" approach actually removes that friction. I'll try to get that same Chart.js functionality working, but this time, I'm not touching Node.js. Not once.

First, I run the pin command:

bin/importmap pin chart.js

When I run this, Rails doesn't download a package to my hard drive. Instead, it adds a line to config/importmap.rb. I opened the file and saw this:

pin "chart.js", to: "https://ga.jspm.io/npm:chart.js@4.4.1/dist/chart.umd.js"

This is the "Aha!" moment. I'm not bundling. I'm just telling the browser: "When I say import 'chart.js', go fetch it from this specific URL." The browser handles the loading natively using ES modules. I don't need a compiler, I don't need node_modules, and I certainly don't need to wait for a build step to finish before I refresh the page.

Testing the execution

Now I'll try to actually use it in my view. I'll create a small canvas element and a script tag to initialize the chart.

<canvas id="myChart"></canvas>
<script type="module">
  import Chart from 'chart.js'
  const ctx = document.getElementById('myChart');
  new Chart(ctx, { 
    type: 'bar', 
    data: { labels: ['Red', 'Blue'], datasets: [{ data: [12, 19] }] } 
  });
</script>

I refresh the page. It just... works. No webpacker:compile, no yarn errors. The browser requested the JS file directly from the CDN (or the local proxy), executed it, and rendered the chart. The development loop is now instantaneous.

Where the trade-off hits

Now, I have to be honest: Import Maps aren't a magic bullet for every single project. As I started playing with more complex ideas, I hit a wall. I wanted to use JSX for a small component. I tried to pin a React component, but the browser gave me a syntax error.

Why? Because JSX isn't valid JavaScript. Browsers can't read it. To use JSX, you must transpile it into standard JS using something like Babel. Import Maps skip the transpilation step entirely.

So, here is the mental model I've settled on: If you are writing standard modern JavaScript (ES6+), Import Maps are a godsend. They strip away the complexity of the Node ecosystem. But the moment you need "non-standard" JS—like TypeScript or JSX—you have to go back to a bundler (like esbuild or Webpacker) because you need a tool to translate that code before the browser ever sees it.




📋 Practical Task

Implementing a Live Weather Widget with Import Maps

Your goal is to integrate the confetti-js library into a Rails application using Import Maps to celebrate when a user "checks in" to a location.

  • Step 1: Use the bin/importmap pin command to add the confetti-js library to your application.
  • Step 2: In your app/javascript/application.js, import the library and create a function called triggerCelebration() that initializes a confetti burst on the screen.
  • Step 3: Create a simple view with a button labeled "Check In". Use a data-controller or a simple onclick attribute to call your triggerCelebration() function.
  • Step 4: Verify that the confetti triggers without any Node.js build processes running in the background.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.