Hanami 2 assets (esbuild)

Hanami Assets 2.0 (esbuild)

:point_right: This is a proposal to make Hanami 2.0 work with esbuild and to imagine how the integration would look like. This is NOT a decision to go with esbuild, we’re evaluating other options like Webpack or Vite. :point_left:

General principles

  • Don’t build a single bundle for the entire app (e.g. app.{js,css} ) [BREAKING]
  • Bundle entry points: [NEW FEATURE]
    • Default entry points are index.{js,ts,jsx,tsx} of each slice
      • Example: slices/main/assets/index.tsx
    • Convention: each index.* file is an entry point, that will generate its own bundle
      • Example: slices/main/assets/login/index.tsx
  • Minify assets [1.0 FEATURE]
  • Source maps [NEW FEATURE]
  • Remove pre-processors [BREAKING]
    • Don’t allow Ruby to interpolate values in assets
    • Example: Don’t support foo.js.erb anymore
  • Remove compile mode [BREAKING] V1.3: Overview | Hanami Guides
    • No longer necessary
  • Use esbuild [NEW FEATURE]
  • View helpers: [1.0 FEATURE, BREAKING Ruby API] V1.3: Assets | Hanami Guides
    • assets["index.js"] resolve an asset Path/URL for the current slice
      • Example:
        • Relative path: /main/assets/index.js
        • File path: [app-root]/public/main/assets/index.js
    • assets.javascript(“index.js”) generates a <script> tag
      • aliased as assets.js()
    • assets.stylesheet generates a <link> tag.
      • aliased as assets.css()
    • assets.image("logo.png") generates an <img> tag
    • assets.favicon(“favicon.ico”) generates a <link> tag
    • Other helpers:
      • assets.video
      • assets.audio
      • assets.path (forces relative path)
      • assets.url (forces absolute path)
  • Fingerprint mode: [1.0 FEATURE] V1.3: Overview | Hanami Guides
    • Use a JSON manifest to resolve helpers path (e.g. assets.javascript(“index.js”)) to real path (e.g. /main/assets/index-abc123.js , where abc123 is the file hashing)
  • Subresource Integrity [1.0 FEATURE] V1.3: Content Delivery Network (CDN) | Hanami Guides
  • CDN: [1.0 FEATURE] V1.3: Content Delivery Network (CDN) | Hanami Guides
    • Configure a CDN base URL. Example: Assuming base_url = "https://123.cloudfront.net", assets.javascript(“index.js”) will be resolved as "https://123.cloudfront.net/main/assets/index.js"
    • When working in combination with Fingerprint mode the above URL would be resolved as "https://123.cloudfront.net/main/assets/index-abc123.js"



  • Watch the source directories (slices/assets/**/*) and output in public
  • Use a Rack middleware to statically serve those assets [1.0 FEATURE]

Test (and CI)

  • Before test suite precompile the assets in public directory
  • Use a Rack middleware to statically serve those assets [1.0 FEATURE]


  • Precompile assets at deploy time in public directory [1.0 FEATURE]
    • Write a JSON manifest [1.0 FEATURE]
  • Use NGINX or CDN to statically serve assets [1.0 FEATURE]