No release in over 3 years
Rails Engine providing Vite view helpers with automatic dev server detection and manifest-based asset resolution for seamless Vite integration in Rails applications.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Runtime

>= 8.0.0, < 8.2
 Project Readme

BetterViteHelper

Rails Engine providing Vite view helpers with automatic dev server detection and manifest-based asset resolution.

Requirements

  • Ruby >= 3.4.7
  • Rails >= 8.0.0, < 8.2

Quick Start

# Add to Gemfile
bundle add better_vite_helper

# Run the generator
bin/rails generate better_vite_helper:install

# Start development (two terminals)
yarn dev          # Terminal 1: Vite dev server
bin/rails server  # Terminal 2: Rails server

Visit http://localhost:3000 - assets are served via Vite with HMR.

Installation

Add to your Gemfile:

gem "better_vite_helper"

Then run:

bundle install
bin/rails generate better_vite_helper:install

The generator automatically:

  • Creates package.json if missing (with dev and build scripts)
  • Installs Vite and Tailwind CSS v4 via yarn (or npm)
  • Copies vite.config.js and postcss.config.js
  • Copies app/javascript/application.js with image glob imports
  • Copies app/assets/stylesheets/application.css with Tailwind CSS import
  • Updates app/views/layouts/application.html.erb with Vite helpers
  • Updates .gitignore with Node/Yarn/Vite entries

Generator Options

bin/rails generate better_vite_helper:install --skip-install  # Skip npm dependencies
bin/rails generate better_vite_helper:install --skip-layout   # Skip layout modification
Option Description
--skip-install Skip installing Vite via yarn/npm
--skip-layout Skip updating application layout with Vite helpers

Development Workflow

Starting Development

# Terminal 1: Start Vite dev server with HMR
yarn dev

# Terminal 2: Start Rails server
bin/rails server

Building for Production

# Build assets with Vite
yarn build

# Assets are output to public/assets/ with manifest.json

Layout Example

A typical application.html.erb after installation:

<!DOCTYPE html>
<html>
  <head>
    <title>My App</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <%= vite_stylesheet_link_tag "application.css" %>
  </head>
  <body>
    <%= yield %>
    <%= vite_javascript_include_tag "application.js" %>
  </body>
</html>

Usage

View Helpers

<%# Include JavaScript entry %>
<%= vite_javascript_include_tag "application.js" %>
<%# Output (dev):  <script type="module" src="http://localhost:5173/app/javascript/application.js"></script> %>
<%# Output (prod): <script type="module" src="/assets/application-abc123.js"></script> %>

<%# Include stylesheet (production only, Vite handles HMR in dev) %>
<%= vite_stylesheet_link_tag "application.css" %>
<%# Output (dev):  (empty - Vite injects styles via JS) %>
<%# Output (prod): <link rel="stylesheet" href="/assets/application-xyz789.css"> %>

<%# Get asset path directly %>
<%= vite_asset_path "application.js" %>
<%# Output (dev):  http://localhost:5173/app/javascript/application.js %>
<%# Output (prod): /assets/application-abc123.js %>

<%# Check if dev server is running %>
<% if vite_development? %>
  <!-- Development mode: Vite dev server is active -->
<% else %>
  <!-- Production mode: Using built assets -->
<% end %>

Image Helpers

<%# Generate img tag with Vite-resolved src %>
<%= vite_image_tag "logo.png", alt: "Logo", class: "logo" %>
<%# Output (dev):  <img src="http://localhost:5173/app/assets/images/logo.png" alt="Logo" class="logo"> %>
<%# Output (prod): <img src="/assets/logo-abc123.png" alt="Logo" class="logo"> %>

<%# Subdirectory images %>
<%= vite_image_tag "icons/arrow.svg", alt: "Arrow" %>

<%# With size attribute %>
<%= vite_image_tag "hero.jpg", alt: "Hero", size: "800x600" %>

<%# Get image path directly %>
<%= vite_image_path "logo.png" %>
<%# Dev:  http://localhost:5173/app/assets/images/logo.png %>
<%# Prod: /assets/logo-abc123.png (with CDN if configured) %>

Images in app/assets/images/ are automatically included in the Vite build via import.meta.glob.

Configuration

# config/initializers/better_vite_helper.rb
BetterViteHelper.configure do |config|
  config.dev_server_url = "http://localhost:5173"  # default, or ENV["VITE_DEV_SERVER_URL"]
  config.manifest_path = Rails.root.join("public/assets/.vite/manifest.json")  # default
  config.asset_host = "https://cdn.example.com"  # optional, falls back to Rails.application.config.asset_host
  config.images_path = "app/assets/images"  # default
end

API Reference

JavaScript and CSS Helpers

vite_javascript_include_tag(entry, **options)

Generates a <script type="module"> tag for the specified entry point.

<%= vite_javascript_include_tag "application.js" %>
<%= vite_javascript_include_tag "admin.js", defer: true, data: { turbo_track: "reload" } %>

vite_stylesheet_link_tag(entry, **options)

Generates a <link rel="stylesheet"> tag. Returns empty string in development (Vite injects styles via JavaScript for HMR).

<%= vite_stylesheet_link_tag "application.css" %>
<%= vite_stylesheet_link_tag "admin.css", media: "print" %>

vite_asset_path(entry)

Returns the resolved URL for an asset entry.

<%= vite_asset_path "application.js" %>
# => "http://localhost:5173/app/javascript/application.js" (dev)
# => "/assets/application-abc123.js" (prod)

Image Helpers

vite_image_tag(source, **options)

Generates an <img> tag with Vite-resolved src. Accepts all standard Rails image_tag options.

<%= vite_image_tag "logo.png", alt: "Logo" %>
<%= vite_image_tag "icons/menu.svg", alt: "Menu", class: "icon", size: "24x24" %>
<%= vite_image_tag "photos/hero.jpg", alt: "Hero", data: { controller: "lightbox" } %>

vite_image_path(source)

Returns the resolved URL for an image.

<%= vite_image_path "logo.png" %>
# => "http://localhost:5173/app/assets/images/logo.png" (dev)
# => "/assets/logo-abc123.png" (prod)

Detection Helpers

vite_development?

Returns true if in development environment AND Vite dev server is running.

<% if vite_development? %>
  <%= javascript_tag nonce: true do %>
    console.log("Development mode with HMR enabled");
  <% end %>
<% end %>

vite_dev_server_running?

Returns true if the Vite dev server is responding. Result is cached.

if vite_dev_server_running?
  # Dev server is active
end

Cache Management

reset_vite_dev_server_cache!

Clears the cached dev server status. Useful in tests.

reset_vite_manifest_cache!

Clears the cached manifest. Useful when manifest changes during runtime.

Development

bundle install
bundle exec rspec           # Run tests
bin/rubocop -a              # Lint and auto-fix

License

The gem is available as open source under the terms of the MIT License.