Search code examples
javascriptruby-on-railsrubydockervite

Why is hot reloading not working in Vite + Rails?


I created a rails app, and installed vite_rails gem. My javascript is in app/frontend folder.

However, hot reloading when I save a JS file is not working. Even more, Vite takes 4 seconds to transform my short code! That is tedious when making many changes to javascript files, and having to wait that long.

I also tried by installing vite-plugin-full-reload NPM package. This is my config for vite:

// vite.config.js
import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import FullReload from 'vite-plugin-full-reload'
import RubyPlugin from 'vite-plugin-ruby'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [
    RubyPlugin(),
    vue(),
    FullReload(['config/routes.rb', 'app/views/**/*', 'app/frontend/**/*']),
  ],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./app/frontend/internal', import.meta.url)),
    },
  },
})

Docker config:

# docker-compose.yml
services:
  db:
    image: postgres
    env_file: .env.development
  web:
    image: rails
    build: .
    volumes:
      - .:/app
    ports:
      - "3000:3000"
    depends_on:
      - db
    env_file: .env.development
FROM ruby:3.3

RUN apt-get update -qq && apt-get install -y build-essential apt-utils libpq-dev nodejs npm

COPY . /app
WORKDIR /app

RUN gem install bundler rails && bundle

CMD rm tmp/pids/server.pid && rails s -b 0.0.0.0

Still not reloading, why?


Solution

  • I solved it by adding a node docker container.

    vite.config.js

    import { defineConfig } from 'vite'
    import RubyPlugin from 'vite-plugin-ruby'
    
    export default defineConfig({
      plugins: [
        RubyPlugin(),
      ],
    })
    

    docker-compose.yml

    version: "3.9"
    services:
      backend:
        image: rails-monolith
        build:
          context: .
          dockerfile: development.Dockerfile
        depends_on:
          - frontend
        volumes:
          - .:/app
        ports:
          - 3000:3000
        env_file: .env.development
      frontend:
        image: vite
        build:
          context: .
          dockerfile: vite.Dockerfile
        env_file: .env.development
        ports:
          - 5173:5173
        volumes:
          - .:/app
    

    vite.Dockerfile

    FROM node:20-bookworm
    
    WORKDIR /app
    
    COPY package.json /app/package.json
    COPY package-lock.json /app/package-lock.json
    RUN npm install
    
    COPY docker-vite.sh /usr/bin/entrypoint.sh
    RUN chmod +x /usr/bin/entrypoint.sh
    ENTRYPOINT ["entrypoint.sh"]
    CMD npm run dev
    

    docker-vite.sh

    #!/bin/bash
    set -e
    
    npm install
    
    # Then exec the container's main process (what's set as CMD in the Dockerfile).
    exec "$@"
    

    .env.development

    RAILS_ENV=development
    
    VITE_RUBY_HOST=frontend
    VITE_RUBY_PORT=5173
    

    package.json

    {
      "private": true,
      "type": "module",
      "scripts": {
        "dev": "vite --host",
        "build": "vite build",
        "preview": "vite preview"
      },
      "devDependencies": {
        "vite": "^5.2.11",
        "vite-plugin-ruby": "^5.0.0"
      }
    }