---
title: Pin JavaScript Dependencies with Import Maps
impact: MEDIUM
impactDescription: eliminates npm/webpack build step entirely
tags: arch, importmap, javascript, dependencies
---

## Pin JavaScript Dependencies with Import Maps

Rails 7+ uses import maps by default to deliver JavaScript without a bundler. This removes the entire Node.js build toolchain (npm, webpack, esbuild) from the development and deployment pipeline, simplifying dependency management and reducing build times to zero. Using `bin/importmap pin` fetches ESM-compatible modules from CDNs and registers them for direct browser loading.

**Incorrect (adding npm packages and configuring webpack/esbuild for client JS):**

```json
// package.json — unnecessary build tooling
{
  "dependencies": {
    "stimulus-autocomplete": "^3.1.0",
    "sortablejs": "^1.15.0",
    "chart.js": "^4.4.0"
  },
  "devDependencies": {
    "esbuild": "^0.19.0",
    "webpack": "^5.88.0"
  }
}
```

```js
// app/javascript/application.js — requires bundler to resolve node_modules
import { Autocomplete } from "stimulus-autocomplete"
import Sortable from "sortablejs"
// Bundler must process and bundle these imports
```

**Correct (bin/importmap pin, direct browser ESM loading):**

```ruby
# Terminal: pin dependencies from CDN
# bin/importmap pin stimulus-autocomplete
# bin/importmap pin sortablejs
# bin/importmap pin chart.js

# config/importmap.rb — generated by pin commands
pin "application"
pin "@hotwired/turbo-rails", to: "turbo.min.js"
pin "@hotwired/stimulus", to: "stimulus.min.js"
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js"

pin "stimulus-autocomplete", to: "https://ga.jspm.io/npm:stimulus-autocomplete@3.1.0/src/autocomplete.js"
pin "sortablejs", to: "https://ga.jspm.io/npm:sortablejs@1.15.0/modular/sortable.esm.js"
pin_all_from "app/javascript/controllers", under: "controllers"
```

```js
// app/javascript/application.js — no bundler needed
import "@hotwired/turbo-rails"
import "controllers"
```

**When NOT to use this pattern:**
- Packages that only publish CommonJS (no ESM) and lack CDN builds
- Applications requiring tree-shaking for large dependency graphs
- TypeScript-first codebases that need transpilation
- Complex CSS pipelines (PostCSS, CSS modules) that require a build step
