vite_rails 1.0.8 → 1.0.9

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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -1
  3. data/CONTRIBUTING.md +0 -1
  4. data/lib/install/template.rb +1 -1
  5. data/lib/tasks/vite/build.rake +1 -5
  6. data/lib/tasks/vite/clean.rake +1 -3
  7. data/lib/tasks/vite/verify_install.rake +3 -3
  8. data/lib/vite_rails.rb +14 -25
  9. data/lib/vite_rails/builder.rb +11 -4
  10. data/lib/vite_rails/commands.rb +50 -10
  11. data/lib/vite_rails/config.rb +35 -23
  12. data/lib/vite_rails/dev_server_proxy.rb +27 -18
  13. data/lib/vite_rails/helper.rb +4 -2
  14. data/lib/vite_rails/manifest.rb +4 -3
  15. data/lib/vite_rails/runner.rb +2 -5
  16. data/lib/vite_rails/version.rb +1 -1
  17. data/package.json +1 -1
  18. data/test/builder_test.rb +27 -22
  19. data/test/commands_test.rb +67 -0
  20. data/test/configuration_test.rb +88 -46
  21. data/test/dev_server_proxy_test.rb +101 -0
  22. data/test/dev_server_test.rb +0 -30
  23. data/test/engine_rake_tasks_test.rb +55 -17
  24. data/test/helper_test.rb +37 -105
  25. data/test/manifest_test.rb +33 -29
  26. data/test/mode_test.rb +6 -11
  27. data/test/mounted_app/test/dummy/config/vite.json +5 -11
  28. data/test/mounted_app/test/dummy/package.json +2 -1
  29. data/test/mounted_app/test/dummy/yarn.lock +208 -0
  30. data/test/rake_tasks_test.rb +5 -19
  31. data/test/runner_test.rb +31 -0
  32. data/test/test_app/app/{javascript → frontend}/entrypoints/application.js +0 -0
  33. data/test/test_app/config/vite.json +0 -2
  34. data/test/test_app/config/vite_additional_paths.json +5 -0
  35. data/test/test_app/config/vite_public_dir.json +5 -0
  36. data/test/test_app/public/vite-production/manifest.json +22 -0
  37. data/test/test_helper.rb +48 -14
  38. metadata +21 -23
  39. data/test/command_test.rb +0 -35
  40. data/test/dev_server_runner_test.rb +0 -83
  41. data/test/test_app/app/javascript/entrypoints/multi_entry.css +0 -4
  42. data/test/test_app/app/javascript/entrypoints/multi_entry.js +0 -4
  43. data/test/test_app/config/vite_public_root.yml +0 -20
  44. data/test/test_app/public/vite/manifest.json +0 -36
  45. data/test/vite_runner_test.rb +0 -59
  46. data/test/webpacker_test.rb +0 -15
@@ -31,7 +31,7 @@ class ViteRails::Manifest
31
31
  # Example:
32
32
  # ViteRails.manifest.lookup('calendar.js')
33
33
  # # { "file" => "/vite/assets/calendar-1016838bab065ae1e122.js", "imports" => [] }
34
- def lookup(name, type:)
34
+ def lookup(name, type: nil)
35
35
  build if should_build?
36
36
 
37
37
  find_manifest_entry(with_file_extension(name, type))
@@ -92,7 +92,8 @@ private
92
92
  def with_file_extension(name, entry_type)
93
93
  return name unless File.extname(name.to_s).empty?
94
94
 
95
- "#{ name }.#{ extension_for_type(entry_type) }"
95
+ extension = extension_for_type(entry_type)
96
+ extension ? "#{ name }.#{ extension }" : name
96
97
  end
97
98
 
98
99
  # Internal: Scopes the paths in the manifest to the output folder in public.
@@ -106,7 +107,7 @@ private
106
107
  when :javascript then 'js'
107
108
  when :stylesheet then 'css'
108
109
  when :typescript then dev_server_running? ? 'ts' : 'js'
109
- else entry_type.to_s
110
+ else entry_type
110
111
  end
111
112
  end
112
113
 
@@ -31,9 +31,8 @@ private
31
31
  cmd = vite_executable
32
32
  cmd.prepend('node', '--inspect-brk') if args.include?('--debug')
33
33
  cmd.prepend('node', '--trace-deprecation') if args.delete('--trace-deprecation')
34
- args.append('--mode', ENV['RAILS_ENV']) unless args.include?('--mode') || args.include?('-m')
34
+ args.append('--mode', ViteRails.mode) unless args.include?('--mode') || args.include?('-m')
35
35
  cmd += args
36
- puts cmd.join(' ')
37
36
  Dir.chdir(File.expand_path('.', Dir.pwd)) { Kernel.exec(ViteRails.env, *cmd) }
38
37
  end
39
38
 
@@ -49,8 +48,6 @@ private
49
48
 
50
49
  # Internal: Returns a path where a Vite executable should be found.
51
50
  def vite_bin_path
52
- ENV["#{ ViteRails::ENV_PREFIX }_VITE_BIN_PATH"] || `yarn bin vite`.chomp
53
- rescue StandardError
54
- "#{ `npm bin`.chomp }/vite"
51
+ ENV["#{ ViteRails::ENV_PREFIX }_VITE_BIN_PATH"] || `yarn bin vite`.chomp.presence || "#{ `npm bin`.chomp }/vite"
55
52
  end
56
53
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ViteRails
4
- VERSION = '1.0.8'
4
+ VERSION = '1.0.9'
5
5
  end
@@ -11,6 +11,6 @@
11
11
  },
12
12
  "dependencies": {
13
13
  "vite": "^2.0.0-beta.34",
14
- "vite-plugin-ruby": "^1.0.2"
14
+ "vite-plugin-ruby": "^1.0.3"
15
15
  }
16
16
  }
@@ -2,27 +2,26 @@
2
2
 
3
3
  require 'test_helper'
4
4
 
5
- class BuilderTest < Minitest::Test
6
- def remove_files_digest_path
5
+ class BuilderTest < ViteRails::Test
6
+ def setup
7
+ refresh_config
7
8
  ViteRails.builder.send(:files_digest_path).tap do |path|
8
9
  path.delete if path.exist?
9
10
  end
10
11
  end
11
12
 
12
- def setup
13
- remove_files_digest_path
13
+ def teardown
14
+ setup
14
15
  end
15
16
 
16
- def teardown
17
- remove_files_digest_path
17
+ def vite_env
18
+ ViteRails.builder.send(:vite_env)
18
19
  end
19
20
 
20
21
  def test_custom_environment_variables
21
- assert_nil ViteRails.builder.send(:vite_env)['FOO']
22
+ assert_nil vite_env['FOO']
22
23
  ViteRails.env['FOO'] = 'BAR'
23
- assert ViteRails.builder.send(:vite_env)['FOO'] == 'BAR'
24
- ensure
25
- ViteRails.env = {}
24
+ assert vite_env['FOO'] == 'BAR'
26
25
  end
27
26
 
28
27
  def test_freshness
@@ -35,21 +34,19 @@ class BuilderTest < Minitest::Test
35
34
  end
36
35
 
37
36
  def test_freshness_on_build_success
38
- status = OpenStruct.new(success?: true)
39
-
40
37
  assert ViteRails.builder.stale?
38
+ status = OpenStruct.new(success?: true)
41
39
  Open3.stub :capture3, [:sterr, :stdout, status] do
42
- ViteRails.builder.build
40
+ assert ViteRails.builder.build
43
41
  assert ViteRails.builder.fresh?
44
42
  end
45
43
  end
46
44
 
47
45
  def test_freshness_on_build_fail
48
- status = OpenStruct.new(success?: false)
49
-
50
46
  assert ViteRails.builder.stale?
47
+ status = OpenStruct.new(success?: false)
51
48
  Open3.stub :capture3, [:sterr, :stdout, status] do
52
- ViteRails.builder.build
49
+ assert !ViteRails.builder.build
53
50
  assert ViteRails.builder.fresh?
54
51
  end
55
52
  end
@@ -58,15 +55,23 @@ class BuilderTest < Minitest::Test
58
55
  assert_equal ViteRails.builder.send(:files_digest_path).basename.to_s, "last-compilation-digest-#{ ViteRails.config.mode }"
59
56
  end
60
57
 
58
+ def test_watched_files_digest
59
+ previous_digest = ViteRails.builder.send(:watched_files_digest)
60
+ refresh_config
61
+ assert_equal previous_digest, ViteRails.builder.send(:watched_files_digest)
62
+ end
63
+
61
64
  def test_external_env_variables
62
- ViteRails.env = {}
63
- assert_equal ViteRails.builder.send(:vite_env)['VITE_RUBY_MODE'], 'production'
64
- assert_equal ViteRails.builder.send(:vite_env)['VITE_RUBY_ROOT'], Rails.root.to_s
65
+ assert_equal 'production', vite_env['VITE_RUBY_MODE']
66
+ assert_equal Rails.root.to_s, vite_env['VITE_RUBY_ROOT']
65
67
 
66
68
  ENV['VITE_RUBY_MODE'] = 'foo.bar'
67
69
  ENV['VITE_RUBY_ROOT'] = '/baz'
68
-
69
- assert_equal ViteRails.builder.send(:vite_env)['VITE_RUBY_MODE'], 'foo.bar'
70
- assert_equal ViteRails.builder.send(:vite_env)['VITE_RUBY_ROOT'], '/baz'
70
+ refresh_config
71
+ assert_equal 'foo.bar', vite_env['VITE_RUBY_MODE']
72
+ assert_equal '/baz', vite_env['VITE_RUBY_ROOT']
73
+ ensure
74
+ ENV.delete('VITE_RUBY_MODE')
75
+ ENV.delete('VITE_RUBY_ROOT')
71
76
  end
72
77
  end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class CommandsTest < ViteRails::Test
6
+ def stub_builder(stale:, build_with_vite:)
7
+ ViteRails.builder.stub :stale?, stale do
8
+ ViteRails.builder.stub :build_with_vite, build_with_vite do
9
+ yield
10
+ end
11
+ end
12
+ end
13
+
14
+ def test_bootstrap
15
+ assert ViteRails.bootstrap
16
+ end
17
+
18
+ def test_build_returns_success_status_when_stale
19
+ stub_builder(stale: true, build_with_vite: true) {
20
+ assert_equal true, ViteRails.build
21
+ assert_equal true, ViteRails.build_from_rake
22
+ }
23
+ end
24
+
25
+ def test_build_returns_success_status_when_fresh
26
+ stub_builder(stale: false, build_with_vite: true) {
27
+ assert_equal true, ViteRails.build
28
+ assert_equal true, ViteRails.build_from_rake
29
+ }
30
+ end
31
+
32
+ def test_build_returns_failure_status_when_stale
33
+ stub_builder(stale: true, build_with_vite: false) {
34
+ assert_equal false, ViteRails.build
35
+ }
36
+ end
37
+
38
+ def test_clean
39
+ with_rails_env('test') { |config|
40
+ manifest = config.build_output_dir.join('manifest.json')
41
+
42
+ # Should not clean, the manifest does not exist.
43
+ config.build_output_dir.mkdir unless config.build_output_dir.exist?
44
+ refute ViteRails.clean
45
+
46
+ # Should not clean, the file is recent.
47
+ manifest.write('{}')
48
+ assert ViteRails.clean_from_rake(OpenStruct.new)
49
+ assert manifest.exist?
50
+
51
+ # Should clean if we remove age restrictions.
52
+ assert ViteRails.clean(keep_up_to: 0, age_in_seconds: 0)
53
+ assert config.build_output_dir.exist?
54
+ refute manifest.exist?
55
+ }
56
+ end
57
+
58
+ def test_clobber
59
+ with_rails_env('test') { |config|
60
+ config.build_output_dir.mkdir unless config.build_output_dir.exist?
61
+ config.build_output_dir.join('manifest.json').write('{}')
62
+ assert config.build_output_dir.exist?
63
+ ViteRails.clobber
64
+ refute config.build_output_dir.exist?
65
+ }
66
+ end
67
+ end
@@ -3,78 +3,120 @@
3
3
  require 'test_helper'
4
4
 
5
5
  class ConfigurationTest < ViteRails::Test
6
- def setup
7
- @config = ViteRails::Configuration.new(
8
- root_path: Pathname.new(File.expand_path('test_app', __dir__)),
9
- config_path: Pathname.new(File.expand_path('./test_app/config/vite.yml', __dir__)),
10
- env: 'production',
11
- )
6
+ def expand_path(path)
7
+ File.expand_path(Pathname.new(__dir__).join(path).to_s)
8
+ end
9
+
10
+ def assert_path(expected, actual)
11
+ assert_equal expand_path(expected), actual.to_s
12
12
  end
13
13
 
14
- def test_source_path
15
- source_path = File.expand_path File.join(File.dirname(__FILE__), 'test_app/app/javascript').to_s
16
- assert_equal source_path, @config.source_path.to_s
14
+ def assert_pathname(expected, actual)
15
+ assert_equal Pathname.new(expand_path("test_app/#{ expected }")), actual
17
16
  end
18
17
 
19
- def test_source_entry_path
20
- source_entry_path = File.expand_path File.join(File.dirname(__FILE__), 'test_app/app/javascript', 'packs').to_s
21
- assert_equal @config.source_entry_path.to_s, source_entry_path
18
+ def resolve_config(mode: 'production', root: test_app_path, **attrs)
19
+ ViteRails::Config.resolve_config(mode: mode, root: root, **attrs)
22
20
  end
23
21
 
24
- def test_public_root_path
25
- public_root_path = File.expand_path File.join(File.dirname(__FILE__), 'test_app/public').to_s
26
- assert_equal @config.public_path.to_s, public_root_path
22
+ def setup
23
+ @config = resolve_config
27
24
  end
28
25
 
29
- def test_public_output_path
30
- public_output_path = File.expand_path File.join(File.dirname(__FILE__), 'test_app/public/packs').to_s
31
- assert_equal @config.public_output_path.to_s, public_output_path
26
+ def test_source_code_dir
27
+ assert_path 'test_app/app/frontend', @config.source_code_dir
28
+ end
32
29
 
33
- @config = ViteRails::Configuration.new(
34
- root_path: @config.root_path,
35
- config_path: Pathname.new(File.expand_path('./test_app/config/vite_public_root.yml', __dir__)),
36
- env: 'production',
37
- )
30
+ def test_entrypoints_dir
31
+ assert_path 'test_app/app/frontend/entrypoints', @config.resolved_entrypoints_dir
32
+ end
38
33
 
39
- public_output_path = File.expand_path File.join(File.dirname(__FILE__), 'public/packs').to_s
40
- assert_equal @config.public_output_path.to_s, public_output_path
34
+ def test_public_dir
35
+ assert_path 'test_app/public', @config.public_dir
41
36
  end
42
37
 
43
- def test_public_manifest_path
44
- public_manifest_path = File.expand_path File.join(File.dirname(__FILE__), 'test_app/public/packs', 'manifest.json').to_s
45
- assert_equal @config.public_manifest_path.to_s, public_manifest_path
38
+ def test_build_output_dir
39
+ assert_path 'test_app/public/vite-production', @config.build_output_dir
40
+
41
+ @config = resolve_config(config_path: 'config/vite_public_dir.json')
42
+ assert_path 'public/vite', @config.build_output_dir
46
43
  end
47
44
 
48
- def test_cache_path
49
- cache_path = File.expand_path File.join(File.dirname(__FILE__), 'test_app/tmp/cache/vite').to_s
50
- assert_equal @config.cache_path.to_s, cache_path
45
+ def test_manifest_path
46
+ assert_path 'test_app/public/vite-production/manifest.json', @config.manifest_path
51
47
  end
52
48
 
53
- def test_additional_paths
54
- assert_equal @config.additional_paths, ['app/assets', '/etc/yarn', 'some.config.js', 'app/elm']
49
+ def test_build_cache_dir
50
+ assert_path 'test_app/tmp/cache/vite', @config.build_cache_dir
55
51
  end
56
52
 
57
- def test_cache_manifest?
58
- assert @config.cache_manifest?
53
+ def test_watch_additional_paths
54
+ assert_equal [], @config.watch_additional_paths
55
+ @config = resolve_config(config_path: 'config/vite_additional_paths.json')
56
+ assert_equal ['config/*'], @config.watch_additional_paths
57
+ end
59
58
 
60
- with_rails_env('development') do
61
- refute ViteRails.config.cache_manifest?
59
+ def test_auto_build
60
+ refute @config.auto_build
61
+
62
+ with_rails_env('development') do |config|
63
+ assert config.auto_build
64
+ end
65
+
66
+ with_rails_env('test') do |config|
67
+ assert config.auto_build
62
68
  end
63
69
 
64
- with_rails_env('test') do
65
- refute ViteRails.config.cache_manifest?
70
+ with_rails_env('staging') do |config|
71
+ refute config.auto_build
66
72
  end
67
73
  end
68
74
 
69
- def test_compile?
70
- refute @config.compile?
75
+ def test_protocol
76
+ assert_equal 'http', @config.protocol
77
+ end
71
78
 
72
- with_rails_env('development') do
73
- assert ViteRails.config.compile?
74
- end
79
+ def test_host_with_port
80
+ assert_equal 3036, @config.port
75
81
 
76
- with_rails_env('test') do
77
- assert ViteRails.config.compile?
82
+ with_rails_env('development') do |config|
83
+ assert_equal 3535, config.port
84
+ assert_equal 'localhost:3535', config.host_with_port
78
85
  end
79
86
  end
87
+
88
+ def test_environment_vars
89
+ ViteRails.env = {
90
+ 'VITE_RUBY_AUTO_BUILD' => 'true',
91
+ 'VITE_RUBY_HOST' => 'example.com',
92
+ 'VITE_RUBY_PORT' => '1920',
93
+ 'VITE_RUBY_HTTPS' => 'true',
94
+ 'VITE_RUBY_CONFIG_PATH' => 'config/vite_additional_paths.json',
95
+ 'VITE_RUBY_BUILD_CACHE_DIR' => 'tmp/vitebuild',
96
+ 'VITE_RUBY_PUBLIC_DIR' => 'pb',
97
+ 'VITE_RUBY_PUBLIC_OUTPUT_DIR' => 'ft',
98
+ 'VITE_RUBY_ASSETS_DIR' => 'as',
99
+ 'VITE_RUBY_SOURCE_CODE_DIR' => 'app',
100
+ 'VITE_RUBY_ENTRYPOINTS_DIR' => 'frontend/entrypoints',
101
+ 'VITE_RUBY_HIDE_BUILD_CONSOLE_OUTPUT' => 'true',
102
+ }
103
+ @config = resolve_config
104
+ assert_equal true, @config.auto_build
105
+ assert_equal 'example.com', @config.host
106
+ assert_equal 1920, @config.port
107
+ assert_equal true, @config.https
108
+ assert_equal 'https', @config.protocol
109
+ assert_equal Pathname.new('config/vite_additional_paths.json'), @config.config_path
110
+ assert_pathname 'tmp/vitebuild', @config.build_cache_dir
111
+ assert_pathname 'pb', @config.public_dir
112
+ assert_equal Pathname.new('ft'), @config.public_output_dir
113
+ assert_pathname 'pb/ft', @config.build_output_dir
114
+ assert_equal 'as', @config.assets_dir
115
+ assert_pathname 'app', @config.source_code_dir
116
+ assert_equal 'frontend/entrypoints', @config.entrypoints_dir
117
+ assert_pathname 'app/frontend/entrypoints', @config.resolved_entrypoints_dir
118
+ assert_equal true, @config.hide_build_console_output
119
+ ensure
120
+ ViteRails.env = {}
121
+ end
80
122
  end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class DevServerProxyTest < ViteRails::Test
6
+ include Rack::Test::Methods
7
+
8
+ def app
9
+ # Capture all changes to the env made by the proxy.
10
+ capture_app = Rack::Builder.new.run(->(env) {
11
+ [200, { 'Content-Type' => 'application/json' }, env.to_json]
12
+ })
13
+ # Avoid actually using the proxy.
14
+ Rack::Proxy.define_method(:perform_request) { |env| capture_app.call(env) }
15
+
16
+ ViteRails::DevServerProxy.new(capture_app)
17
+ end
18
+
19
+ def test_non_asset
20
+ get_with_dev_server_running '/'
21
+ assert_not_forwarded
22
+ end
23
+
24
+ def test_non_vite_asset
25
+ get_with_dev_server_running '/example_import.js'
26
+ assert_not_forwarded
27
+ end
28
+
29
+ def test_vite_asset
30
+ get_with_dev_server_running '/vite-production/application.js'
31
+ assert_forwarded to: '/application.js'
32
+ end
33
+
34
+ def test_vite_client
35
+ get_with_dev_server_running '/@vite/client'
36
+ assert_forwarded to: '/@vite/client'
37
+ end
38
+
39
+ def test_vite_import
40
+ get_with_dev_server_running '/@fs//package/example/app/frontend/App.vue?import&t=1611322300214&vue&type=style&index=0&lang.css'
41
+ assert_forwarded to: '/@fs//package/example/app/frontend/App.vue?import&t=1611322300214&vue&type=style&index=0&lang.css'
42
+ end
43
+
44
+ def test_hmr_for_stylesheet
45
+ get_with_dev_server_running '/colored.css?t=1611322562923'
46
+ assert_forwarded to: '/colored.css?t=1611322562923'
47
+ end
48
+
49
+ def test_hmr_for_imported_entrypoint
50
+ get_with_dev_server_running '/colored.css?import&t=1611322562923'
51
+ assert_forwarded to: '/colored.css?import&t=1611322562923'
52
+ end
53
+
54
+ def test_entrypoint_imported_from_entrypoint
55
+ header 'Referer', 'http://localhost:3000/vite-production/application.js'
56
+ get_with_dev_server_running '/example_import.js'
57
+ assert_forwarded to: '/example_import.js'
58
+ end
59
+
60
+ def test_without_dev_server_running
61
+ get '/vite-production/application.js'
62
+ assert_not_forwarded
63
+
64
+ get '/colored.css?import&t=1611322562923'
65
+ assert_not_forwarded
66
+
67
+ header 'Referer', 'http://localhost:3000/vite-production/application.js'
68
+ get '/example_import.js'
69
+ assert_not_forwarded
70
+ end
71
+
72
+ private
73
+
74
+ def get_with_dev_server_running(*args)
75
+ with_dev_server_running {
76
+ get(*args)
77
+ }
78
+ end
79
+
80
+ def assert_not_forwarded
81
+ assert last_response.ok?
82
+ env = JSON.parse(last_response.body)
83
+ assert_nil env['HTTP_X_FORWARDED_HOST']
84
+ assert_nil env['HTTP_X_FORWARDED_PORT']
85
+ end
86
+
87
+ def assert_forwarded(to: nil)
88
+ assert last_response.ok?
89
+ env = JSON.parse(last_response.body)
90
+
91
+ assert_equal ViteRails.config.host, env['HTTP_X_FORWARDED_HOST']
92
+ assert_equal ViteRails.config.port, Integer(env['HTTP_X_FORWARDED_PORT'])
93
+
94
+ return unless to
95
+
96
+ path, query = to.split('?')
97
+ assert_equal path, env['PATH_INFO']
98
+ assert_equal query, env['QUERY_STRING']
99
+ assert_equal to, env['REQUEST_URI']
100
+ end
101
+ end