The Javascript Fatigue
We have all been there.
You want to start a new project. You run npm install. You wait. You see 84 vulnerabilities found. You try to configure Webpack, but the config format changed since version 4. You add Babel. You add PostCSS.
Three hours later, you haven't written a single line of business logic. You have just been configuring a build pipeline.
For a team of 20 frontend engineers, these tools are necessary. They need tree-shaking, minification, and code-splitting to shave off kilobytes.
But for the One-Person Team? This is pure friction.
Enter the "No-Build" Era
Browser technology has finally caught up. Modern browsers (Chrome, Firefox, Safari, Edge) now support ES Modules natively. They understand import React from "react" without needing a bundler to stitch it all together first.
Rails 7 (and now 8) embraced this with Importmaps.
The premise is simple: What if you just didn't have a build step?
What if you saved a file, hit refresh, and the browser just loaded it?
How Importmaps Work
Instead of bundling 500 files into one massive application.js blob, Importmaps rely on a simple JSON map inside your HTML <head>.
It looks like this:
<script type="importmap">
{
"imports": {
"application": "/assets/application.js",
"lodash": "https://ga.jspm.io/npm:lodash@4.17.21/lodash.js",
"stimulus": "https://ga.jspm.io/npm:@hotwired/stimulus@3.2.1/dist/stimulus.js"
}
}
</script>
When you write import _ from "lodash" in your Javascript, the browser looks at the map, sees the URL, and fetches it.
The Benefits for the Solo Dev
1. No node_modules Black Hole
You don't need yarn, npm, or pnpm. You don't have a 500MB folder on your disk. You don't have to wait for CI to "install dependencies" before running tests. Your repository is cleaner and lighter.
2. Instant Feedback Loop
Because there is no "transpiling" or "bundling" process, the moment you save a file, it is ready.
- Old way: Save -> Wait for Webpack Compiler (2.4s) -> Refresh.
- New way: Save -> Refresh.
3. CDNs do the Heavy Lifting
Rails uses jspm or jsdelivr to fetch libraries. These CDNs are incredibly fast, optimized, and often cached in the user's browser from other sites.
How to use it in Rails
It is ridiculously easy.
Want to add a library? Say, canvas-confetti?
bin/importmap pin canvas-confetti
That's it. Rails finds the CDN URL, adds it to config/importmap.rb, and you can immediately use it in your controller:
// app/javascript/controllers/confetti_controller.js
import JSConfetti from 'canvas-confetti'
export default class extends Controller {
connect() {
const jsConfetti = new JSConfetti()
jsConfetti.addConfetti()
}
}
"But what about Performance?"
The critique is that HTTP/2 requests for many small files are slower than one big bundled file.
While technically true for massive applications, for 95% of SaaS apps, it does not matter.
Network speeds are fast. HTTP/2 and HTTP/3 multiplexing allow browsers to download many small files in parallel. The imperceptible performance difference is worth the massive gain in developer happiness and velocity.
When should you NOT use it?
If you are using React (JSX) or Vue (SFC) heavy flows, you still need a build step (to transpile JSX to JS). In that case, use esbuild or vite.
But if you are following the Rails "Omakase" way - using Hotwire, Turbo, and Stimulus - you are writing standard Javascript. You do not need a bundler.
Summary
The future of development is usually about removing layers of abstraction, not adding them.
Importmaps remove the most fragile, frustrating layer of modern web development: the build pipeline.
Stop debugging config files. Start shipping features.
Have you ditched the build step yet? Share your experience below! 👇
Top comments (0)