vite_ruby 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +3 -0
- data/CONTRIBUTING.md +33 -0
- data/LICENSE.txt +21 -0
- data/README.md +82 -0
- data/default.vite.json +17 -0
- data/exe/vite +10 -0
- data/lib/tasks/vite.rake +51 -0
- data/lib/vite_ruby.rb +125 -0
- data/lib/vite_ruby/builder.rb +103 -0
- data/lib/vite_ruby/cli.rb +14 -0
- data/lib/vite_ruby/cli/build.rb +18 -0
- data/lib/vite_ruby/cli/dev.rb +12 -0
- data/lib/vite_ruby/cli/install.rb +122 -0
- data/lib/vite_ruby/cli/version.rb +9 -0
- data/lib/vite_ruby/commands.rb +153 -0
- data/lib/vite_ruby/config.rb +152 -0
- data/lib/vite_ruby/dev_server_proxy.rb +62 -0
- data/lib/vite_ruby/manifest.rb +168 -0
- data/lib/vite_ruby/runner.rb +57 -0
- data/lib/vite_ruby/version.rb +5 -0
- data/templates/config/vite.config.ts +8 -0
- data/templates/config/vite.json +15 -0
- data/templates/entrypoints/application.js +8 -0
- metadata +153 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 522fa472785527e2ee77fac1df4b7471a7d9dbce81ac768f0723604389151d74
|
4
|
+
data.tar.gz: 7e080892e4b503768b43d04cd9c562c655ff76cb939ceb956b72e278500994fe
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 14cc69c07939b2b67a0bb1f7a2ef3db95373f2ab12e83bf826ade50ceb877ff7d25db823c8b928247c7e81ee8a50e556c213806317a64c09a77c4c88a4f68c62
|
7
|
+
data.tar.gz: e41055b2a38e7e24ee8ba3a9f942448068f427187f8c300d6a3721a295573937a08c956307d9a4246d30a440e00ec015815e45ee2a8aef49d2790e7e0004164f
|
data/CHANGELOG.md
ADDED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
## Setting Up a Development Environment
|
2
|
+
|
3
|
+
1. Install [Yarn](https://yarnpkg.com/)
|
4
|
+
|
5
|
+
2. Run the following commands to set up the development environment.
|
6
|
+
|
7
|
+
```
|
8
|
+
bundle install
|
9
|
+
```
|
10
|
+
|
11
|
+
## Making sure your changes pass all tests
|
12
|
+
There are a number of automated checks which run on GitHub Actions when a pull request is created.
|
13
|
+
You can run those checks on your own locally to make sure that your changes would not break the CI build.
|
14
|
+
|
15
|
+
### 1. Check the code for JavaScript style violations
|
16
|
+
```
|
17
|
+
yarn lint
|
18
|
+
```
|
19
|
+
|
20
|
+
### 2. Check the code for Ruby style violations
|
21
|
+
```
|
22
|
+
bundle exec rubocop
|
23
|
+
```
|
24
|
+
|
25
|
+
### 3. Run the JavaScript test suite
|
26
|
+
```
|
27
|
+
yarn test
|
28
|
+
```
|
29
|
+
|
30
|
+
### 4. Run the Ruby test suite
|
31
|
+
```
|
32
|
+
bundle exec rake test
|
33
|
+
```
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2020 Maximo Mussini
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
<h1 align="center">
|
2
|
+
<a href="https://vite-rails.netlify.app/">
|
3
|
+
<img src="https://raw.githubusercontent.com/ElMassimo/vite_rails/main/docs/public/logo.svg" width="120px"/>
|
4
|
+
</a>
|
5
|
+
|
6
|
+
<br>
|
7
|
+
|
8
|
+
<a href="https://vite-rails.netlify.app/">
|
9
|
+
Vite Ruby
|
10
|
+
</a>
|
11
|
+
|
12
|
+
<br>
|
13
|
+
|
14
|
+
<p align="center">
|
15
|
+
<a href="https://github.com/ElMassimo/vite_rails/actions">
|
16
|
+
<img alt="Build Status" src="https://github.com/ElMassimo/vite_rails/workflows/build/badge.svg"/>
|
17
|
+
</a>
|
18
|
+
<a href="https://codeclimate.com/github/ElMassimo/vite_rails">
|
19
|
+
<img alt="Maintainability" src="https://codeclimate.com/github/ElMassimo/vite_rails/badges/gpa.svg"/>
|
20
|
+
</a>
|
21
|
+
<a href="https://codeclimate.com/github/ElMassimo/vite_rails">
|
22
|
+
<img alt="Test Coverage" src="https://codeclimate.com/github/ElMassimo/vite_rails/badges/coverage.svg"/>
|
23
|
+
</a>
|
24
|
+
<a href="https://rubygems.org/gems/vite_ruby">
|
25
|
+
<img alt="Gem Version" src="https://img.shields.io/gem/v/vite_ruby.svg?colorB=e9573f"/>
|
26
|
+
</a>
|
27
|
+
<a href="https://github.com/ElMassimo/vite_rails/blob/master/LICENSE.txt">
|
28
|
+
<img alt="License" src="https://img.shields.io/badge/license-MIT-428F7E.svg"/>
|
29
|
+
</a>
|
30
|
+
</p>
|
31
|
+
</h1>
|
32
|
+
|
33
|
+
[website]: https://vite-rails.netlify.app/
|
34
|
+
[configuration reference]: https://vite-rails.netlify.app/config/
|
35
|
+
[features]: https://vite-rails.netlify.app/guide/introduction.html
|
36
|
+
[guides]: https://vite-rails.netlify.app/guide/
|
37
|
+
[config]: https://vite-rails.netlify.app/config/
|
38
|
+
[vite_rails]: https://github.com/ElMassimo/vite_rails
|
39
|
+
[webpacker]: https://github.com/rails/webpacker
|
40
|
+
[vite]: http://vitejs.dev/
|
41
|
+
[config file]: https://github.com/ElMassimo/vite_rails/blob/main/vite-plugin-ruby/default.vite.json
|
42
|
+
[example app]: https://github.com/ElMassimo/pingcrm-vite
|
43
|
+
[heroku]: https://pingcrm-vite.herokuapp.com/
|
44
|
+
[Issues]: https://github.com/ElMassimo/vite_rails/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc
|
45
|
+
[Discussions]: https://github.com/ElMassimo/vite_rails/discussions
|
46
|
+
[vite_rails]: https://github.com/ElMassimo/vite_rails/tree/main/vite_rails
|
47
|
+
[vite_ruby]: https://github.com/ElMassimo/vite_rails/tree/main/vite_ruby
|
48
|
+
[vite_hanami]: https://github.com/ElMassimo/vite_rails/tree/main/vite_hanami
|
49
|
+
|
50
|
+
|
51
|
+
[Vite] is to frontend tooling as Ruby to programming, pure joy! 😍
|
52
|
+
|
53
|
+
This is the core library for Rack apps, used by [<kbd>vite_rails</kbd>][vite_rails] and [<kbd>vite_hanami</kbd>][vite_hanami].
|
54
|
+
|
55
|
+
## Features ⚡️
|
56
|
+
|
57
|
+
- 💡 Instant server start
|
58
|
+
- ⚡️ Blazing fast hot reload
|
59
|
+
- 🚀 Zero-config deployments
|
60
|
+
- 🤝 Integrated with <kbd>assets:precompile</kbd>
|
61
|
+
- [And more!][features]
|
62
|
+
|
63
|
+
## Documentation 📖
|
64
|
+
|
65
|
+
Visit the [documentation website][website] to check out the [guides] and searchable [configuration reference].
|
66
|
+
|
67
|
+
## Contact ✉️
|
68
|
+
|
69
|
+
Please use [Issues] to report bugs you find, and [Discussions] to make feature requests or get help.
|
70
|
+
|
71
|
+
Don't hesitate to _⭐️ star the project_ if you find it useful!
|
72
|
+
|
73
|
+
|
74
|
+
## Special Thanks 🙏
|
75
|
+
|
76
|
+
- [webpacker]
|
77
|
+
- [vite]
|
78
|
+
|
79
|
+
|
80
|
+
## License
|
81
|
+
|
82
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/default.vite.json
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
{
|
2
|
+
"assetHost": null,
|
3
|
+
"assetsDir": "assets",
|
4
|
+
"autoBuild": false,
|
5
|
+
"buildCacheDir": "tmp/cache/vite",
|
6
|
+
"publicOutputDir": "vite",
|
7
|
+
"configPath": "config/vite.json",
|
8
|
+
"devServerConnectTimeout": 0.01,
|
9
|
+
"publicDir": "public",
|
10
|
+
"entrypointsDir": "entrypoints",
|
11
|
+
"sourceCodeDir": "app/frontend",
|
12
|
+
"host": "localhost",
|
13
|
+
"https": null,
|
14
|
+
"port": 3036,
|
15
|
+
"hideBuildConsoleOutput": false,
|
16
|
+
"watchAdditionalPaths": []
|
17
|
+
}
|
data/exe/vite
ADDED
data/lib/tasks/vite.rake
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$stdout.sync = true
|
4
|
+
|
5
|
+
require 'rake'
|
6
|
+
|
7
|
+
namespace :vite do
|
8
|
+
task :binstubs do
|
9
|
+
ViteRuby.commands.install_binstubs
|
10
|
+
end
|
11
|
+
|
12
|
+
desc 'Compile JavaScript packs using vite for production with digests'
|
13
|
+
task build: :'vite:verify_install' do
|
14
|
+
ViteRuby.commands.build_from_task
|
15
|
+
end
|
16
|
+
|
17
|
+
desc 'Remove old compiled vites'
|
18
|
+
task :clean, [:keep, :age] => :'vite:verify_install' do |_, args|
|
19
|
+
ViteRuby.commands.clean_from_task(args)
|
20
|
+
end
|
21
|
+
|
22
|
+
desc 'Remove the vite build output directory'
|
23
|
+
task clobber: :'vite:verify_install' do
|
24
|
+
ViteRuby.commands.clobber
|
25
|
+
$stdout.puts "Removed vite build output directory #{ ViteRuby.config.build_output_dir }"
|
26
|
+
end
|
27
|
+
|
28
|
+
desc 'Verifies if ViteRuby is properly installed in this application'
|
29
|
+
task :verify_install do
|
30
|
+
ViteRuby.commands.verify_install
|
31
|
+
end
|
32
|
+
|
33
|
+
desc 'Install all JavaScript dependencies'
|
34
|
+
task :install_dependencies do
|
35
|
+
system({ 'NODE_ENV' => 'development' }, 'npx ci')
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "Provide information on ViteRuby's environment"
|
39
|
+
task :info do
|
40
|
+
ViteRuby.commands.print_info
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
if Rake::Task.task_defined?('assets:precompile')
|
45
|
+
Rake::Task['assets:precompile'].enhance do |task|
|
46
|
+
prefix = task.name.split(/#|assets:precompile/).first
|
47
|
+
Rake::Task["#{ prefix }vite:build"].invoke
|
48
|
+
end
|
49
|
+
else
|
50
|
+
Rake::Task.define_task('assets:precompile' => ['vite:install_dependencies', 'vite:build'])
|
51
|
+
end
|
data/lib/vite_ruby.rb
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
require 'forwardable'
|
5
|
+
require 'pathname'
|
6
|
+
|
7
|
+
require 'zeitwerk'
|
8
|
+
loader = Zeitwerk::Loader.for_gem
|
9
|
+
loader.ignore("#{ __dir__ }/install")
|
10
|
+
loader.ignore("#{ __dir__ }/tasks")
|
11
|
+
loader.ignore("#{ __dir__ }/exe")
|
12
|
+
loader.inflector.inflect('cli' => 'CLI')
|
13
|
+
loader.setup
|
14
|
+
|
15
|
+
class ViteRuby
|
16
|
+
# Internal: Prefix used for environment variables that modify the configuration.
|
17
|
+
ENV_PREFIX = 'VITE_RUBY'
|
18
|
+
|
19
|
+
# Internal: Versions used by default when running `vite install`.
|
20
|
+
DEFAULT_VITE_VERSION = '^2.0.0-beta.65'
|
21
|
+
DEFAULT_PLUGIN_VERSION = '^1.0.8'
|
22
|
+
|
23
|
+
# Internal: Ruby Frameworks that have a companion library for Vite Ruby.
|
24
|
+
SUPPORTED_FRAMEWORKS = %w[rails hanami roda].freeze
|
25
|
+
|
26
|
+
class << self
|
27
|
+
extend Forwardable
|
28
|
+
|
29
|
+
def_delegators :instance, :config, :commands, :run_proxy?
|
30
|
+
def_delegators :config, :mode
|
31
|
+
def_delegators :commands, :build
|
32
|
+
def_delegators 'ViteRuby::Runner.new', :run
|
33
|
+
|
34
|
+
def instance
|
35
|
+
@instance ||= ViteRuby.new
|
36
|
+
end
|
37
|
+
|
38
|
+
# Public: Additional environment variables to pass to Vite.
|
39
|
+
#
|
40
|
+
# Example:
|
41
|
+
# ViteRuby.env['VITE_RUBY_CONFIG_PATH'] = 'config/alternate_vite.json'
|
42
|
+
def env
|
43
|
+
@env ||= load_env_variables
|
44
|
+
end
|
45
|
+
|
46
|
+
# Internal: Refreshes the manifest.
|
47
|
+
def bootstrap
|
48
|
+
instance.manifest.refresh
|
49
|
+
end
|
50
|
+
|
51
|
+
# Internal: Loads all available rake tasks.
|
52
|
+
def install_tasks
|
53
|
+
load File.expand_path('tasks/vite.rake', __dir__)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Internal: Refreshes the config after setting the env vars.
|
57
|
+
def reload_with(env_vars)
|
58
|
+
env.update(env_vars)
|
59
|
+
@instance = nil
|
60
|
+
config
|
61
|
+
end
|
62
|
+
|
63
|
+
# Internal: Allows to obtain any env variables for configuration options.
|
64
|
+
def load_env_variables
|
65
|
+
ENV.select { |key, _| key.start_with?(ENV_PREFIX) }
|
66
|
+
end
|
67
|
+
|
68
|
+
# Internal: Detects if the application has installed a framework-specific
|
69
|
+
# variant of Vite Ruby.
|
70
|
+
def framework_libraries
|
71
|
+
SUPPORTED_FRAMEWORKS.map { |framework|
|
72
|
+
if library = Gem.loaded_specs["vite_#{ framework }"]
|
73
|
+
[framework, library]
|
74
|
+
end
|
75
|
+
}.compact
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
attr_writer :logger
|
80
|
+
|
81
|
+
def logger
|
82
|
+
@logger ||= Logger.new($stdout)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Public: Returns true if the Vite development server is currently running.
|
86
|
+
# NOTE: Checks only once every second since every lookup calls this method.
|
87
|
+
def dev_server_running?
|
88
|
+
return false unless run_proxy?
|
89
|
+
return true if defined?(@running_at) && @running_at && Time.now - @running_at < 1
|
90
|
+
|
91
|
+
Socket.tcp(config.host, config.port, connect_timeout: config.dev_server_connect_timeout).close
|
92
|
+
@running_at = Time.now
|
93
|
+
true
|
94
|
+
rescue SystemCallError
|
95
|
+
@running_at = false
|
96
|
+
end
|
97
|
+
|
98
|
+
# Public: The proxy for assets should only run in development mode.
|
99
|
+
def run_proxy?
|
100
|
+
config.mode == 'development'
|
101
|
+
rescue StandardError => error
|
102
|
+
logger.error("Failed to check mode for Vite: #{ error.message }")
|
103
|
+
false
|
104
|
+
end
|
105
|
+
|
106
|
+
# Public: Keeps track of watched files and triggers builds as needed.
|
107
|
+
def builder
|
108
|
+
@builder ||= ViteRuby::Builder.new(self)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Internal: Helper to run commands related with Vite.
|
112
|
+
def commands
|
113
|
+
@commands ||= ViteRuby::Commands.new(self)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Public: Current instance configuration for Vite.
|
117
|
+
def config
|
118
|
+
@config ||= ViteRuby::Config.resolve_config
|
119
|
+
end
|
120
|
+
|
121
|
+
# Public: Enables looking up assets managed by Vite using name and type.
|
122
|
+
def manifest
|
123
|
+
@manifest ||= ViteRuby::Manifest.new(self)
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'digest/sha1'
|
4
|
+
|
5
|
+
# Public: Keeps track of watched files and triggers builds as needed.
|
6
|
+
class ViteRuby::Builder
|
7
|
+
def initialize(vite_ruby)
|
8
|
+
@vite_ruby = vite_ruby
|
9
|
+
end
|
10
|
+
|
11
|
+
# Public: Checks if the watched files have changed since the last compilation,
|
12
|
+
# and triggers a Vite build if any files have changed.
|
13
|
+
def build
|
14
|
+
if stale?
|
15
|
+
build_with_vite.tap { record_files_digest }
|
16
|
+
else
|
17
|
+
logger.debug 'Skipping build. Vite assets are already up-to-date ⚡️'
|
18
|
+
true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Public: Returns true if all the assets built by Vite are up to date.
|
23
|
+
def fresh?
|
24
|
+
previous_files_digest&.== watched_files_digest
|
25
|
+
end
|
26
|
+
|
27
|
+
# Public: Returns true if any of the assets built by Vite is out of date.
|
28
|
+
def stale?
|
29
|
+
!fresh?
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
extend Forwardable
|
35
|
+
|
36
|
+
def_delegators :@vite_ruby, :config, :logger
|
37
|
+
|
38
|
+
# Internal: Writes a digest of the watched files to disk for future checks.
|
39
|
+
def record_files_digest
|
40
|
+
config.build_cache_dir.mkpath
|
41
|
+
files_digest_path.write(watched_files_digest)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Internal: The path of where a digest of the watched files is stored.
|
45
|
+
def files_digest_path
|
46
|
+
config.build_cache_dir.join("last-compilation-digest-#{ config.mode }")
|
47
|
+
end
|
48
|
+
|
49
|
+
# Internal: Reads a digest of watched files from disk.
|
50
|
+
def previous_files_digest
|
51
|
+
files_digest_path.read if files_digest_path.exist? && config.manifest_path.exist?
|
52
|
+
rescue Errno::ENOENT, Errno::ENOTDIR
|
53
|
+
end
|
54
|
+
|
55
|
+
# Internal: Returns a digest of all the watched files, allowing to detect
|
56
|
+
# changes, and skip Vite builds if no files have changed.
|
57
|
+
def watched_files_digest
|
58
|
+
Dir.chdir File.expand_path(config.root) do
|
59
|
+
files = Dir[*watched_paths].reject { |f| File.directory?(f) }
|
60
|
+
file_ids = files.sort.map { |f| "#{ File.basename(f) }/#{ Digest::SHA1.file(f).hexdigest }" }
|
61
|
+
Digest::SHA1.hexdigest(file_ids.join('/'))
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Public: Initiates a Vite build command to generate assets.
|
66
|
+
#
|
67
|
+
# Returns true if the build is successful, or false if it failed.
|
68
|
+
def build_with_vite
|
69
|
+
logger.info 'Building with Vite ⚡️'
|
70
|
+
|
71
|
+
stdout, stderr, status = ViteRuby.run(['build'], capture: true)
|
72
|
+
log_build_result(stdout, stderr, status)
|
73
|
+
|
74
|
+
status.success?
|
75
|
+
end
|
76
|
+
|
77
|
+
# Internal: Outputs the build results.
|
78
|
+
#
|
79
|
+
# NOTE: By default it also outputs the manifest entries.
|
80
|
+
def log_build_result(stdout, stderr, status)
|
81
|
+
if status.success?
|
82
|
+
logger.info "Build with Vite complete: #{ config.build_output_dir }"
|
83
|
+
logger.error(stderr.to_s) unless stderr.empty?
|
84
|
+
logger.info(stdout) unless config.hide_build_console_output
|
85
|
+
else
|
86
|
+
non_empty_streams = [stdout, stderr].delete_if(&:empty?)
|
87
|
+
logger.error "Build with Vite failed:\n#{ non_empty_streams.join("\n\n") }"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# Internal: Files and directories that should be watched for changes.
|
92
|
+
#
|
93
|
+
# NOTE: You can specify additional ones in vite.json using "watchAdditionalPaths": [...]
|
94
|
+
def watched_paths
|
95
|
+
[
|
96
|
+
*config.watch_additional_paths,
|
97
|
+
"#{ config.source_code_dir }/**/*",
|
98
|
+
'yarn.lock',
|
99
|
+
'package.json',
|
100
|
+
config.config_path,
|
101
|
+
].freeze
|
102
|
+
end
|
103
|
+
end
|