vite_rails 1.0.11 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
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