vite_rails 1.0.10 → 2.0.2

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