hotwire-livereload 1.3.1 → 1.4.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 42f6430166f2bcdcb52940e92965a5e1d202c57b09966ddb72f76b746918b473
4
- data.tar.gz: be8743a9b6cbced10614d8fb4fc9cae8306c4355648175a91ed716a763722453
3
+ metadata.gz: 76c9e1c7f17f98e067a076d8dfc624d03aa1a7a64784da9fdde0b59f211bebe5
4
+ data.tar.gz: 3fa02e7e5a7592c61be7db173ff945f9d2f6da2e29ba4a777072702619b54473
5
5
  SHA512:
6
- metadata.gz: 909b0a55ec3d9d4dcbb0f7536e72c380a2d2d8e885cc5d988fe64f91771b759a2809d65f3fad8e500e565a51620532ae1b43c338880c7da977f396852f3b2d6b
7
- data.tar.gz: 90116c0e4b698346603d398cc3a4c7dd6616403f6caae041a014251ea24f57a5e36f83bc6e8554d1c65b21e36e92592c9a583f2f14ca042f357a7d324ecbff8d
6
+ metadata.gz: 760b3adbb7ef2bc0231f8e90f7ec3b5bfabbc2c01965518d1c69ab9885b0974cbdf0551d1f44e72a498917c55f790947fbad61ec1267973ac139ff85704c2a2f
7
+ data.tar.gz: 449e13ba3578d4fcc8e41e4939abecd29ee1a9673cdeaa7a0da24090c31de249868ae7c6541ed37c181cc4a4a23a40c6ee04f83b6922b65be3d9b0d92131d44c
data/README.md CHANGED
@@ -20,7 +20,7 @@ Run installer:
20
20
  rails livereload:install
21
21
  ```
22
22
 
23
- Folders listened by default:
23
+ Folders watched by default:
24
24
  - `app/views`
25
25
  - `app/helpers`
26
26
  - `app/javascript`
@@ -32,8 +32,16 @@ Folders listened by default:
32
32
 
33
33
  The gem detects if you use [`jsbundling-rails`](https://github.com/rails/jsbundling-rails) or [`cssbundling-rails`](https://github.com/rails/cssbundling-rails) and watches for changes in their output folder `app/assets/builds` automatically.
34
34
 
35
+ In your layout, make sure you don't `turbo-track` your JS/CSS in development:
36
+ ```diff
37
+ + <%= stylesheet_link_tag "application", "data-turbo-track": Rails.env.production? ? "reload" : "" %>
38
+ - <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
39
+ ```
40
+
35
41
  ## Configuration
36
42
 
43
+ ### Listen paths
44
+
37
45
  You can watch for changes in additional folders by adding them to `listen_paths`:
38
46
  ```ruby
39
47
  # config/environments/development.rb
@@ -44,6 +52,16 @@ Rails.application.configure do
44
52
  end
45
53
  ```
46
54
 
55
+ You can skip one or few default listen paths:
56
+ ```ruby
57
+ # config/environments/development.rb
58
+
59
+ Rails.application.configure do
60
+ # ...
61
+ config.hotwire_livereload.skip_listen_paths << Rails.root.join("app/views")
62
+ end
63
+ ```
64
+
47
65
  You can disable default listen paths and fully override them:
48
66
  ```ruby
49
67
  # config/environments/development.rb
@@ -58,6 +76,8 @@ Rails.application.configure do
58
76
  end
59
77
  ```
60
78
 
79
+ ### Force reload
80
+
61
81
  If you don't have `data-turbo-track="reload"` attribute on your JS and CSS bundles you might need to setup force reloading. This will trigger full browser reloading for JS and CSS files only:
62
82
  ```ruby
63
83
  # config/environments/development.rb
@@ -69,6 +89,8 @@ Rails.application.configure do
69
89
  end
70
90
  ```
71
91
 
92
+ ### Reload method
93
+
72
94
  Instead of a direct ActionCable websocket connection, you can reuse the existing TurboStream websocket connection and send updates using standard turbo-streams:
73
95
  ```ruby
74
96
  # config/environments/development.rb
@@ -90,6 +112,37 @@ In that case you need to place `hotwire_livereload_tags` helper in your layout *
90
112
  </head>
91
113
  ```
92
114
 
115
+ ### Listen options
116
+
117
+ [Listen gem](https://github.com/guard/listen), which is used for file system monitoring, accepts [options](https://github.com/guard/listen?tab=readme-ov-file#options) like enabling a fallback mechanism called "polling" to detect file changes.
118
+
119
+ By default, Listen uses a more efficient mechanism called "native" which relies on the operating system's file system events to detect changes. However, in some cases, such as when working with network-mounted file systems or in certain virtualized environments, the native mechanism may not work reliably. In such cases, enabling force_polling ensures that file changes are still detected, albeit with a slightly higher resource usage.
120
+
121
+ You may use listen_options to pass these options like:
122
+ ```ruby
123
+ # config/environments/development.rb
124
+
125
+ Rails.application.configure do
126
+ # ...
127
+ config.hotwire_livereload.listen_options[:force_polling] = true
128
+ end
129
+ ```
130
+
131
+ ### Listen debounce delay
132
+
133
+ If your app uses TailwindCSS or similar that compiles your CSS from looking at your templates, you can end up in a situation, where updating a template triggers twice for changes; once for the template and once for the rebuilt CSS. This can lead to unreliable reloads, ie. the reload happening before the CSS is built.
134
+
135
+ To avoid this, you can add a debounce delay to the file watcher:
136
+
137
+ ```ruby
138
+ # config/environments/development.rb
139
+
140
+ Rails.application.configure do
141
+ # ...
142
+ config.hotwire_livereload.debounce_delay_ms = 300 # in milliseconds
143
+ end
144
+ ```
145
+
93
146
  ## Disable livereload
94
147
 
95
148
  To temporarily disable livereload use:
@@ -115,6 +115,7 @@
115
115
  } else {
116
116
  console.log("[Hotwire::Livereload] Files changed. Reloading..");
117
117
  hotwire_livereload_scroll_position_default.save();
118
+ Turbo.cache.clear();
118
119
  Turbo.visit(window.location.href, { action: "replace" });
119
120
  }
120
121
  }, 300);
@@ -697,6 +697,7 @@
697
697
  } else {
698
698
  console.log("[Hotwire::Livereload] Files changed. Reloading..");
699
699
  hotwire_livereload_scroll_position_default.save();
700
+ Turbo.cache.clear();
700
701
  Turbo.visit(window.location.href, { action: "replace" });
701
702
  }
702
703
  }, 300);
@@ -10,6 +10,7 @@ export default debounce(({force_reload}) => {
10
10
  } else {
11
11
  console.log("[Hotwire::Livereload] Files changed. Reloading..")
12
12
  scrollPosition.save()
13
+ Turbo.cache.clear()
13
14
  Turbo.visit(window.location.href, { action: 'replace' })
14
15
  }
15
16
  }, 300)
@@ -8,6 +8,7 @@ module Hotwire
8
8
  isolate_namespace Hotwire::Livereload
9
9
  config.hotwire_livereload = ActiveSupport::OrderedOptions.new
10
10
  config.hotwire_livereload.listen_paths ||= []
11
+ config.hotwire_livereload.skip_listen_paths ||= []
11
12
  config.hotwire_livereload.force_reload_paths ||= []
12
13
  config.hotwire_livereload.reload_method = :action_cable
13
14
  config.hotwire_livereload.disable_default_listeners = false
@@ -15,6 +16,8 @@ module Hotwire
15
16
  #{root}/app/channels
16
17
  #{root}/app/helpers
17
18
  ]
19
+ config.hotwire_livereload.listen_options ||= {}
20
+ config.hotwire_livereload.debounce_delay_ms = 0
18
21
 
19
22
  initializer "hotwire_livereload.assets" do
20
23
  if Rails.application.config.respond_to?(:assets)
@@ -30,6 +33,7 @@ module Hotwire
30
33
 
31
34
  initializer "hotwire_livereload.set_configs" do |app|
32
35
  options = app.config.hotwire_livereload
36
+ skip_listen_paths = options.skip_listen_paths.map(&:to_s).uniq
33
37
 
34
38
  unless options.disable_default_listeners
35
39
  default_listen_paths = %w[
@@ -54,16 +58,25 @@ module Hotwire
54
58
  .uniq
55
59
  .map { |p| Rails.root.join(p) }
56
60
  .select { |p| Dir.exist?(p) }
61
+ .reject { |p| skip_listen_paths.include?(p.to_s) }
57
62
  end
58
63
  end
59
64
 
60
65
  config.after_initialize do |app|
61
66
  if Rails.env.development? && Hotwire::Livereload.server_process?
67
+ @trigger_reload = (Hotwire::Livereload.debounce(config.hotwire_livereload.debounce_delay_ms) do |options|
68
+ if config.hotwire_livereload.reload_method == :turbo_stream
69
+ Hotwire::Livereload.turbo_stream(options)
70
+ else
71
+ Hotwire::Livereload.action_cable(options)
72
+ end
73
+ end)
74
+
62
75
  options = app.config.hotwire_livereload
63
76
  listen_paths = options.listen_paths.map(&:to_s).uniq
64
77
  force_reload_paths = options.force_reload_paths.map(&:to_s).uniq.join("|")
65
78
 
66
- @listener = Listen.to(*listen_paths) do |modified, added, removed|
79
+ @listener = Listen.to(*listen_paths, **config.hotwire_livereload.listen_options) do |modified, added, removed|
67
80
  unless File.exist?(DISABLE_FILE)
68
81
  changed = [modified, removed, added].flatten.uniq
69
82
  next unless changed.any?
@@ -73,11 +86,7 @@ module Hotwire
73
86
  end
74
87
 
75
88
  options = {changed: changed, force_reload: force_reload}
76
- if config.hotwire_livereload.reload_method == :turbo_stream
77
- Hotwire::Livereload.turbo_stream(options)
78
- else
79
- Hotwire::Livereload.action_cable(options)
80
- end
89
+ @trigger_reload.call(options)
81
90
  end
82
91
  end
83
92
  @listener.start
@@ -110,5 +119,27 @@ module Hotwire
110
119
 
111
120
  puma_process || rails_server
112
121
  end
122
+
123
+ def self.debounce(wait_ms, &block)
124
+ if wait_ms.zero?
125
+ return ->(*args) { yield(*args) }
126
+ end
127
+
128
+ mutex = Mutex.new
129
+ timer_thread = nil
130
+ seconds = wait_ms.to_f / 1000.0
131
+
132
+ lambda do |*args|
133
+ mutex.synchronize do
134
+ # Cancel previous timer
135
+ timer_thread&.kill
136
+
137
+ timer_thread = Thread.new do
138
+ sleep(seconds)
139
+ yield(*args)
140
+ end
141
+ end
142
+ end
143
+ end
113
144
  end
114
145
  end
@@ -1,5 +1,5 @@
1
1
  module Hotwire
2
2
  module Livereload
3
- VERSION = "1.3.1"
3
+ VERSION = "1.4.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hotwire-livereload
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kirill Platonov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-01-04 00:00:00.000000000 Z
11
+ date: 2024-04-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties