vite_rb 0.0.1.alpha1

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 (127) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +3 -0
  3. data/.dockerignore +22 -0
  4. data/.github/FUNDING.yml +1 -0
  5. data/.github/workflows/build.yml +17 -0
  6. data/.gitignore +71 -0
  7. data/.ruby-version +1 -0
  8. data/.solargraph.yml +16 -0
  9. data/.standard.yml +11 -0
  10. data/CHANGELOG.md +65 -0
  11. data/Gemfile +8 -0
  12. data/LICENSE.txt +21 -0
  13. data/README.md +258 -0
  14. data/Rakefile +39 -0
  15. data/bin/console +15 -0
  16. data/bin/setup +8 -0
  17. data/examples/rails-without-webpack/.gitignore +34 -0
  18. data/examples/rails-without-webpack/.ruby-version +1 -0
  19. data/examples/rails-without-webpack/Gemfile +33 -0
  20. data/examples/rails-without-webpack/README.md +24 -0
  21. data/examples/rails-without-webpack/Rakefile +6 -0
  22. data/examples/rails-without-webpack/app/assets/config/manifest.js +2 -0
  23. data/examples/rails-without-webpack/app/assets/images/.keep +0 -0
  24. data/examples/rails-without-webpack/app/assets/stylesheets/application.css +15 -0
  25. data/examples/rails-without-webpack/app/assets/stylesheets/static_pages.scss +3 -0
  26. data/examples/rails-without-webpack/app/channels/application_cable/channel.rb +4 -0
  27. data/examples/rails-without-webpack/app/channels/application_cable/connection.rb +4 -0
  28. data/examples/rails-without-webpack/app/channels/chat_channel.rb +12 -0
  29. data/examples/rails-without-webpack/app/controllers/application_controller.rb +2 -0
  30. data/examples/rails-without-webpack/app/controllers/concerns/.keep +0 -0
  31. data/examples/rails-without-webpack/app/controllers/static_pages_controller.rb +4 -0
  32. data/examples/rails-without-webpack/app/helpers/application_helper.rb +2 -0
  33. data/examples/rails-without-webpack/app/helpers/static_pages_helper.rb +2 -0
  34. data/examples/rails-without-webpack/app/jobs/application_job.rb +7 -0
  35. data/examples/rails-without-webpack/app/mailers/application_mailer.rb +4 -0
  36. data/examples/rails-without-webpack/app/models/application_record.rb +3 -0
  37. data/examples/rails-without-webpack/app/models/concerns/.keep +0 -0
  38. data/examples/rails-without-webpack/app/snowpacker/assets/fake-asset.png +0 -0
  39. data/examples/rails-without-webpack/app/snowpacker/channels/consumer.js +5 -0
  40. data/examples/rails-without-webpack/app/snowpacker/channels/index.js +2 -0
  41. data/examples/rails-without-webpack/app/snowpacker/entrypoints/application.js +10 -0
  42. data/examples/rails-without-webpack/app/snowpacker/javascript/index.js +1 -0
  43. data/examples/rails-without-webpack/app/snowpacker/stylesheets/index.css +3 -0
  44. data/examples/rails-without-webpack/app/views/layouts/application.html.erb +15 -0
  45. data/examples/rails-without-webpack/app/views/layouts/mailer.html.erb +13 -0
  46. data/examples/rails-without-webpack/app/views/layouts/mailer.text.erb +1 -0
  47. data/examples/rails-without-webpack/app/views/static_pages/index.html.erb +2 -0
  48. data/examples/rails-without-webpack/bin/bundle +114 -0
  49. data/examples/rails-without-webpack/bin/rails +9 -0
  50. data/examples/rails-without-webpack/bin/rake +9 -0
  51. data/examples/rails-without-webpack/bin/setup +36 -0
  52. data/examples/rails-without-webpack/bin/spring +17 -0
  53. data/examples/rails-without-webpack/bin/yarn +9 -0
  54. data/examples/rails-without-webpack/config.ru +5 -0
  55. data/examples/rails-without-webpack/config/application.rb +19 -0
  56. data/examples/rails-without-webpack/config/boot.rb +4 -0
  57. data/examples/rails-without-webpack/config/cable.yml +10 -0
  58. data/examples/rails-without-webpack/config/credentials.yml.enc +1 -0
  59. data/examples/rails-without-webpack/config/database.yml +25 -0
  60. data/examples/rails-without-webpack/config/environment.rb +5 -0
  61. data/examples/rails-without-webpack/config/environments/development.rb +62 -0
  62. data/examples/rails-without-webpack/config/environments/production.rb +112 -0
  63. data/examples/rails-without-webpack/config/environments/test.rb +49 -0
  64. data/examples/rails-without-webpack/config/initializers/application_controller_renderer.rb +8 -0
  65. data/examples/rails-without-webpack/config/initializers/assets.rb +14 -0
  66. data/examples/rails-without-webpack/config/initializers/backtrace_silencers.rb +7 -0
  67. data/examples/rails-without-webpack/config/initializers/content_security_policy.rb +31 -0
  68. data/examples/rails-without-webpack/config/initializers/cookies_serializer.rb +5 -0
  69. data/examples/rails-without-webpack/config/initializers/filter_parameter_logging.rb +4 -0
  70. data/examples/rails-without-webpack/config/initializers/inflections.rb +16 -0
  71. data/examples/rails-without-webpack/config/initializers/mime_types.rb +4 -0
  72. data/examples/rails-without-webpack/config/initializers/snowpacker.rb +41 -0
  73. data/examples/rails-without-webpack/config/initializers/wrap_parameters.rb +14 -0
  74. data/examples/rails-without-webpack/config/locales/en.yml +33 -0
  75. data/examples/rails-without-webpack/config/puma.rb +38 -0
  76. data/examples/rails-without-webpack/config/routes.rb +5 -0
  77. data/examples/rails-without-webpack/config/snowpacker/.browserslistrc +1 -0
  78. data/examples/rails-without-webpack/config/snowpacker/babel.config.js +76 -0
  79. data/examples/rails-without-webpack/config/snowpacker/postcss.config.js +12 -0
  80. data/examples/rails-without-webpack/config/snowpacker/snowpack.config.js +61 -0
  81. data/examples/rails-without-webpack/config/spring.rb +6 -0
  82. data/examples/rails-without-webpack/config/storage.yml +34 -0
  83. data/examples/rails-without-webpack/db/seeds.rb +7 -0
  84. data/examples/rails-without-webpack/lib/assets/.keep +0 -0
  85. data/examples/rails-without-webpack/lib/tasks/.keep +0 -0
  86. data/examples/rails-without-webpack/package.json +20 -0
  87. data/examples/rails-without-webpack/storage/.keep +0 -0
  88. data/examples/rails-without-webpack/test/application_system_test_case.rb +5 -0
  89. data/examples/rails-without-webpack/test/channels/application_cable/connection_test.rb +11 -0
  90. data/examples/rails-without-webpack/test/channels/chat_channel_test.rb +8 -0
  91. data/examples/rails-without-webpack/test/controllers/.keep +0 -0
  92. data/examples/rails-without-webpack/test/controllers/static_pages_controller_test.rb +8 -0
  93. data/examples/rails-without-webpack/test/fixtures/.keep +0 -0
  94. data/examples/rails-without-webpack/test/fixtures/files/.keep +0 -0
  95. data/examples/rails-without-webpack/test/helpers/.keep +0 -0
  96. data/examples/rails-without-webpack/test/integration/.keep +0 -0
  97. data/examples/rails-without-webpack/test/mailers/.keep +0 -0
  98. data/examples/rails-without-webpack/test/models/.keep +0 -0
  99. data/examples/rails-without-webpack/test/system/.keep +0 -0
  100. data/examples/rails-without-webpack/test/test_helper.rb +13 -0
  101. data/examples/rails-without-webpack/vendor/.keep +0 -0
  102. data/examples/rails-without-webpack/yarn.lock +7545 -0
  103. data/lib/tasks/rails.rake +31 -0
  104. data/lib/tasks/ruby.rake +21 -0
  105. data/lib/vite_rb.rb +25 -0
  106. data/lib/vite_rb/configuration.rb +56 -0
  107. data/lib/vite_rb/engine.rb +5 -0
  108. data/lib/vite_rb/env.rb +29 -0
  109. data/lib/vite_rb/generator.rb +81 -0
  110. data/lib/vite_rb/helpers.rb +51 -0
  111. data/lib/vite_rb/manifest.rb +40 -0
  112. data/lib/vite_rb/proxy.rb +35 -0
  113. data/lib/vite_rb/runner.rb +46 -0
  114. data/lib/vite_rb/templates/postcss.config.js +12 -0
  115. data/lib/vite_rb/templates/vite.config.js +71 -0
  116. data/lib/vite_rb/templates/vite.rb.tt +54 -0
  117. data/lib/vite_rb/templates/vite/channels/consumer.js +5 -0
  118. data/lib/vite_rb/templates/vite/channels/index.js +2 -0
  119. data/lib/vite_rb/templates/vite/entrypoints/application.js +10 -0
  120. data/lib/vite_rb/templates/vite/stylesheets/index.css +3 -0
  121. data/lib/vite_rb/utils.rb +55 -0
  122. data/lib/vite_rb/version.rb +5 -0
  123. data/package.json +25 -0
  124. data/package/src/index.js +0 -0
  125. data/vite_rb.gemspec +46 -0
  126. data/yarn.lock +1215 -0
  127. metadata +337 -0
@@ -0,0 +1,31 @@
1
+ namespace :vite do
2
+ task init: :environment do
3
+ Rake::Task["vite:init"].invoke
4
+ end
5
+
6
+ desc "Removes compiled assets"
7
+ task clobber: :environment do
8
+ build_dir = Rails.root.join(ViteRb.config.build_dir)
9
+ output_dir = File.join(build_dir, ViteRb.config.output_dir)
10
+ command = "rm -rf #{output_dir}"
11
+ logger = Logger.new(STDOUT)
12
+ logger.info(command)
13
+ system(command)
14
+ end
15
+
16
+ task build: :environment do
17
+ Rake::Task["vite:build"].invoke
18
+ end
19
+
20
+ task dev: :environment do
21
+ Rake::Task["vite:dev"].invoke
22
+ end
23
+ end
24
+
25
+ Rake::Task["assets:precompile"].enhance do
26
+ Rake::Task["vite:build"].invoke
27
+ end
28
+
29
+ Rake::Task["assets:clobber"].enhance do
30
+ Rake::Task["vite:clobber"].invoke
31
+ end
@@ -0,0 +1,21 @@
1
+ require "vite_rb/generator"
2
+
3
+ namespace :vite do
4
+ desc "initializes vite"
5
+ task :init do
6
+ ViteRb::Generator.init
7
+ end
8
+
9
+ desc "Compiles assets using snowpack bundler"
10
+ task :build do
11
+ ViteRb::Runner.build
12
+ end
13
+
14
+ desc "Compiles assets using snowpack bundler"
15
+ task compile: :build
16
+
17
+ desc "Run a snowpack dev server"
18
+ task :dev do
19
+ ViteRb::Runner.dev
20
+ end
21
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "vite_rb/configuration"
4
+ require "vite_rb/env"
5
+ require "vite_rb/generator"
6
+ require "vite_rb/helpers"
7
+ require "vite_rb/proxy"
8
+ require "vite_rb/utils"
9
+ require "vite_rb/manifest"
10
+
11
+ # ViteRb is the top-level module for interacting with the Vite ESM bundler.
12
+ module ViteRb
13
+ class << self
14
+ attr_accessor :config
15
+
16
+ def configure
17
+ self.config ||= Configuration.new
18
+ yield(config) if block_given?
19
+ end
20
+ end
21
+ end
22
+
23
+ require "vite_rb/version"
24
+ require "vite_rb/runner"
25
+ require "vite_rb/engine" if defined?(Rails)
@@ -0,0 +1,56 @@
1
+ module ViteRb
2
+ class Configuration
3
+ attr_accessor :config_path
4
+ attr_accessor :config_file
5
+ attr_accessor :babel_config_file
6
+ attr_accessor :postcss_config_file
7
+ attr_accessor :build_dir
8
+ attr_accessor :mount_path
9
+ attr_accessor :manifest_file
10
+ attr_accessor :output_dir
11
+ attr_accessor :port, :hostname
12
+
13
+ def initialize
14
+ yield(self) if block_given?
15
+ end
16
+
17
+
18
+ # Allows dynamic definition of getters and setters
19
+ # The setter must be the value used first.
20
+ # @example
21
+ # ViteRb.config.fake_attr # => Raises an error
22
+ # ViteRb.config.fake_attr = "stuff"
23
+ # ViteRb.config.fake_attr # => "stuff"
24
+ def method_missing(method_name, *args, &block)
25
+ # Check if the method missing an "attr=" method
26
+ raise unless method_name.to_s.end_with?("=")
27
+
28
+ setter = method_name
29
+ getter = method_name.to_s.slice(0...-1).to_sym
30
+ instance_var = "@#{getter}".to_sym
31
+
32
+ # attr_writer
33
+ define_singleton_method(setter) do |new_val|
34
+ instance_variable_set(instance_var, new_val)
35
+ end
36
+
37
+ # attr_reader
38
+ define_singleton_method(getter) { instance_variable_get(instance_var) }
39
+
40
+ # Ignores all arguments but the first one
41
+ value = args[0]
42
+
43
+ # Actually sets the value on the instance variable
44
+ send(setter, value)
45
+ rescue MethodMissing
46
+ # Raise error as normal, nothing to see here
47
+ super(method_name, *args, &block)
48
+ end
49
+
50
+ # rubocop:enable Style/MethodMissingSuper Metrics/MethodLength
51
+
52
+ def respond_to_missing?(method_name, include_private = false)
53
+ method_name.to_s.end_with?("=") || super
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,5 @@
1
+ # This is required for Rails to load our tasks.
2
+ module ViteRb
3
+ class Engine < ::Rails::Engine
4
+ end
5
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ViteR
4
+ # Sets the appropriately prefixed ENV variables with VITE_RB
5
+ class Env
6
+ ENV_PREFIX = 'VITE_RB'
7
+
8
+ class << self
9
+ def create_env_variables(config = ViteRb.config)
10
+ instance_variables.each do |var|
11
+ value = config.instance_variable_get(var)
12
+
13
+ # .slice removes the "@" from beginning of string
14
+ var = var.to_s.upcase.slice(1..-1)
15
+
16
+ set_env(var, value)
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def set_env(env_var, value)
23
+ return if value.nil?
24
+
25
+ ENV["#{ENV_PREFIX}_#{env_var}"] ||= value.to_s
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,81 @@
1
+ require "thor"
2
+ require "vite_rb/utils"
3
+
4
+ module ViteRb
5
+ class Generator < Thor::Group
6
+ include Thor::Actions
7
+ extend Utils
8
+
9
+ TEMPLATES = File.join(File.expand_path(__dir__), "templates")
10
+ CONFIG_FILES = %w[
11
+ vite.config.js
12
+ postcss.config.js
13
+ ]
14
+
15
+ def self.source_root
16
+ TEMPLATES
17
+ end
18
+
19
+ def create_initializer_file
20
+ target = "vite.rb"
21
+ source = "#{target}.tt"
22
+
23
+ destination = File.join("config", "initializers", target)
24
+
25
+ if Utils.rails?
26
+ destination = Rails.root.join("config", "initializers", target)
27
+ end
28
+
29
+ # Creates a config/initializers/vite.rb file
30
+ say "\n\nCreating initializer file at #{destination}...\n\n", :magenta
31
+ template source, destination
32
+ end
33
+
34
+ def create_config_files
35
+ destination = File.join("config", "vite")
36
+
37
+ if Utils.rails?
38
+ destination = Rails.root.join("config", "vite")
39
+ end
40
+
41
+ Rake.mkdir_p destination
42
+
43
+ say "\n\nCreating config files @ #{destination}...\n\n", :magenta
44
+ CONFIG_FILES.each do |filename|
45
+ template filename, File.join(destination, filename)
46
+ end
47
+ end
48
+
49
+ def create_vite_files
50
+ destination = File.join("app", "vite")
51
+
52
+ if Utils.rails?
53
+ destination = Rails.root.join("app", "vite")
54
+ end
55
+ say "\n\nCreating vite files...\n\n", :magenta
56
+
57
+ directory "vite", destination
58
+ end
59
+
60
+ def init
61
+ create_initializer_file
62
+ create_config_files
63
+ create_vite_files
64
+ add_vite
65
+
66
+ say "Finished initializing vite", :green
67
+ end
68
+
69
+ def add_vite
70
+ if ENV["VITE_RB_TEST"] == "true"
71
+ return system("yarn add vite_rb file:../../")
72
+ end
73
+
74
+ system("yarn add vite_rb")
75
+ end
76
+
77
+ def self.init
78
+ new.init
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,51 @@
1
+ require "vite_rb/utils"
2
+
3
+ module ViteRb
4
+ module Helpers
5
+ # Injects an HMR tag during development via a websocket.
6
+ def vite_hmr_tag
7
+ return unless Rails.env == "development"
8
+
9
+ hostname = ViteRb
10
+ port = ViteRb
11
+
12
+ hmr = %(window.HMR_WEBSOCKET_URL = "ws:#{hostname}:#{port}")
13
+
14
+ return tag.script(hmr.html_safe) if Utils.rails?
15
+
16
+ hmr
17
+ end
18
+
19
+ def vite_asset_path(name, **options)
20
+ asset_path(File.join(vite_dir, name), options)
21
+ end
22
+
23
+ def javascript_vite_tag(name, **options)
24
+ options[:type] ||= "module"
25
+
26
+ if Utils.dev_server_running?
27
+ javascript_include_tag("/#{vite_dir}/#{entrypoints_dir}/#{name}", options)
28
+ end
29
+
30
+ ## TODO: Change to reading from manifest for production
31
+ javascript_include_tag("/#{vite_dir}/#{entrypoints_dir}/#{name}", options)
32
+ end
33
+
34
+ # Returns nothing when not in production. CSS only gets extracted
35
+ # during the final build.
36
+ def stylesheet_vite_tag(name, **options)
37
+ return unless Rails.env == "development"
38
+
39
+ options[:media] ||= "screen"
40
+ stylesheet_link_tag("/#{vite_dir}/#{name}", options)
41
+ end
42
+
43
+ def vite_dir
44
+ ViteRb
45
+ end
46
+
47
+ def entrypoints_dir
48
+ ViteRb
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,40 @@
1
+ require "json"
2
+
3
+ module ViteRb
4
+ module Manifest
5
+ VALID_TYPES = [:js, :"js.map", :css, :"css.map"]
6
+ class << self
7
+ attr_accessor :manifest_hash
8
+
9
+ def reload_manifest(manifest_file = ViteRb.config.manifest_file)
10
+ @manifest_hash = load_manifest(manifest_file)
11
+ end
12
+
13
+ def find_entrypoint(file_name, type)
14
+ @manifest_hash[:entrypoints][file_name.to_sym][type.to_sym]
15
+ end
16
+
17
+ def find_file(file_name)
18
+ @manifest_hash[file_name.to_sym]
19
+ end
20
+
21
+ def find_chunk(chunk_name)
22
+ @manifest_hash[:chunks][chunk_name.to_sym][:js]
23
+ end
24
+
25
+ private
26
+
27
+ # rubocop:disable Naming/MemoizedInstanceVariableName
28
+ def load_manifest(manifest_file = ViteRb.config.manifest_file)
29
+ @manifest_hash ||= JSON.parse(File.read(manifest_file), symbolize_names: true)
30
+ end
31
+ # rubocop:enable Naming/MemoizedInstanceVariableName
32
+
33
+ def valid_type?(type)
34
+ return true if VALID_TYPES.include?(type)
35
+
36
+ false
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rack/proxy"
4
+ require "socket"
5
+ require "vite_rb/utils"
6
+
7
+ module ViteRb
8
+ # Proxy server for Vite
9
+ class Proxy < Rack::Proxy
10
+ def initialize(app = nil, opts = {})
11
+ opts[:streaming] = false if Rails.env.test? && !opts.key?(:streaming)
12
+ super
13
+ end
14
+
15
+ def perform_request(env)
16
+ output_dir = %r{/#{ViteRb.config.output_dir}/}
17
+
18
+ if env["PATH_INFO"].start_with?(output_dir) && Utils.dev_server_running?
19
+ env["HTTP_HOST"] = env["HTTP_X_FORWARDED_HOST"] = ViteRb
20
+ env["HTTP_X_FORWARDED_SERVER"] = Utils.host_with_port
21
+ env["HTTP_PORT"] = env["HTTP_X_FORWARDED_PORT"] = ViteRb
22
+ env["HTTP_X_FORWARDED_PROTO"] = env["HTTP_X_FORWARDED_SCHEME"] = "http"
23
+
24
+ unless Utils.https?
25
+ env["HTTPS"] = env["HTTP_X_FORWARDED_SSL"] = "off"
26
+ end
27
+
28
+ env["SCRIPT_NAME"] = ""
29
+ super(env)
30
+ else
31
+ @app.call(env)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "socket"
4
+ require "vite_rb/env"
5
+ require "vite_rb/utils"
6
+ require "thor"
7
+
8
+ module ViteRb
9
+ class Runner < Thor::Group
10
+ include ::Thor::Actions
11
+
12
+ attr_reader :config_file
13
+
14
+ def initialize
15
+ Env.create_env_variables
16
+ rescue Errno::ENOENT, NoMethodError
17
+ $stdout.puts "Vite configuration not found in #{ViteRb.config.config_dir}"
18
+ $stdout.puts "Please run bundle exec rails generate vite_rb to install Vite"
19
+ exit!
20
+ end
21
+
22
+ class << self
23
+ # Build for production
24
+ def build
25
+ new
26
+ vite_rb_command(env: :production, cmd: :build)
27
+ end
28
+
29
+ # Serve for development
30
+ def dev
31
+ Utils.detect_port!
32
+ new
33
+ vite_rb_command(env: :development, cmd: :dev)
34
+ end
35
+
36
+ private
37
+
38
+ def vite_rb_command(env: "", cmd: "")
39
+ env = ENV["NODE_ENV"] || env
40
+ config_file = ViteRb
41
+ command = "NODE_ENV=#{env} yarn run vite #{cmd} --config #{config_file}"
42
+ Rake.sh(command)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,12 @@
1
+ module.exports = {
2
+ plugins: [
3
+ require('postcss-import'),
4
+ require('postcss-flexbugs-fixes'),
5
+ require('postcss-preset-env')({
6
+ autoprefixer: {
7
+ flexbox: 'no-2009'
8
+ },
9
+ stage: 3
10
+ })
11
+ ]
12
+ }