vite_rails 1.0.12 → 2.0.0

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 +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