rails_vite 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -0
- data/README.md +11 -2
- data/lib/rails_vite/auto_build.rb +57 -8
- data/lib/rails_vite/config.rb +5 -1
- data/lib/rails_vite/engine.rb +1 -1
- data/lib/rails_vite/errors.rb +13 -0
- data/lib/rails_vite/manifest.rb +9 -1
- data/lib/rails_vite/version.rb +1 -1
- data/lib/tasks/rails_vite/build.rake +10 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fc4469f0512e076ff2acb18a110d7b346082837a0b46ef4d7369907df851883d
|
|
4
|
+
data.tar.gz: f6e624fcb760ca2b5d61c2a7954d98c491f3150a44a735cc1d62de21b2692763
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c46090d913dd40e3fd9e9c78b3010917463ce9a3fc297c810d7f2f5fd7418298299d1a8e7c165bb96e44a4685b611323ce173f1ab26cda04d98d8f3584298691
|
|
7
|
+
data.tar.gz: 2f092d13f0a7d3ff5d25ada3faf133d77fc4e660e376ff5c6301168fd68980b0b84b4cfdee1fbdaf6f8d18db49b8cdc536ca1a080b03a493309bad270402acdf
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,23 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog],
|
|
6
6
|
and this project adheres to [Semantic Versioning].
|
|
7
7
|
|
|
8
|
+
## rails_vite@0.4.0 / rails-vite-plugin@0.4.0 - 2026-11-12
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- `rake vite:auto_build` builds stale assets the way auto build does, so a parallel test runner can build once before it starts its workers. `RailsVite::AutoBuild.build_if_stale` does the same from Ruby. Both do nothing when assets are fresh, and fail with `RailsVite::BuildError` when the build fails (#59) ([@brodienguyen])
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- `RailsVite.digest` is computed once outside development and test, instead of hashing the manifest file on every call (#57) ([@thomasklemm])
|
|
17
|
+
- A failed auto build raises `RailsVite::BuildError` instead of logging and serving the previous assets, and a process does not run it again until a source changes or `rake vite:build` writes a fresh manifest (#59) ([@brodienguyen])
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- `bin/rails test` keeps the test environment's `eager_load` setting. The `test:prepare` build loaded the app through Rake's `environment` task, which turned eager loading off for the whole run (#62) ([@skryukov])
|
|
22
|
+
- Auto build no longer walks the whole Rails root when Vite's `root` is the source directory (`prependSourceDirToEntries: false`). `log/` and `tmp/` made assets look stale on every request. The plugin now also writes the source directory to its metadata as `sourcePath`, and auto build watches it. Upgrade `rails-vite-plugin` together with the gem: metadata from older plugin versions has no `sourcePath`, so auto build falls back to `sourceDir` (#61) ([@mdesantis])
|
|
23
|
+
- Auto builds hold a file lock in `tmp/`, so parallel test workers and a server beside a test run no longer build into the same directory at once. The first process to find stale assets builds them, and the others wait and reuse that build (#59) ([@brodienguyen])
|
|
24
|
+
|
|
8
25
|
## rails_vite@0.3.0 / rails-vite-plugin@0.3.0 - 2026-10-11
|
|
9
26
|
|
|
10
27
|
### Added
|
|
@@ -128,6 +145,8 @@ and this project adheres to [Semantic Versioning].
|
|
|
128
145
|
[@cole-robertson]: https://github.com/cole-robertson
|
|
129
146
|
[@madogiwa0124]: https://github.com/madogiwa0124
|
|
130
147
|
[@janko]: https://github.com/janko
|
|
148
|
+
[@thomasklemm]: https://github.com/thomasklemm
|
|
149
|
+
[@mdesantis]: https://github.com/mdesantis
|
|
131
150
|
|
|
132
151
|
[Keep a Changelog]: https://keepachangelog.com/en/1.0.0/
|
|
133
152
|
[Semantic Versioning]: https://semver.org/spec/v2.0.0.html
|
data/README.md
CHANGED
|
@@ -374,7 +374,15 @@ Rails.application.config.rails_vite.auto_build = false
|
|
|
374
374
|
|
|
375
375
|
By default, auto build is enabled in development and test (`Rails.env.local?`).
|
|
376
376
|
|
|
377
|
-
|
|
377
|
+
Auto builds hold a file lock in `tmp/`, so parallel test workers and a server beside a test run never build at once: the first process to find stale assets builds them, and the others wait and reuse that build. A failed build raises `RailsVite::BuildError`, and a process does not retry it until a source changes.
|
|
378
|
+
|
|
379
|
+
A parallel test runner can build once before it starts its workers, so no worker spends its first test waiting for the build. `rake vite:auto_build` runs the same check, lock and build as the middleware: it builds only when sources changed, does nothing while the dev server runs or with auto build off, and fails with `RailsVite::BuildError` when the build fails. Run it in the environment the workers use:
|
|
380
|
+
|
|
381
|
+
```bash
|
|
382
|
+
RAILS_ENV=test bin/rails vite:auto_build && bundle exec parallel_rspec
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
From Ruby, for example in a script that starts the workers itself, call `RailsVite::AutoBuild.build_if_stale`.
|
|
378
386
|
|
|
379
387
|
## CDN
|
|
380
388
|
|
|
@@ -431,6 +439,7 @@ Defaults match the plugin defaults — no config needed if you follow convention
|
|
|
431
439
|
| Task | Description |
|
|
432
440
|
|------|-------------|
|
|
433
441
|
| `rake vite:build` | Build assets for production |
|
|
442
|
+
| `rake vite:auto_build` | Build assets only if sources changed, as [auto build](#auto-build) does |
|
|
434
443
|
| `rake vite:install` | Install JavaScript dependencies |
|
|
435
444
|
| `rake vite:clobber` | Remove `public/vite/` |
|
|
436
445
|
|
|
@@ -533,7 +542,7 @@ In development, jsbundling mode writes `tmp/rails-vite.json` — the same file t
|
|
|
533
542
|
```json
|
|
534
543
|
// package.json — replace vite-plugin-ruby with rails-vite-plugin
|
|
535
544
|
- "vite-plugin-ruby": "^5.1.1"
|
|
536
|
-
+ "rails-vite-plugin": "^0.
|
|
545
|
+
+ "rails-vite-plugin": "^0.4.0"
|
|
537
546
|
```
|
|
538
547
|
|
|
539
548
|
### 2. Replace `vite.config.ts`
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
require "fileutils"
|
|
1
2
|
require "find"
|
|
2
3
|
|
|
3
4
|
module RailsVite
|
|
@@ -5,6 +6,17 @@ module RailsVite
|
|
|
5
6
|
NEVER = Time.at(0).freeze
|
|
6
7
|
SOURCE_CHECK_INTERVAL = 2 # seconds
|
|
7
8
|
|
|
9
|
+
# Auto build runs when it is on and no dev server serves the assets.
|
|
10
|
+
def self.enabled?(config)
|
|
11
|
+
config.auto_build? && !config.dev_server_running?
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Builds stale assets outside a request, as the middleware does on the
|
|
15
|
+
# first one; for example, before a test runner starts its workers.
|
|
16
|
+
def self.build_if_stale(config = RailsVite.config)
|
|
17
|
+
new(nil, config).build_if_stale if enabled?(config)
|
|
18
|
+
end
|
|
19
|
+
|
|
8
20
|
def initialize(app, config)
|
|
9
21
|
@app = app
|
|
10
22
|
@config = config
|
|
@@ -14,30 +26,67 @@ module RailsVite
|
|
|
14
26
|
end
|
|
15
27
|
|
|
16
28
|
def call(env)
|
|
17
|
-
|
|
29
|
+
build_if_stale
|
|
18
30
|
@app.call(env)
|
|
19
31
|
end
|
|
20
32
|
|
|
33
|
+
# Builds the assets when a source is newer than the manifest, or waits for
|
|
34
|
+
# another process's build. Raises BuildError when the build fails.
|
|
35
|
+
def build_if_stale
|
|
36
|
+
build! if stale?
|
|
37
|
+
end
|
|
38
|
+
|
|
21
39
|
private
|
|
22
40
|
|
|
23
41
|
def build!
|
|
24
42
|
@mutex.synchronize do
|
|
25
43
|
return unless stale?
|
|
26
44
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
45
|
+
with_build_lock do
|
|
46
|
+
# Another process may have finished a build while this one waited.
|
|
47
|
+
return unless stale?
|
|
48
|
+
|
|
49
|
+
sources = compute_latest_source_mtime
|
|
50
|
+
raise BuildError.new(skipped: true) if @failed_sources == sources
|
|
51
|
+
|
|
52
|
+
# Build quietly: vite's per-build summary is noise on every auto-build
|
|
53
|
+
# (e.g. each local system-test run). Warnings and errors still stream.
|
|
54
|
+
next if system(RailsVite::Tasks.build_env, "#{RailsVite::Tasks.build_command} --logLevel warn", chdir: Rails.root)
|
|
55
|
+
|
|
56
|
+
# Remember the failure for these sources, so this process does not
|
|
57
|
+
# rebuild them until a source changes.
|
|
58
|
+
@failed_sources = sources
|
|
59
|
+
raise BuildError
|
|
60
|
+
end
|
|
61
|
+
@failed_sources = nil
|
|
30
62
|
@cached_source_mtime = nil
|
|
31
63
|
@source_mtime_checked_at = nil
|
|
32
64
|
end
|
|
33
65
|
end
|
|
34
66
|
|
|
67
|
+
# Serializes builds across processes (parallel test workers, a server
|
|
68
|
+
# beside a test run): Vite empties the build directory first, so the lock
|
|
69
|
+
# lives outside it.
|
|
70
|
+
def with_build_lock
|
|
71
|
+
path = Rails.root.join("tmp", "rails-vite-build-#{@config.build_dir}.lock")
|
|
72
|
+
FileUtils.mkdir_p(path.dirname)
|
|
73
|
+
File.open(path, File::RDWR | File::CREAT, 0o644) do |lock|
|
|
74
|
+
lock.flock(File::LOCK_EX)
|
|
75
|
+
yield
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
35
79
|
def stale?
|
|
36
80
|
# The manifest file's mtime is our persisted "last build" timestamp: it
|
|
37
81
|
# lives on disk, so freshness survives process restarts (e.g. a new Rails
|
|
38
|
-
# process per local system-test run) without any extra state.
|
|
39
|
-
|
|
40
|
-
|
|
82
|
+
# process per local system-test run) without any extra state. A missing
|
|
83
|
+
# manifest is stale, including one another process's build has just
|
|
84
|
+
# removed: Vite empties the build directory first, so it can vanish
|
|
85
|
+
# between any check and the read. Stale takes the build lock, which
|
|
86
|
+
# waits for that build and then checks again.
|
|
87
|
+
latest_source_mtime > File.mtime(@config.manifest_path)
|
|
88
|
+
rescue Errno::ENOENT
|
|
89
|
+
true
|
|
41
90
|
end
|
|
42
91
|
|
|
43
92
|
def latest_source_mtime
|
|
@@ -52,7 +101,7 @@ module RailsVite
|
|
|
52
101
|
|
|
53
102
|
def compute_latest_source_mtime
|
|
54
103
|
latest = NEVER
|
|
55
|
-
source_path = Rails.root.join(@config.
|
|
104
|
+
source_path = Rails.root.join(@config.source_path).to_s
|
|
56
105
|
|
|
57
106
|
Find.find(source_path, *auto_build_path_matches) do |path|
|
|
58
107
|
next unless File.file?(path)
|
data/lib/rails_vite/config.rb
CHANGED
|
@@ -34,6 +34,10 @@ module RailsVite
|
|
|
34
34
|
plugin_meta["sourceDir"] || "app/javascript"
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
+
def source_path
|
|
38
|
+
plugin_meta["sourcePath"].presence || source_dir
|
|
39
|
+
end
|
|
40
|
+
|
|
37
41
|
def entrypoints_dir
|
|
38
42
|
plugin_meta["entrypointsDir"]
|
|
39
43
|
end
|
|
@@ -44,7 +48,7 @@ module RailsVite
|
|
|
44
48
|
end
|
|
45
49
|
|
|
46
50
|
# Paths or globs relative to Rails.root that auto build checks for changes,
|
|
47
|
-
# in addition to
|
|
51
|
+
# in addition to source_path. Directories are walked recursively.
|
|
48
52
|
def auto_build_paths
|
|
49
53
|
@auto_build_paths ||= [
|
|
50
54
|
"vite.config.*",
|
data/lib/rails_vite/engine.rb
CHANGED
|
@@ -6,7 +6,7 @@ module RailsVite
|
|
|
6
6
|
|
|
7
7
|
initializer "rails_vite.auto_build", after: :load_config_initializers do |app|
|
|
8
8
|
vite_config = RailsVite.config
|
|
9
|
-
if
|
|
9
|
+
if RailsVite::AutoBuild.enabled?(vite_config)
|
|
10
10
|
app.middleware.use RailsVite::AutoBuild, vite_config
|
|
11
11
|
end
|
|
12
12
|
end
|
data/lib/rails_vite/errors.rb
CHANGED
|
@@ -12,6 +12,19 @@ module RailsVite
|
|
|
12
12
|
end
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
+
class BuildError < Error
|
|
16
|
+
# skipped: Vite did not run because these sources already failed to build
|
|
17
|
+
# in an earlier request, so its errors are not in this output.
|
|
18
|
+
def initialize(skipped: false)
|
|
19
|
+
message = if skipped
|
|
20
|
+
"Vite auto build failed earlier for these sources and is not retried until a source changes or the app restarts. Run `rake vite:build` to see its errors."
|
|
21
|
+
else
|
|
22
|
+
"Vite auto build failed; its errors are in the output above. It retries once a source changes, or run `rake vite:build`."
|
|
23
|
+
end
|
|
24
|
+
super(message)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
15
28
|
class MissingEntryError < Error
|
|
16
29
|
def initialize(name, path)
|
|
17
30
|
super("Entry \"#{name}\" not found in Vite manifest at #{path}.")
|
data/lib/rails_vite/manifest.rb
CHANGED
|
@@ -32,7 +32,11 @@ module RailsVite
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def digest
|
|
35
|
-
|
|
35
|
+
if Rails.env.local?
|
|
36
|
+
load_digest
|
|
37
|
+
else
|
|
38
|
+
@digest ||= load_digest
|
|
39
|
+
end
|
|
36
40
|
rescue Errno::ENOENT
|
|
37
41
|
NO_MANIFEST_DIGEST
|
|
38
42
|
end
|
|
@@ -47,6 +51,10 @@ module RailsVite
|
|
|
47
51
|
end
|
|
48
52
|
end
|
|
49
53
|
|
|
54
|
+
def load_digest
|
|
55
|
+
Digest::MD5.file(@path).hexdigest
|
|
56
|
+
end
|
|
57
|
+
|
|
50
58
|
def load_manifest
|
|
51
59
|
JSON.parse(File.read(@path))
|
|
52
60
|
rescue Errno::ENOENT
|
data/lib/rails_vite/version.rb
CHANGED
|
@@ -13,6 +13,15 @@ namespace :vite do
|
|
|
13
13
|
|
|
14
14
|
Rake::Task["vite:build"].prereqs << :install unless ENV["SKIP_VITE_INSTALL"]
|
|
15
15
|
|
|
16
|
+
desc "Build Vite assets the way auto build does, only if sources changed"
|
|
17
|
+
task auto_build: :environment do
|
|
18
|
+
RailsVite::AutoBuild.build_if_stale
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
task :keep_eager_load do
|
|
22
|
+
ActiveSupport.on_load(:before_initialize) { config.rake_eager_load = config.eager_load }
|
|
23
|
+
end
|
|
24
|
+
|
|
16
25
|
desc "Remove Vite build artifacts"
|
|
17
26
|
task :clobber do
|
|
18
27
|
rm_rf Rails.root.join("public", RailsVite.config.asset_prefix.delete_prefix("/"))
|
|
@@ -36,7 +45,7 @@ unless ENV["SKIP_VITE_BUILD"]
|
|
|
36
45
|
|
|
37
46
|
%w[test:prepare spec:prepare db:test:prepare].each do |t|
|
|
38
47
|
if Rake::Task.task_defined?(t)
|
|
39
|
-
Rake::Task[t].enhance(["vite:build"])
|
|
48
|
+
Rake::Task[t].enhance(["vite:keep_eager_load", "vite:build"])
|
|
40
49
|
break
|
|
41
50
|
end
|
|
42
51
|
end
|