vite_rails 1.0.11 → 2.0.3

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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -0
  3. data/README.md +52 -34
  4. data/lib/tasks/vite.rake +17 -0
  5. data/lib/vite_rails.rb +5 -82
  6. data/lib/vite_rails/config.rb +11 -130
  7. data/lib/vite_rails/engine.rb +7 -11
  8. data/lib/vite_rails/installation.rb +52 -0
  9. data/lib/vite_rails/tag_helpers.rb +61 -0
  10. data/lib/vite_rails/version.rb +2 -2
  11. data/{lib/install/config/vite.json → templates/config/rails-vite.json} +1 -0
  12. data/{lib/install/javascript → templates}/entrypoints/application.js +0 -0
  13. metadata +27 -166
  14. data/CONTRIBUTING.md +0 -33
  15. data/lib/install/bin/vite +0 -17
  16. data/lib/install/binstubs.rb +0 -6
  17. data/lib/install/config/vite.config.ts +0 -11
  18. data/lib/install/template.rb +0 -40
  19. data/lib/tasks/vite/binstubs.rake +0 -12
  20. data/lib/tasks/vite/build.rake +0 -39
  21. data/lib/tasks/vite/clean.rake +0 -23
  22. data/lib/tasks/vite/clobber.rake +0 -20
  23. data/lib/tasks/vite/info.rake +0 -20
  24. data/lib/tasks/vite/install.rake +0 -12
  25. data/lib/tasks/vite/install_dependencies.rake +0 -14
  26. data/lib/tasks/vite/verify_install.rake +0 -23
  27. data/lib/vite_rails/builder.rb +0 -111
  28. data/lib/vite_rails/commands.rb +0 -109
  29. data/lib/vite_rails/dev_server.rb +0 -23
  30. data/lib/vite_rails/dev_server_proxy.rb +0 -57
  31. data/lib/vite_rails/helper.rb +0 -71
  32. data/lib/vite_rails/manifest.rb +0 -140
  33. data/lib/vite_rails/runner.rb +0 -53
  34. data/package.json +0 -19
  35. data/package/default.vite.json +0 -16
  36. data/test/builder_test.rb +0 -77
  37. data/test/commands_test.rb +0 -67
  38. data/test/config_test.rb +0 -133
  39. data/test/dev_server_proxy_test.rb +0 -102
  40. data/test/dev_server_test.rb +0 -9
  41. data/test/engine_rake_tasks_test.rb +0 -81
  42. data/test/helper_test.rb +0 -70
  43. data/test/manifest_test.rb +0 -79
  44. data/test/mode_test.rb +0 -16
  45. data/test/mounted_app/Rakefile +0 -6
  46. data/test/mounted_app/test/dummy/Rakefile +0 -5
  47. data/test/mounted_app/test/dummy/bin/rails +0 -5
  48. data/test/mounted_app/test/dummy/bin/rake +0 -5
  49. data/test/mounted_app/test/dummy/config.ru +0 -7
  50. data/test/mounted_app/test/dummy/config/application.rb +0 -12
  51. data/test/mounted_app/test/dummy/config/environment.rb +0 -5
  52. data/test/mounted_app/test/dummy/config/vite.json +0 -14
  53. data/test/mounted_app/test/dummy/package.json +0 -8
  54. data/test/mounted_app/test/dummy/yarn.lock +0 -208
  55. data/test/rake_tasks_test.rb +0 -60
  56. data/test/runner_test.rb +0 -31
  57. data/test/test_app/Rakefile +0 -5
  58. data/test/test_app/app/frontend/entrypoints/application.js +0 -2
  59. data/test/test_app/bin/vite +0 -17
  60. data/test/test_app/config.ru +0 -7
  61. data/test/test_app/config/application.rb +0 -13
  62. data/test/test_app/config/environment.rb +0 -6
  63. data/test/test_app/config/vite.json +0 -18
  64. data/test/test_app/config/vite_additional_paths.json +0 -5
  65. data/test/test_app/config/vite_public_dir.json +0 -5
  66. data/test/test_app/package.json +0 -13
  67. data/test/test_app/public/vite-production/manifest.json +0 -22
  68. data/test/test_app/some.config.js +0 -0
  69. data/test/test_app/yarn.lock +0 -11
  70. data/test/test_helper.rb +0 -68
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- say 'Copying binstubs'
4
- directory "#{ __dir__ }/bin", 'bin'
5
-
6
- chmod 'bin', 0o755 & ~File.umask, verbose: false
@@ -1,11 +0,0 @@
1
- import { defineConfig } from 'vite'
2
- import RubyPlugin from 'vite-plugin-ruby'
3
-
4
- export default defineConfig({
5
- plugins: [
6
- RubyPlugin(),
7
- ],
8
- optimizeDeps: {
9
- exclude: [/webpack/], // In case webpacker is installed (these deps won't be imported)
10
- },
11
- })
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Install Vite Rails
4
- say 'Creating configuration files'
5
- copy_file "#{ __dir__ }/config/vite.json", ViteRails.config.config_path
6
- copy_file "#{ __dir__ }/config/vite.config.ts", Rails.root.join('vite.config.ts')
7
-
8
- say 'Creating entrypoints directory'
9
- directory "#{ __dir__ }/javascript/entrypoints", ViteRails.config.resolved_entrypoints_dir
10
-
11
- apply "#{ __dir__ }/binstubs.rb"
12
-
13
- git_ignore_path = Rails.root.join('.gitignore')
14
- if git_ignore_path.exist?
15
- append_to_file(git_ignore_path) {
16
- <<~GITIGNORE
17
-
18
- # Vite on Rails
19
- /public/vite
20
- /public/vite-dev
21
- /public/vite-test
22
- node_modules
23
- *.local
24
- .DS_Store
25
- GITIGNORE
26
- }
27
- end
28
-
29
- Dir.chdir(Rails.root) do
30
- say 'Installing JavaScript dependencies for Vite Rails'
31
- package_json = File.read("#{ __dir__ }/../../package.json")
32
-
33
- vite_version = package_json.match(/"vite": "(.*)"/)[1]
34
- plugin_version = package_json.match(/"vite-plugin-ruby": "(.*)"/)[1]
35
-
36
- say 'Installing vite as build dependencies'
37
- run "yarn add -D vite@#{ vite_version } vite-plugin-ruby@#{ plugin_version }"
38
- end
39
-
40
- say 'Vite ⚡️ Rails successfully installed! 🎉', :green
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- binstubs_template_path = File.expand_path('../../install/binstubs.rb', __dir__).freeze
4
- bin_path = ENV['BUNDLE_BIN'] || Rails.root.join('bin')
5
-
6
- namespace :vite do
7
- desc 'Installs Vite binstubs in this application'
8
- task :binstubs do |task|
9
- prefix = task.name.split(/#|vite:binstubs/).first
10
- exec "#{ RbConfig.ruby } #{ bin_path }/rails #{ prefix }app:template LOCATION=#{ binstubs_template_path }"
11
- end
12
- end
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- $stdout.sync = true
4
-
5
- def enhance_assets_precompile
6
- # Before installing
7
- ['yarn:install', 'webpacker:yarn_install'].each do |name|
8
- Rake::Task[name].enhance([:'vite:set_node_env']) if Rake::Task.task_defined?(name)
9
- end
10
-
11
- # After precompiling
12
- Rake::Task['assets:precompile'].enhance do |task|
13
- prefix = task.name.split(/#|assets:precompile/).first
14
- Rake::Task["#{ prefix }vite:build"].invoke
15
- end
16
- end
17
-
18
- namespace :vite do
19
- desc 'Fixes Rails management of node dev dependencies (build dependencies)'
20
- task :set_node_env do
21
- ENV['NODE_ENV'] = 'development'
22
- end
23
-
24
- desc 'Compile JavaScript packs using vite for production with digests'
25
- task build: [:'vite:verify_install', :environment] do
26
- ViteRails.build_from_rake
27
- end
28
- end
29
-
30
- # Compile packs after we've compiled all other assets during precompilation
31
- skip_vite_precompile = %w[no false n f].include?(ENV['VITE_RUBY_PRECOMPILE'])
32
-
33
- unless skip_vite_precompile
34
- if Rake::Task.task_defined?('assets:precompile')
35
- enhance_assets_precompile
36
- else
37
- Rake::Task.define_task('assets:precompile' => [:'vite:install_dependencies', :'vite:build'])
38
- end
39
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- $stdout.sync = true
4
-
5
- namespace :vite do
6
- desc 'Remove old compiled vites'
7
- task :clean, [:keep, :age] => [:'vite:verify_install', :environment] do |_, args|
8
- ViteRails.clean_from_rake(args)
9
- end
10
- end
11
-
12
- skip_vite_clean = %w[no false n f].include?(ENV['VITE_RUBY_PRECOMPILE'])
13
-
14
- unless skip_vite_clean
15
- # Run clean if the assets:clean is run
16
- if Rake::Task.task_defined?('assets:clean')
17
- Rake::Task['assets:clean'].enhance do
18
- Rake::Task['vite:clean'].invoke
19
- end
20
- else
21
- Rake::Task.define_task('assets:clean' => 'vite:clean')
22
- end
23
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- namespace :vite do
4
- desc 'Remove the vite build output directory'
5
- task clobber: [:'vite:verify_install', :environment] do
6
- ViteRails.clobber
7
- $stdout.puts "Removed vite build output directory #{ ViteRails.config.build_output_dir }"
8
- end
9
- end
10
-
11
- skip_vite_clobber = %w[no false n f].include?(ENV['VITE_RUBY_PRECOMPILE'])
12
-
13
- unless skip_vite_clobber
14
- # Run clobber if the assets:clobber is run
15
- if Rake::Task.task_defined?('assets:clobber')
16
- Rake::Task['assets:clobber'].enhance do
17
- Rake::Task['vite:clobber'].invoke
18
- end
19
- end
20
- end
@@ -1,20 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- namespace :vite do
4
- desc "Provide information on ViteRails's environment"
5
- task :info do
6
- Dir.chdir(Rails.root) do
7
- $stdout.puts "Ruby: #{ `ruby --version` }"
8
- $stdout.puts "Rails: #{ Rails.version }"
9
- $stdout.puts "ViteRails: #{ ViteRails::VERSION }"
10
- $stdout.puts "Node: #{ `node --version` }"
11
- $stdout.puts "Yarn: #{ `yarn --version` }"
12
-
13
- $stdout.puts "\n"
14
- $stdout.puts "vite-plugin-ruby: \n#{ `npm list vite-plugin-ruby version` }"
15
-
16
- $stdout.puts "Is bin/vite present?: #{ File.exist? 'bin/vite' }"
17
- $stdout.puts "Is bin/yarn present?: #{ File.exist? 'bin/yarn' }"
18
- end
19
- end
20
- end
@@ -1,12 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- install_template_path = File.expand_path('../../install/template.rb', __dir__).freeze
4
- bin_path = ENV['BUNDLE_BIN'] || Rails.root.join('bin')
5
-
6
- namespace :vite do
7
- desc 'Install ViteRails in this application'
8
- task :install do |task|
9
- prefix = task.name.split(/#|vite:install/).first
10
- exec "#{ RbConfig.ruby } #{ bin_path }/rails #{ prefix }app:template LOCATION=#{ install_template_path }"
11
- end
12
- end
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- namespace :vite do
4
- desc 'Install all JavaScript dependencies as specified via Yarn'
5
- task :install_dependencies do
6
- valid_node_envs = %w[test development production]
7
- node_env = ENV.fetch('NODE_ENV') { valid_node_envs.include?(Rails.env) ? Rails.env : 'production' }
8
- Dir.chdir(Rails.root) do
9
- v1 = `yarn --version`.start_with?('1')
10
- install_command = "yarn install #{ v1 ? '--no-progress --frozen-lockfile' : '--immutable' } --production=false"
11
- system({ 'NODE_ENV' => node_env }, install_command)
12
- end
13
- end
14
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- namespace :vite do
4
- desc 'Verifies if Vite Rails is installed'
5
- task :verify_install do
6
- unless File.exist?(Rails.root.join('bin/vite'))
7
- warn <<~WARN
8
- vite binstub not found.
9
- Have you run rails vite:install?
10
- Make sure the bin directory and bin/vite are not included in .gitignore
11
- WARN
12
- exit!
13
- end
14
- config_path = Rails.root.join(ViteRails.config.config_path)
15
- unless config_path.exist?
16
- warn <<~WARN
17
- Configuration #{ config_path } file for vite-plugin-ruby not found.
18
- Make sure vite:install has run successfully before running dependent tasks.
19
- WARN
20
- exit!
21
- end
22
- end
23
- end
@@ -1,111 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'open3'
4
- require 'digest/sha1'
5
-
6
- # Public: Keeps track of watched files and triggers builds as needed.
7
- class ViteRails::Builder
8
- def initialize(vite_rails)
9
- @vite_rails = vite_rails
10
- end
11
-
12
- # Public: Checks if the watched files have changed since the last compilation,
13
- # and triggers a Vite build if any files have changed.
14
- def build
15
- if stale?
16
- build_with_vite.tap { record_files_digest }
17
- else
18
- logger.debug 'Skipping build. Vite assets are already up-to-date ⚡️'
19
- true
20
- end
21
- end
22
-
23
- # Public: Returns true if all the assets built by Vite are up to date.
24
- def fresh?
25
- previous_files_digest&.== watched_files_digest
26
- end
27
-
28
- # Public: Returns true if any of the assets built by Vite is out of date.
29
- def stale?
30
- !fresh?
31
- end
32
-
33
- private
34
-
35
- delegate :config, :logger, to: :@vite_rails
36
-
37
- # Internal: Writes a digest of the watched files to disk for future checks.
38
- def record_files_digest
39
- config.build_cache_dir.mkpath
40
- files_digest_path.write(watched_files_digest)
41
- end
42
-
43
- # Internal: The path of where a digest of the watched files is stored.
44
- def files_digest_path
45
- config.build_cache_dir.join("last-compilation-digest-#{ config.mode }")
46
- end
47
-
48
- # Internal: Reads a digest of watched files from disk.
49
- def previous_files_digest
50
- files_digest_path.read if files_digest_path.exist? && config.manifest_path.exist?
51
- rescue Errno::ENOENT, Errno::ENOTDIR
52
- end
53
-
54
- # Internal: Returns a digest of all the watched files, allowing to detect
55
- # changes, and skip Vite builds if no files have changed.
56
- def watched_files_digest
57
- Dir.chdir File.expand_path(config.root) do
58
- files = Dir[*watched_paths].reject { |f| File.directory?(f) }
59
- file_ids = files.sort.map { |f| "#{ File.basename(f) }/#{ Digest::SHA1.file(f).hexdigest }" }
60
- Digest::SHA1.hexdigest(file_ids.join('/'))
61
- end
62
- end
63
-
64
- # Public: Initiates a Vite build command to generate assets.
65
- #
66
- # Returns true if the build is successful, or false if it failed.
67
- def build_with_vite
68
- logger.info 'Building with Vite ⚡️'
69
-
70
- command = "#{ which_ruby } ./bin/vite build --mode #{ config.mode }"
71
- stdout, stderr, status = Open3.capture3(ViteRails.config.to_env, command, chdir: File.expand_path(config.root))
72
-
73
- log_build_result(stdout, stderr, status)
74
-
75
- status.success?
76
- end
77
-
78
- # Internal: Outputs the build results.
79
- #
80
- # NOTE: By default it also outputs the manifest entries.
81
- def log_build_result(stdout, stderr, status)
82
- if status.success?
83
- logger.info "Build with Vite complete: #{ config.build_output_dir }"
84
- logger.error(stderr.to_s) unless stderr.empty?
85
- logger.info(stdout) unless config.hide_build_console_output
86
- else
87
- non_empty_streams = [stdout, stderr].delete_if(&:empty?)
88
- logger.error "Build with Vite failed:\n#{ non_empty_streams.join("\n\n") }"
89
- end
90
- end
91
-
92
- # Internal: Used to prefix the bin/vite executable file.
93
- def which_ruby
94
- bin_vite_path = config.root.join('bin/vite')
95
- first_line = File.readlines(bin_vite_path).first.chomp
96
- /ruby/.match?(first_line) ? RbConfig.ruby : ''
97
- end
98
-
99
- # Internal: Files and directories that should be watched for changes.
100
- #
101
- # NOTE: You can specify additional ones in vite.json using "watchAdditionalPaths": [...]
102
- def watched_paths
103
- [
104
- *config.watch_additional_paths,
105
- "#{ config.source_code_dir }/**/*",
106
- 'yarn.lock',
107
- 'package.json',
108
- config.config_path,
109
- ].freeze
110
- end
111
- end
@@ -1,109 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Public: Encapsulates common tasks, available both programatically and in Rake.
4
- class ViteRails::Commands
5
- def initialize(vite_rails)
6
- @vite_rails = vite_rails
7
- end
8
-
9
- # Public: Loads the manifest with all the entries compiled by Vite.
10
- def bootstrap
11
- manifest.refresh
12
- end
13
-
14
- # Public: Defaults to production, and exits if the build fails.
15
- def build_from_rake
16
- with_node_env(ENV.fetch('NODE_ENV', 'production')) {
17
- ensure_log_goes_to_stdout {
18
- build || exit!
19
- }
20
- }
21
- end
22
-
23
- # Public: Builds all assets that are managed by Vite, from the entrypoints.
24
- def build
25
- builder.build.tap { manifest.refresh }
26
- end
27
-
28
- # Public: Removes all build cache and previously compiled assets.
29
- def clobber
30
- config.build_output_dir.rmtree if config.build_output_dir.exist?
31
- config.build_cache_dir.rmtree if config.build_cache_dir.exist?
32
- config.vite_cache_dir.rmtree if config.vite_cache_dir.exist?
33
- end
34
-
35
- # Public: Receives arguments from a rake task.
36
- def clean_from_rake(args)
37
- ensure_log_goes_to_stdout {
38
- clean(keep_up_to: Integer(args.keep || 2), age_in_seconds: Integer(args.age || 3600))
39
- }
40
- end
41
-
42
- # Public: Cleanup old assets in the output directory.
43
- #
44
- # keep_up_to - Max amount of backups to preserve.
45
- # age_in_seconds - Amount of time to look back in order to preserve them.
46
- #
47
- # NOTE: By default keeps the last version, or 2 if created in the past hour.
48
- #
49
- # Examples:
50
- # To force only 1 backup to be kept: clean(1, 0)
51
- # To only keep files created within the last 10 minutes: clean(0, 600)
52
- def clean(keep_up_to: 2, age_in_seconds: 3600)
53
- return false unless may_clean?
54
-
55
- versions
56
- .each_with_index
57
- .drop_while { |(mtime, _), index|
58
- max_age = [0, Time.now - Time.at(mtime)].max
59
- max_age < age_in_seconds || index < keep_up_to
60
- }
61
- .each do |(_, files), _|
62
- clean_files(files)
63
- end
64
- true
65
- end
66
-
67
- private
68
-
69
- delegate :config, :builder, :manifest, :logger, to: :@vite_rails
70
-
71
- def may_clean?
72
- config.build_output_dir.exist? && config.manifest_path.exist?
73
- end
74
-
75
- def clean_files(files)
76
- files.select { |file| File.file?(file) }.each do |file|
77
- File.delete(file)
78
- logger.info("Removed #{ file }")
79
- end
80
- end
81
-
82
- def versions
83
- all_files = Dir.glob("#{ config.build_output_dir }/**/*")
84
- entries = all_files - [config.manifest_path] - current_version_files
85
- entries.reject { |file| File.directory?(file) }
86
- .group_by { |file| File.mtime(file).utc.to_i }
87
- .sort.reverse
88
- end
89
-
90
- def current_version_files
91
- Dir.glob(manifest.refresh.values.map { |value| config.build_output_dir.join("#{ value['file'] }*") })
92
- end
93
-
94
- def with_node_env(env)
95
- original = ENV['NODE_ENV']
96
- ENV['NODE_ENV'] = env
97
- yield
98
- ensure
99
- ENV['NODE_ENV'] = original
100
- end
101
-
102
- def ensure_log_goes_to_stdout
103
- old_logger = ViteRails.logger
104
- ViteRails.logger = ActiveSupport::Logger.new(STDOUT)
105
- yield
106
- ensure
107
- ViteRails.logger = old_logger
108
- end
109
- end