vite_rails 1.0.12 → 2.0.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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/README.md +39 -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 -135
  7. data/lib/vite_rails/engine.rb +7 -11
  8. data/lib/vite_rails/installation.rb +47 -0
  9. data/lib/vite_rails/tag_helpers.rb +61 -0
  10. data/lib/vite_rails/version.rb +2 -2
  11. data/{test/mounted_app/test/dummy/config/vite.json → templates/config/rails-vite.json} +1 -0
  12. data/{lib/install/javascript → templates}/entrypoints/application.js +0 -0
  13. metadata +25 -129
  14. data/lib/install/bin/vite +0 -17
  15. data/lib/install/binstubs.rb +0 -6
  16. data/lib/install/config/vite.config.ts +0 -8
  17. data/lib/install/config/vite.json +0 -14
  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 -143
  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 -75
  43. data/test/manifest_test.rb +0 -85
  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/package.json +0 -8
  53. data/test/mounted_app/test/dummy/yarn.lock +0 -208
  54. data/test/rake_tasks_test.rb +0 -60
  55. data/test/runner_test.rb +0 -31
  56. data/test/test_app/Rakefile +0 -5
  57. data/test/test_app/app/frontend/entrypoints/application.js +0 -2
  58. data/test/test_app/bin/vite +0 -17
  59. data/test/test_app/config.ru +0 -7
  60. data/test/test_app/config/application.rb +0 -13
  61. data/test/test_app/config/environment.rb +0 -6
  62. data/test/test_app/config/vite.json +0 -18
  63. data/test/test_app/config/vite_additional_paths.json +0 -5
  64. data/test/test_app/config/vite_public_dir.json +0 -5
  65. data/test/test_app/package.json +0 -13
  66. data/test/test_app/public/vite-production/manifest-assets.json +0 -10
  67. data/test/test_app/public/vite-production/manifest.json +0 -39
  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,143 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Public: Registry for accessing resources managed by Vite, using a generated
4
- # manifest file which maps entrypoint names to file paths.
5
- #
6
- # Example:
7
- # lookup_entrypoint('calendar', type: :javascript)
8
- # => { "file" => "/vite/assets/calendar-1016838bab065ae1e314.js", "imports" => [] }
9
- #
10
- # NOTE: Using "autoBuild": true` in `config/vite.json` file will trigger a build
11
- # on demand as needed, before performing any lookup.
12
- class ViteRails::Manifest
13
- class MissingEntryError < StandardError
14
- end
15
-
16
- def initialize(vite_rails)
17
- @vite_rails = vite_rails
18
- end
19
-
20
- # Public: Strict version of lookup.
21
- #
22
- # Returns a relative path for the asset, or raises an error if not found.
23
- def lookup!(*args, **options)
24
- lookup(*args, **options) || missing_entry_error(*args, **options)
25
- end
26
-
27
- # Public: Computes the path for a given Vite asset using manifest.json.
28
- #
29
- # Returns a relative path, or nil if the asset is not found.
30
- #
31
- # Example:
32
- # ViteRails.manifest.lookup('calendar.js')
33
- # # { "file" => "/vite/assets/calendar-1016838bab065ae1e122.js", "imports" => [] }
34
- def lookup(name, type: nil)
35
- build if should_build?
36
-
37
- find_manifest_entry(with_file_extension(name, type))
38
- end
39
-
40
- # Public: Refreshes the cached mappings by reading the updated manifest files.
41
- def refresh
42
- @manifest = load_manifest
43
- end
44
-
45
- # Public: Scopes an asset to the output folder in public, as a path.
46
- def prefix_vite_asset(path)
47
- File.join("/#{ config.public_output_dir }", path)
48
- end
49
-
50
- private
51
-
52
- delegate :config, :builder, :dev_server_running?, to: :@vite_rails
53
-
54
- # NOTE: Auto compilation is convenient when running tests, when the developer
55
- # won't focus on the frontend, or when running the Vite server is not desired.
56
- def should_build?
57
- config.auto_build && !dev_server_running?
58
- end
59
-
60
- # Internal: Finds the specified entry in the manifest.
61
- def find_manifest_entry(name)
62
- if dev_server_running?
63
- { 'file' => prefix_vite_asset(name.to_s) }
64
- else
65
- manifest[name.to_s]
66
- end
67
- end
68
-
69
- # Internal: Performs a Vite build.
70
- def build
71
- ViteRails.logger.tagged('Vite') { builder.build }
72
- end
73
-
74
- # Internal: The parsed data from manifest.json.
75
- #
76
- # NOTE: When using build-on-demand in development and testing, the manifest
77
- # is reloaded automatically before each lookup, to ensure it's always fresh.
78
- def manifest
79
- return refresh if config.auto_build
80
-
81
- @manifest ||= load_manifest
82
- end
83
-
84
- # Internal: Loads and merges the manifest files, resolving the asset paths.
85
- def load_manifest
86
- files = [config.manifest_path, config.assets_manifest_path].select(&:exist?)
87
- files.map { |path| JSON.parse(path.read) }.inject({}, &:merge).tap(&method(:resolve_references))
88
- end
89
-
90
- # Internal: Resolves the paths that reference a manifest entry.
91
- def resolve_references(manifest)
92
- manifest.each_value do |entry|
93
- entry['file'] = prefix_vite_asset(entry['file'])
94
- entry['css'] = Array.wrap(entry['css']).map { |path| prefix_vite_asset(path) } if entry['css']
95
- entry['imports']&.map! { |name| manifest.fetch(name) }
96
- end
97
- end
98
-
99
- # Internal: Adds a file extension to the file name, unless it already has one.
100
- def with_file_extension(name, entry_type)
101
- return name unless File.extname(name.to_s).empty?
102
-
103
- extension = extension_for_type(entry_type)
104
- extension ? "#{ name }.#{ extension }" : name
105
- end
106
-
107
- # Internal: Allows to receive :javascript and :stylesheet as :type in helpers.
108
- def extension_for_type(entry_type)
109
- case entry_type
110
- when :javascript then 'js'
111
- when :stylesheet then 'css'
112
- when :typescript then 'ts'
113
- else entry_type
114
- end
115
- end
116
-
117
- # Internal: Raises a detailed message when an entry is missing in the manifest.
118
- def missing_entry_error(name, type: nil, **_options)
119
- file_name = with_file_extension(name, type)
120
- raise ViteRails::Manifest::MissingEntryError, <<~MSG
121
- Vite Rails can't find #{ file_name } in #{ config.manifest_path } or #{ config.assets_manifest_path }.
122
-
123
- Possible causes:
124
- #{ missing_entry_causes.map { |cause| "\t- #{ cause }" }.join("\n") }
125
-
126
- Content in your manifests:
127
- #{ JSON.pretty_generate(@manifest) }
128
- MSG
129
- end
130
-
131
- def missing_entry_causes
132
- local = config.auto_build
133
- [
134
- (dev_server_running? && 'Vite has not yet re-built your latest changes.'),
135
- (local && !dev_server_running? && "\"autoBuild\": false in your #{ config.mode } configuration."),
136
- (local && !dev_server_running? && 'The Vite development server has crashed or is no longer available.'),
137
- 'You have misconfigured config/vite.json file.',
138
- (!local && 'Assets have not been precompiled'),
139
- ].select(&:present?)
140
- rescue StandardError
141
- []
142
- end
143
- end
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Public: Executes Vite commands, providing conveniences for debugging.
4
- class ViteRails::Runner
5
- def initialize(argv)
6
- detect_unsupported_switches!(argv)
7
- @argv = argv
8
- end
9
-
10
- # Public: Executes Vite with the specified arguments.
11
- def run
12
- execute_command(@argv.clone)
13
- end
14
-
15
- private
16
-
17
- UNSUPPORTED_SWITCHES = %w[--host --port --https --root -r --config -c]
18
- private_constant :UNSUPPORTED_SWITCHES
19
-
20
- # Internal: Allows to prevent configuration mistakes by ensuring the Rails app
21
- # and vite-plugin-ruby are using the same configuration for the dev server.
22
- def detect_unsupported_switches!(args)
23
- return unless (unsupported = UNSUPPORTED_SWITCHES & args).any?
24
-
25
- $stdout.puts "Please set the following switches in your vite.json instead: #{ unsupported }."
26
- exit!
27
- end
28
-
29
- # Internal: Executes the command with the specified arguments.
30
- def execute_command(args)
31
- cmd = vite_executable
32
- cmd.prepend('node', '--inspect-brk') if args.include?('--debug')
33
- cmd.prepend('node', '--trace-deprecation') if args.delete('--trace-deprecation')
34
- args.append('--mode', ViteRails.mode) unless args.include?('--mode') || args.include?('-m')
35
- cmd += args
36
- Dir.chdir(File.expand_path('.', Dir.pwd)) { Kernel.exec(ViteRails.config.to_env, *cmd) }
37
- end
38
-
39
- # Internal: Resolves to an executable for Vite.
40
- def vite_executable
41
- executable_exists?(path = vite_bin_path) ? [path] : %w[yarn vite]
42
- end
43
-
44
- # Internal: Only so that we can easily cover both paths in tests
45
- def executable_exists?(path)
46
- File.exist?(path)
47
- end
48
-
49
- # Internal: Returns a path where a Vite executable should be found.
50
- def vite_bin_path
51
- ENV["#{ ViteRails::ENV_PREFIX }_VITE_BIN_PATH"] || `yarn bin vite`.chomp.presence || "#{ `npm bin`.chomp }/vite"
52
- end
53
- end
data/package.json DELETED
@@ -1,19 +0,0 @@
1
- {
2
- "name": "only-for-workflows",
3
- "version": "unknown",
4
- "license": "MIT",
5
- "scripts": {
6
- "docs": "npm -C docs run docs",
7
- "docs:build": "npm -C docs run docs:build",
8
- "docs:search": "npm -C docs run docs:search",
9
- "docs:lint": "npm -C docs run lint",
10
- "build": "rm -rf package/dist && npm -C package run prerelease",
11
- "release": "rm -rf package/dist && npm -C package run release",
12
- "lint": "npm -C package run lint",
13
- "test": "npm -C package run test"
14
- },
15
- "dependencies": {
16
- "vite": "^2.0.0-beta.56",
17
- "vite-plugin-ruby": "^1.0.6"
18
- }
19
- }
@@ -1,16 +0,0 @@
1
- {
2
- "assetHost": null,
3
- "assetsDir": "assets",
4
- "autoBuild": false,
5
- "buildCacheDir": "tmp/cache/vite",
6
- "publicOutputDir": "vite",
7
- "configPath": "config/vite.json",
8
- "publicDir": "public",
9
- "entrypointsDir": "entrypoints",
10
- "sourceCodeDir": "app/frontend",
11
- "host": "localhost",
12
- "https": null,
13
- "port": 3036,
14
- "hideBuildConsoleOutput": false,
15
- "watchAdditionalPaths": []
16
- }
data/test/builder_test.rb DELETED
@@ -1,77 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class BuilderTest < ViteRails::Test
6
- def setup
7
- refresh_config
8
- ViteRails.builder.send(:files_digest_path).tap do |path|
9
- path.delete if path.exist?
10
- end
11
- end
12
-
13
- def teardown
14
- setup
15
- end
16
-
17
- def vite_env
18
- ViteRails.config.to_env
19
- end
20
-
21
- def test_custom_environment_variables
22
- assert_nil vite_env['FOO']
23
- ViteRails.env['FOO'] = 'BAR'
24
- assert vite_env['FOO'] == 'BAR'
25
- end
26
-
27
- def test_freshness
28
- assert ViteRails.builder.stale?
29
- assert !ViteRails.builder.fresh?
30
- end
31
-
32
- def test_build
33
- assert !ViteRails.builder.build
34
- end
35
-
36
- def test_freshness_on_build_success
37
- assert ViteRails.builder.stale?
38
- status = OpenStruct.new(success?: true)
39
- Open3.stub :capture3, [:sterr, :stdout, status] do
40
- assert ViteRails.builder.build
41
- assert ViteRails.builder.fresh?
42
- end
43
- end
44
-
45
- def test_freshness_on_build_fail
46
- assert ViteRails.builder.stale?
47
- status = OpenStruct.new(success?: false)
48
- Open3.stub :capture3, [:sterr, :stdout, status] do
49
- assert !ViteRails.builder.build
50
- assert ViteRails.builder.fresh?
51
- end
52
- end
53
-
54
- def test_files_digest_path
55
- assert_equal ViteRails.builder.send(:files_digest_path).basename.to_s, "last-compilation-digest-#{ ViteRails.config.mode }"
56
- end
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
-
64
- def test_external_env_variables
65
- assert_equal 'production', vite_env['VITE_RUBY_MODE']
66
- assert_equal Rails.root.to_s, vite_env['VITE_RUBY_ROOT']
67
-
68
- ENV['VITE_RUBY_MODE'] = 'foo.bar'
69
- 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')
76
- end
77
- end
@@ -1,67 +0,0 @@
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
data/test/config_test.rb DELETED
@@ -1,133 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class ConfigTest < ViteRails::Test
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
- end
13
-
14
- def assert_pathname(expected, actual)
15
- assert_equal Pathname.new(expand_path("test_app/#{ expected }")), actual
16
- end
17
-
18
- def resolve_config(mode: 'production', root: test_app_path, **attrs)
19
- ViteRails::Config.resolve_config(mode: mode, root: root, **attrs)
20
- end
21
-
22
- def setup
23
- @config = resolve_config
24
- end
25
-
26
- def test_source_code_dir
27
- assert_equal 'app/frontend', @config.source_code_dir
28
- end
29
-
30
- def test_entrypoints_dir
31
- assert_path 'test_app/app/frontend/entrypoints', @config.resolved_entrypoints_dir
32
- end
33
-
34
- def test_public_dir
35
- assert_equal 'public', @config.public_dir
36
- end
37
-
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
43
- end
44
-
45
- def test_manifest_path
46
- assert_path 'test_app/public/vite-production/manifest.json', @config.manifest_path
47
- end
48
-
49
- def test_build_cache_dir
50
- assert_path 'test_app/tmp/cache/vite', @config.build_cache_dir
51
- end
52
-
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
58
-
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
68
- end
69
-
70
- with_rails_env('staging') do |config|
71
- refute config.auto_build
72
- end
73
- end
74
-
75
- def test_protocol
76
- assert_equal 'http', @config.protocol
77
- end
78
-
79
- def test_host_with_port
80
- assert_equal 3036, @config.port
81
-
82
- with_rails_env('development') do |config|
83
- assert_equal 3535, config.port
84
- assert_equal 'localhost:3535', config.host_with_port
85
- end
86
- end
87
-
88
- def test_to_env
89
- env = @config.to_env
90
- assert_nil env['VITE_RUBY_ASSET_HOST']
91
-
92
- Rails.application.config.action_controller.asset_host = 'assets-cdn.com'
93
- env = refresh_config.to_env
94
- assert_equal env['VITE_RUBY_ASSET_HOST'], 'assets-cdn.com'
95
- ensure
96
- Rails.application.config.action_controller.asset_host = nil
97
- end
98
-
99
- def test_environment_vars
100
- ViteRails.env = {
101
- 'VITE_RUBY_AUTO_BUILD' => 'true',
102
- 'VITE_RUBY_HOST' => 'example.com',
103
- 'VITE_RUBY_PORT' => '1920',
104
- 'VITE_RUBY_HTTPS' => 'true',
105
- 'VITE_RUBY_CONFIG_PATH' => 'config/vite_additional_paths.json',
106
- 'VITE_RUBY_BUILD_CACHE_DIR' => 'tmp/vitebuild',
107
- 'VITE_RUBY_PUBLIC_DIR' => 'pb',
108
- 'VITE_RUBY_PUBLIC_OUTPUT_DIR' => 'ft',
109
- 'VITE_RUBY_ASSETS_DIR' => 'as',
110
- 'VITE_RUBY_SOURCE_CODE_DIR' => 'app',
111
- 'VITE_RUBY_ENTRYPOINTS_DIR' => 'frontend/entrypoints',
112
- 'VITE_RUBY_HIDE_BUILD_CONSOLE_OUTPUT' => 'true',
113
- }
114
- @config = resolve_config
115
- assert_equal true, @config.auto_build
116
- assert_equal 'example.com', @config.host
117
- assert_equal 1920, @config.port
118
- assert_equal true, @config.https
119
- assert_equal 'https', @config.protocol
120
- assert_equal 'config/vite_additional_paths.json', @config.config_path
121
- assert_pathname 'tmp/vitebuild', @config.build_cache_dir
122
- assert_equal 'pb', @config.public_dir
123
- assert_equal 'ft', @config.public_output_dir
124
- assert_pathname 'pb/ft', @config.build_output_dir
125
- assert_equal 'as', @config.assets_dir
126
- assert_equal 'app', @config.source_code_dir
127
- assert_equal 'frontend/entrypoints', @config.entrypoints_dir
128
- assert_pathname 'app/frontend/entrypoints', @config.resolved_entrypoints_dir
129
- assert_equal true, @config.hide_build_console_output
130
- ensure
131
- ViteRails.env = {}
132
- end
133
- end