vite_rails 1.0.10 → 2.0.2

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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/README.md +55 -30
  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 +52 -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 -127
  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 -11
  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 -29
  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 -20
  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 -69
  32. data/lib/vite_rails/manifest.rb +0 -140
  33. data/lib/vite_rails/runner.rb +0 -53
  34. data/package.json +0 -16
  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 -101
  40. data/test/dev_server_test.rb +0 -9
  41. data/test/engine_rake_tasks_test.rb +0 -80
  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/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.json +0 -22
  67. data/test/test_app/some.config.js +0 -0
  68. data/test/test_app/yarn.lock +0 -11
  69. data/test/test_helper.rb +0 -68
@@ -1,69 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Public: Allows to render HTML tags for scripts and styles processed by Vite.
4
- module ViteRails::Helper
5
- DEFAULT_VITE_SKIP_PRELOAD_TAGS = Rails.gem_version < Gem::Version.new('5.2.0')
6
-
7
- # Public: Returns the current Vite Rails instance.
8
- def current_vite_instance
9
- ViteRails.instance
10
- end
11
-
12
- # Public: Renders a script tag for vite/client to enable HMR in development.
13
- def vite_client_tag
14
- content_tag('script', '', src: '/@vite/client', type: 'module') if ViteRails.dev_server_running?
15
- end
16
-
17
- # Public: Resolves the path for the specified Vite asset.
18
- #
19
- # Example:
20
- # <%= vite_asset_path 'calendar.css' %> # => "/vite/assets/calendar-1016838bab065ae1e122.css"
21
- def vite_asset_path(name, **options)
22
- path_to_asset current_vite_instance.manifest.lookup!(name, **options).fetch('file')
23
- end
24
-
25
- # Public: Renders a <script> tag for the specified Vite entrypoints.
26
- def vite_javascript_tag(*names,
27
- type: 'module',
28
- asset_type: :javascript,
29
- skip_preload_tags: DEFAULT_VITE_SKIP_PRELOAD_TAGS,
30
- skip_style_tags: false,
31
- crossorigin: 'anonymous',
32
- **options)
33
- js_entries = names.map { |name| current_vite_instance.manifest.lookup!(name, type: asset_type) }
34
- js_tags = javascript_include_tag(*js_entries.map { |entry| entry['file'] }, crossorigin: crossorigin, type: type, **options)
35
-
36
- unless skip_preload_tags || ViteRails.dev_server_running?
37
- preload_paths = js_entries.flat_map { |entry| entry['imports'] }.compact.uniq
38
- preload_tags = preload_paths.map { |path| preload_link_tag(path, crossorigin: crossorigin) }
39
- end
40
-
41
- unless skip_style_tags || ViteRails.dev_server_running?
42
- style_paths = names.map { |name|
43
- current_vite_instance.manifest.lookup(name.delete_suffix('.js'), type: :stylesheet)&.fetch('file')
44
- }.compact
45
- style_tags = stylesheet_link_tag(*style_paths)
46
- end
47
-
48
- safe_join [js_tags, preload_tags, style_tags]
49
- end
50
-
51
- # Public: Renders a <script> tag for the specified Vite entrypoints.
52
- #
53
- # NOTE: Because TypeScript is not a valid target in browsers, we only specify
54
- # the ts file when running the Vite development server.
55
- def vite_typescript_tag(*names, **options)
56
- vite_javascript_tag(*names, asset_type: :typescript, extname: false, **options)
57
- end
58
-
59
- # Public: Renders a <link> tag for the specified Vite entrypoints.
60
- def vite_stylesheet_tag(*names, **options)
61
- stylesheet_link_tag(*sources_from_vite_manifest(names, type: :stylesheet), **options)
62
- end
63
-
64
- private
65
-
66
- def sources_from_vite_manifest(names, type:)
67
- names.map { |name| vite_asset_path(name, type: type) }
68
- end
69
- end
@@ -1,140 +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.
41
- def refresh
42
- @manifest = load_manifest
43
- end
44
-
45
- private
46
-
47
- delegate :config, :builder, :dev_server_running?, to: :@vite_rails
48
-
49
- # NOTE: Auto compilation is convenient when running tests, when the developer
50
- # won't focus on the frontend, or when running the Vite server is not desired.
51
- def should_build?
52
- config.auto_build && !dev_server_running?
53
- end
54
-
55
- # Internal: Finds the specified entry in the manifest.
56
- def find_manifest_entry(name)
57
- if dev_server_running?
58
- { 'file' => "/#{ config.public_output_dir.join(name.to_s) }" }
59
- else
60
- manifest[name.to_s]
61
- end
62
- end
63
-
64
- # Internal: Performs a Vite build.
65
- def build
66
- ViteRails.logger.tagged('Vite') { builder.build }
67
- end
68
-
69
- # Internal: The parsed data from manifest.json.
70
- #
71
- # NOTE: When using build-on-demand in development and testing, the manifest
72
- # is reloaded automatically before each lookup, to ensure it's always fresh.
73
- def manifest
74
- return refresh if config.auto_build
75
-
76
- @manifest ||= load_manifest
77
- end
78
-
79
- # Internal: Returns a Hash with the entries in the manifest.json.
80
- def load_manifest
81
- if config.manifest_path.exist?
82
- JSON.parse(config.manifest_path.read).each do |_, entry|
83
- entry['file'] = within_public_output_dir(entry['file'])
84
- entry['imports'] = entry['imports']&.map { |path| within_public_output_dir(path) }
85
- end
86
- else
87
- {}
88
- end
89
- end
90
-
91
- # Internal: Adds a file extension to the file name, unless it already has one.
92
- def with_file_extension(name, entry_type)
93
- return name unless File.extname(name.to_s).empty?
94
-
95
- extension = extension_for_type(entry_type)
96
- extension ? "#{ name }.#{ extension }" : name
97
- end
98
-
99
- # Internal: Scopes the paths in the manifest to the output folder in public.
100
- def within_public_output_dir(path)
101
- "/#{ config.public_output_dir.join(path) }"
102
- end
103
-
104
- # Internal: Allows to receive :javascript and :stylesheet as :type in helpers.
105
- def extension_for_type(entry_type)
106
- case entry_type
107
- when :javascript then 'js'
108
- when :stylesheet then 'css'
109
- when :typescript then dev_server_running? ? 'ts' : 'js'
110
- else entry_type
111
- end
112
- end
113
-
114
- # Internal: Raises a detailed message when an entry is missing in the manifest.
115
- def missing_entry_error(name, type: nil, **_options)
116
- file_name = with_file_extension(name, type)
117
- raise ViteRails::Manifest::MissingEntryError, <<~MSG
118
- Vite Rails can't find #{ file_name } in #{ config.manifest_path }.
119
-
120
- Possible causes:
121
- #{ missing_entry_causes.map { |cause| "\t- #{ cause }" }.join("\n") }
122
-
123
- Your manifest contains:
124
- #{ JSON.pretty_generate(@manifest) }
125
- MSG
126
- end
127
-
128
- def missing_entry_causes
129
- local = config.auto_build
130
- [
131
- (dev_server_running? && 'Vite has not yet re-built your latest changes.'),
132
- (local && !dev_server_running? && "\"autoBuild\": false in your #{ config.mode } configuration."),
133
- (local && !dev_server_running? && 'The Vite development server has crashed or is no longer available.'),
134
- 'You have misconfigured config/vite.json file.',
135
- (!local && 'Assets have not been precompiled'),
136
- ].compact
137
- rescue StandardError
138
- []
139
- end
140
- 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,16 +0,0 @@
1
- {
2
- "name": "only-for-workflows",
3
- "version": "unknown",
4
- "scripts": {
5
- "docs": "npm -C docs run docs",
6
- "docs:build": "npm -C docs run docs:build",
7
- "docs:search": "npm -C docs run docs:search",
8
- "docs:lint": "npm -C docs run lint",
9
- "lint": "npm -C package run lint",
10
- "test": "npm -C package run test"
11
- },
12
- "dependencies": {
13
- "vite": "^2.0.0-beta.34",
14
- "vite-plugin-ruby": "^1.0.4"
15
- }
16
- }
@@ -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