Skip to content

Commit

Permalink
Replace the asset pipeline with Vite in app/frontend
Browse files Browse the repository at this point in the history
- Remove esbuild
- Install the vite_rails gem
- Move asset pipeline files into app/frontend
- Run the vite installer
- Replace vite-plugin-ruby with vite-plugin-rails
- Move vite package from devDependencies to dependencies
- Install autoprefixer
- Disable autoBuild in test environment
- Install modern-normalize and base stylesheets
- Configure turbo/stimulus
- Add InlineSvgHelper
- Add a `bin/dev` script that uses run-pty
- Add Safari cache workaround in development
- Remove jsbundling-rails
- Remove sprockets
- Add Node steps to CI workflow
  • Loading branch information
jarodtaylor committed Sep 15, 2024
1 parent c3afde2 commit d420b94
Show file tree
Hide file tree
Showing 35 changed files with 904 additions and 183 deletions.
9 changes: 9 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,15 @@ jobs:
ruby-version: .ruby-version
bundler-cache: true

- name: Set up Node
uses: actions/setup-node@v4
with:
node-version-file: ".node-version"
cache: yarn

- name: Install Yarn packages
run: npx --yes ci

- name: Run tests
env:
RAILS_ENV: test
Expand Down
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,11 @@

/node_modules
node_modules/

# Vite Ruby
/public/vite*
node_modules
# Vite uses dotenv and suggests to ignore local-only env files. See
# https://vitejs.dev/guide/env-and-mode.html#env-files
*.local

2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
source "https://rubygems.org"

gem "vite_rails", "~> 3.0"
gem "rails", "~> 7.2.1"
gem "pg", "~> 1.1"
gem "puma", ">= 5.0"
gem "jsbundling-rails"
gem "turbo-rails"
gem "stimulus-rails"
gem "jbuilder"
Expand Down
14 changes: 11 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ GEM
irb (~> 1.10)
reline (>= 0.3.8)
drb (2.2.1)
dry-cli (1.1.0)
erubi (1.13.0)
globalid (1.2.1)
activesupport (>= 6.1)
Expand All @@ -111,8 +112,6 @@ GEM
jbuilder (2.13.0)
actionview (>= 5.0.0)
activesupport (>= 5.0.0)
jsbundling-rails (1.3.1)
railties (>= 6.0.0)
json (2.7.2)
language_server-protocol (3.17.0.3)
logger (1.6.1)
Expand Down Expand Up @@ -163,6 +162,8 @@ GEM
nio4r (~> 2.0)
racc (1.8.1)
rack (3.1.7)
rack-proxy (0.7.7)
rack
rack-session (2.0.0)
rack (>= 3.0.0)
rack-test (2.1.0)
Expand Down Expand Up @@ -257,6 +258,13 @@ GEM
concurrent-ruby (~> 1.0)
unicode-display_width (2.6.0)
useragent (0.16.10)
vite_rails (3.0.17)
railties (>= 5.1, < 8)
vite_ruby (~> 3.0, >= 3.2.2)
vite_ruby (3.8.2)
dry-cli (>= 0.7, < 2)
rack-proxy (~> 0.6, >= 0.6.1)
zeitwerk (~> 2.2)
web-console (4.2.1)
actionview (>= 6.0.0)
activemodel (>= 6.0.0)
Expand Down Expand Up @@ -285,7 +293,6 @@ DEPENDENCIES
capybara
debug
jbuilder
jsbundling-rails
pg (~> 1.1)
puma (>= 5.0)
rails (~> 7.2.1)
Expand All @@ -294,6 +301,7 @@ DEPENDENCIES
stimulus-rails
turbo-rails
tzinfo-data
vite_rails (~> 3.0)
web-console

BUNDLED WITH
Expand Down
2 changes: 0 additions & 2 deletions Procfile.dev

This file was deleted.

Empty file removed app/assets/images/.keep
Empty file.
1 change: 0 additions & 1 deletion app/assets/stylesheets/application.css

This file was deleted.

File renamed without changes.
5 changes: 5 additions & 0 deletions app/frontend/controllers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { application } from "./application";
import { registerControllers } from "stimulus-vite-helpers";

const controllers = import.meta.glob("./**/*_controller.js", { eager: true });
registerControllers(application, controllers);
31 changes: 31 additions & 0 deletions app/frontend/entrypoints/application.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import "~/stylesheets/index.css";
import "~/controllers";
import "@hotwired/turbo-rails";
// To see this message, add the following to the `<head>` section in your
// views/layouts/application.html.erb
//
// <%= vite_client_tag %>
// <%= vite_javascript_tag 'application' %>
console.log('Vite ⚡️ Rails')

// If using a TypeScript entrypoint file:
// <%= vite_typescript_tag 'application' %>
//
// If you want to use .jsx or .tsx, add the extension:
// <%= vite_javascript_tag 'application.jsx' %>

console.log('Visit the guide for more information: ', 'https://vite-ruby.netlify.app/guide/rails')

// Example: Load Rails libraries in Vite.
//
// import * as Turbo from '@hotwired/turbo'
// Turbo.start()
//
// import ActiveStorage from '@rails/activestorage'
// ActiveStorage.start()
//
// // Import all channels.
// const channels = import.meta.globEager('./**/*_channel.js')

// Example: Import a stylesheet in app/frontend/index.css
// import '~/index.css'
File renamed without changes.
3 changes: 3 additions & 0 deletions app/frontend/images/example.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions app/frontend/stylesheets/base.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
This file is for base element styles, like:
- Any @font-face declarations needed custom web fonts.
- Default font-family on the body element.
- Default foreground, background, and link colors.
- Global CSS variables (declared on :root), such as color palette.
*/
3 changes: 3 additions & 0 deletions app/frontend/stylesheets/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@import "modern-normalize";
@import "reset";
@import "base";
36 changes: 36 additions & 0 deletions app/frontend/stylesheets/reset.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
:root {
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
h4,
h5,
figure,
p,
ol,
ul {
margin: 0;
}

ol,
ul {
list-style: none;
padding-inline: 0;
}

h1,
h2,
h3,
h4,
h5 {
font-size: inherit;
font-weight: inherit;
}

img {
display: block;
max-inline-size: 100%;
}
11 changes: 11 additions & 0 deletions app/helpers/inline_svg_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

module InlineSvgHelper
def inline_svg_tag(filename, title: nil)
svg = ViteInlineSvgFileLoader.named(filename)
svg = svg.sub(/\A<svg/, '<svg role="img"')
svg = svg.sub(/\A<svg.*?>/, safe_join(['\0', "\n", tag.title(title)])) if title.present?

svg.strip.html_safe # rubocop:disable Rails/OutputSafety
end
end
3 changes: 0 additions & 3 deletions app/javascript/application.js

This file was deleted.

8 changes: 0 additions & 8 deletions app/javascript/controllers/index.js

This file was deleted.

14 changes: 13 additions & 1 deletion app/views/layouts/application.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,20 @@
<link rel="icon" href="/icon.png" type="image/png">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/icon.png">
<%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>

<%= javascript_include_tag "application", "data-turbo-track": "reload", type: "module" %>
<%= vite_client_tag %>
<%= vite_javascript_tag "application", "data-turbo-track": "reload" %>
<!--
If using a TypeScript entrypoint file:
vite_typescript_tag 'application'
If using a .jsx or .tsx entrypoint, add the extension:
vite_javascript_tag 'application.jsx'
Visit the guide for more information: https://vite-ruby.netlify.app/guide/rails
-->

</head>

<body>
Expand Down
13 changes: 3 additions & 10 deletions bin/dev
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
#!/usr/bin/env sh
#!/usr/bin/env ruby
# frozen_string_literal: true

if gem list --no-installed --exact --silent foreman; then
echo "Installing foreman..."
gem install foreman
fi

# Default to port 3000 if not specified
export PORT="${PORT:-3000}"

exec foreman start -f Procfile.dev --env /dev/null "$@"
exec "npx", "run-pty", "run-pty.json", *ARGV
27 changes: 27 additions & 0 deletions bin/vite
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

#
# This file was generated by Bundler.
#
# The application 'vite' is installed as part of a gem, and
# this file is here to facilitate running it.
#

ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)

bundle_binstub = File.expand_path("bundle", __dir__)

if File.file?(bundle_binstub)
if File.read(bundle_binstub, 300).include?("This file was generated by Bundler")
load(bundle_binstub)
else
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
end
end

require "rubygems"
require "bundler/setup"

load Gem.bin_path("vite_ruby", "vite")
3 changes: 3 additions & 0 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

module RorViteTailwind
class Application < Rails::Application
# Prevents Rails from trying to eager-load the contents of app/frontend
config.javascript_path = "frontend"

# Initialize configuration defaults for originally generated Rails version.
config.load_defaults 7.2

Expand Down
4 changes: 4 additions & 0 deletions config/environments/development.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,8 @@

# Apply autocorrection by RuboCop to files generated by `bin/rails generate`.
# config.generators.apply_rubocop_autocorrect_after_generate!

# Disable `Link: ... rel=preload` header to work around Safari caching bug
# https://bugs.webkit.org/show_bug.cgi?id=193533
config.action_view.preload_links_header = false
end
9 changes: 9 additions & 0 deletions config/initializers/content_security_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,16 @@
# policy.img_src :self, :https, :data
# policy.object_src :none
# policy.script_src :self, :https
# Allow @vite/client to hot reload javascript changes in development
# policy.script_src *policy.script_src, :unsafe_eval, "http://#{ ViteRuby.config.host_with_port }" if Rails.env.development?

# You may need to enable this in production as well depending on your setup.
# policy.script_src *policy.script_src, :blob if Rails.env.test?

# policy.style_src :self, :https
# Allow @vite/client to hot reload style changes in development
# policy.style_src *policy.style_src, :unsafe_inline if Rails.env.development?

# # Specify URI for violation reports
# # policy.report_uri "/csp-violation-report-endpoint"
# end
Expand Down
16 changes: 16 additions & 0 deletions config/vite.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"all": {
"sourceCodeDir": "app/frontend",
"watchAdditionalPaths": []
},
"development": {
"autoBuild": true,
"publicOutputDir": "vite-dev",
"port": 3036
},
"test": {
"autoBuild": false,
"publicOutputDir": "vite-test",
"port": 3037
}
}
27 changes: 27 additions & 0 deletions lib/vite_inline_svg_file_loader.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

module ViteInlineSvgFileLoader
class << self
def named(filename)
vite = ViteRuby.instance
vite_asset_path = vite.manifest.path_for(filename)

if vite.dev_server_running?
fetch_from_dev_server(vite_asset_path)
else
Rails.public_path.join(vite_asset_path.sub(%r{^/}, "")).read
end
end

private

def fetch_from_dev_server(path)
config = ViteRuby.config
dev_server_uri = URI("#{config.protocol}://#{config.host_with_port}#{path}")
response = Net::HTTP.get_response(dev_server_uri)
raise "Failed to load inline SVG from #{dev_server_uri}" unless response.is_a?(Net::HTTPSuccess)

response.body
end
end
end
19 changes: 12 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@
"engines": {
"node": "^18.12.0 || >= 20.0.0"
},
"devDependencies": {
"esbuild": "^0.23.1"
},
"scripts": {
"build": "esbuild app/javascript/*.* --bundle --sourcemap --format=esm --outdir=app/assets/builds --public-path=/assets"
},
"scripts": {},
"dependencies": {
"@hotwired/stimulus": "^3.2.2",
"@hotwired/turbo-rails": "^8.0.9"
"@hotwired/turbo-rails": "^8.0.9",
"autoprefixer": "^10.4.14",
"modern-normalize": "^3.0.0",
"postcss": "^8.4.24",
"rollup": "^4.2.0",
"stimulus-vite-helpers": "^3.1.0",
"vite": "^5.0.0",
"vite-plugin-rails": "^0.5.0"
},
"devDependencies": {
"run-pty": "^5"
}
}
3 changes: 3 additions & 0 deletions postcss.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
plugins: [require("autoprefixer")],
};
Loading

0 comments on commit d420b94

Please sign in to comment.