hotwire-livereload 1.3.2 → 1.4.1
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 +4 -4
- data/README.md +32 -1
- data/app/assets/javascripts/hotwire-livereload.js +57 -50
- data/app/javascript/hotwire-livereload.js +11 -1
- data/lib/hotwire/livereload/engine.rb +35 -5
- data/lib/hotwire/livereload/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 04b3a325fa089d62215f26cf3fbac951e3ac91d0b03af7aed02fa2a49075969e
|
4
|
+
data.tar.gz: 24e7339a71da29f35b1930f95f18f0c035aa0221b411fe4a58f27d10384dbb76
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 01e7cc071040c5fbafa3fac11adcdfff171695a82c6d6d90db06c8d2010032beb4172ae667b029512737c0afb79c005bcd2e54084661ff662bbae28157087a68
|
7
|
+
data.tar.gz: 41e86aa960b2796d65aa26e1d8034a819e5ecdfea578b5995e275f713d666f9b4ffd6a9c6337a6bf17834394ac194382aa2ddf9ff74843fb0f7644ed20bfd2fa
|
data/README.md
CHANGED
@@ -20,7 +20,7 @@ Run installer:
|
|
20
20
|
rails livereload:install
|
21
21
|
```
|
22
22
|
|
23
|
-
Folders
|
23
|
+
Folders watched by default:
|
24
24
|
- `app/views`
|
25
25
|
- `app/helpers`
|
26
26
|
- `app/javascript`
|
@@ -32,6 +32,12 @@ 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
|
|
37
43
|
### Listen paths
|
@@ -46,6 +52,16 @@ Rails.application.configure do
|
|
46
52
|
end
|
47
53
|
```
|
48
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
|
+
|
49
65
|
You can disable default listen paths and fully override them:
|
50
66
|
```ruby
|
51
67
|
# config/environments/development.rb
|
@@ -112,6 +128,21 @@ Rails.application.configure do
|
|
112
128
|
end
|
113
129
|
```
|
114
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
|
+
|
115
146
|
## Disable livereload
|
116
147
|
|
117
148
|
To temporarily disable livereload use:
|
@@ -396,19 +396,19 @@
|
|
396
396
|
this.subscriptions = subscriptions;
|
397
397
|
this.pendingSubscriptions = [];
|
398
398
|
}
|
399
|
-
SubscriptionGuarantor2.prototype.guarantee = function guarantee(
|
400
|
-
if (this.pendingSubscriptions.indexOf(
|
401
|
-
logger.log("SubscriptionGuarantor guaranteeing " +
|
402
|
-
this.pendingSubscriptions.push(
|
399
|
+
SubscriptionGuarantor2.prototype.guarantee = function guarantee(subscription2) {
|
400
|
+
if (this.pendingSubscriptions.indexOf(subscription2) == -1) {
|
401
|
+
logger.log("SubscriptionGuarantor guaranteeing " + subscription2.identifier);
|
402
|
+
this.pendingSubscriptions.push(subscription2);
|
403
403
|
} else {
|
404
|
-
logger.log("SubscriptionGuarantor already guaranteeing " +
|
404
|
+
logger.log("SubscriptionGuarantor already guaranteeing " + subscription2.identifier);
|
405
405
|
}
|
406
406
|
this.startGuaranteeing();
|
407
407
|
};
|
408
|
-
SubscriptionGuarantor2.prototype.forget = function forget(
|
409
|
-
logger.log("SubscriptionGuarantor forgetting " +
|
408
|
+
SubscriptionGuarantor2.prototype.forget = function forget(subscription2) {
|
409
|
+
logger.log("SubscriptionGuarantor forgetting " + subscription2.identifier);
|
410
410
|
this.pendingSubscriptions = this.pendingSubscriptions.filter(function(s) {
|
411
|
-
return s !==
|
411
|
+
return s !== subscription2;
|
412
412
|
});
|
413
413
|
};
|
414
414
|
SubscriptionGuarantor2.prototype.startGuaranteeing = function startGuaranteeing() {
|
@@ -422,9 +422,9 @@
|
|
422
422
|
var _this = this;
|
423
423
|
this.retryTimeout = setTimeout(function() {
|
424
424
|
if (_this.subscriptions && typeof _this.subscriptions.subscribe === "function") {
|
425
|
-
_this.pendingSubscriptions.map(function(
|
426
|
-
logger.log("SubscriptionGuarantor resubscribing " +
|
427
|
-
_this.subscriptions.subscribe(
|
425
|
+
_this.pendingSubscriptions.map(function(subscription2) {
|
426
|
+
logger.log("SubscriptionGuarantor resubscribing " + subscription2.identifier);
|
427
|
+
_this.subscriptions.subscribe(subscription2);
|
428
428
|
});
|
429
429
|
}
|
430
430
|
}, 500);
|
@@ -443,37 +443,37 @@
|
|
443
443
|
var params = (typeof channel === "undefined" ? "undefined" : _typeof(channel)) === "object" ? channel : {
|
444
444
|
channel
|
445
445
|
};
|
446
|
-
var
|
447
|
-
return this.add(
|
446
|
+
var subscription2 = new Subscription(this.consumer, params, mixin);
|
447
|
+
return this.add(subscription2);
|
448
448
|
};
|
449
|
-
Subscriptions2.prototype.add = function add(
|
450
|
-
this.subscriptions.push(
|
449
|
+
Subscriptions2.prototype.add = function add(subscription2) {
|
450
|
+
this.subscriptions.push(subscription2);
|
451
451
|
this.consumer.ensureActiveConnection();
|
452
|
-
this.notify(
|
453
|
-
this.subscribe(
|
454
|
-
return
|
455
|
-
};
|
456
|
-
Subscriptions2.prototype.remove = function remove2(
|
457
|
-
this.forget(
|
458
|
-
if (!this.findAll(
|
459
|
-
this.sendCommand(
|
452
|
+
this.notify(subscription2, "initialized");
|
453
|
+
this.subscribe(subscription2);
|
454
|
+
return subscription2;
|
455
|
+
};
|
456
|
+
Subscriptions2.prototype.remove = function remove2(subscription2) {
|
457
|
+
this.forget(subscription2);
|
458
|
+
if (!this.findAll(subscription2.identifier).length) {
|
459
|
+
this.sendCommand(subscription2, "unsubscribe");
|
460
460
|
}
|
461
|
-
return
|
461
|
+
return subscription2;
|
462
462
|
};
|
463
463
|
Subscriptions2.prototype.reject = function reject(identifier) {
|
464
464
|
var _this = this;
|
465
|
-
return this.findAll(identifier).map(function(
|
466
|
-
_this.forget(
|
467
|
-
_this.notify(
|
468
|
-
return
|
465
|
+
return this.findAll(identifier).map(function(subscription2) {
|
466
|
+
_this.forget(subscription2);
|
467
|
+
_this.notify(subscription2, "rejected");
|
468
|
+
return subscription2;
|
469
469
|
});
|
470
470
|
};
|
471
|
-
Subscriptions2.prototype.forget = function forget(
|
472
|
-
this.guarantor.forget(
|
471
|
+
Subscriptions2.prototype.forget = function forget(subscription2) {
|
472
|
+
this.guarantor.forget(subscription2);
|
473
473
|
this.subscriptions = this.subscriptions.filter(function(s) {
|
474
|
-
return s !==
|
474
|
+
return s !== subscription2;
|
475
475
|
});
|
476
|
-
return
|
476
|
+
return subscription2;
|
477
477
|
};
|
478
478
|
Subscriptions2.prototype.findAll = function findAll(identifier) {
|
479
479
|
return this.subscriptions.filter(function(s) {
|
@@ -482,8 +482,8 @@
|
|
482
482
|
};
|
483
483
|
Subscriptions2.prototype.reload = function reload() {
|
484
484
|
var _this2 = this;
|
485
|
-
return this.subscriptions.map(function(
|
486
|
-
return _this2.subscribe(
|
485
|
+
return this.subscriptions.map(function(subscription2) {
|
486
|
+
return _this2.subscribe(subscription2);
|
487
487
|
});
|
488
488
|
};
|
489
489
|
Subscriptions2.prototype.notifyAll = function notifyAll(callbackName) {
|
@@ -491,38 +491,38 @@
|
|
491
491
|
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
492
492
|
args[_key - 1] = arguments[_key];
|
493
493
|
}
|
494
|
-
return this.subscriptions.map(function(
|
495
|
-
return _this3.notify.apply(_this3, [
|
494
|
+
return this.subscriptions.map(function(subscription2) {
|
495
|
+
return _this3.notify.apply(_this3, [subscription2, callbackName].concat(args));
|
496
496
|
});
|
497
497
|
};
|
498
|
-
Subscriptions2.prototype.notify = function notify(
|
498
|
+
Subscriptions2.prototype.notify = function notify(subscription2, callbackName) {
|
499
499
|
for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) {
|
500
500
|
args[_key2 - 2] = arguments[_key2];
|
501
501
|
}
|
502
502
|
var subscriptions = void 0;
|
503
|
-
if (typeof
|
504
|
-
subscriptions = this.findAll(
|
503
|
+
if (typeof subscription2 === "string") {
|
504
|
+
subscriptions = this.findAll(subscription2);
|
505
505
|
} else {
|
506
|
-
subscriptions = [
|
506
|
+
subscriptions = [subscription2];
|
507
507
|
}
|
508
|
-
return subscriptions.map(function(
|
509
|
-
return typeof
|
508
|
+
return subscriptions.map(function(subscription3) {
|
509
|
+
return typeof subscription3[callbackName] === "function" ? subscription3[callbackName].apply(subscription3, args) : void 0;
|
510
510
|
});
|
511
511
|
};
|
512
|
-
Subscriptions2.prototype.subscribe = function subscribe(
|
513
|
-
if (this.sendCommand(
|
514
|
-
this.guarantor.guarantee(
|
512
|
+
Subscriptions2.prototype.subscribe = function subscribe(subscription2) {
|
513
|
+
if (this.sendCommand(subscription2, "subscribe")) {
|
514
|
+
this.guarantor.guarantee(subscription2);
|
515
515
|
}
|
516
516
|
};
|
517
517
|
Subscriptions2.prototype.confirmSubscription = function confirmSubscription(identifier) {
|
518
518
|
var _this4 = this;
|
519
519
|
logger.log("Subscription confirmed " + identifier);
|
520
|
-
this.findAll(identifier).map(function(
|
521
|
-
return _this4.guarantor.forget(
|
520
|
+
this.findAll(identifier).map(function(subscription2) {
|
521
|
+
return _this4.guarantor.forget(subscription2);
|
522
522
|
});
|
523
523
|
};
|
524
|
-
Subscriptions2.prototype.sendCommand = function sendCommand(
|
525
|
-
var identifier =
|
524
|
+
Subscriptions2.prototype.sendCommand = function sendCommand(subscription2, command) {
|
525
|
+
var identifier = subscription2.identifier;
|
526
526
|
return this.consumer.send({
|
527
527
|
command,
|
528
528
|
identifier
|
@@ -704,7 +704,8 @@
|
|
704
704
|
|
705
705
|
// app/javascript/hotwire-livereload.js
|
706
706
|
var consumer = (0, import_actioncable.createConsumer)();
|
707
|
-
|
707
|
+
var subscription = null;
|
708
|
+
var createSubscription = () => consumer.subscriptions.create("Hotwire::Livereload::ReloadChannel", {
|
708
709
|
received: hotwire_livereload_received_default,
|
709
710
|
connected() {
|
710
711
|
console.log("[Hotwire::Livereload] Websocket connected");
|
@@ -713,8 +714,14 @@
|
|
713
714
|
console.log("[Hotwire::Livereload] Websocket disconnected");
|
714
715
|
}
|
715
716
|
});
|
717
|
+
subscription = createSubscription();
|
716
718
|
document.addEventListener("turbo:load", () => {
|
717
719
|
hotwire_livereload_scroll_position_default.restore();
|
718
720
|
hotwire_livereload_scroll_position_default.remove();
|
721
|
+
if (subscription) {
|
722
|
+
consumer.subscriptions.remove(subscription);
|
723
|
+
subscription = null;
|
724
|
+
}
|
725
|
+
subscription = createSubscription();
|
719
726
|
});
|
720
727
|
})();
|
@@ -3,7 +3,9 @@ import received from "./lib/hotwire-livereload-received"
|
|
3
3
|
import scrollPosition from "./lib/hotwire-livereload-scroll-position"
|
4
4
|
|
5
5
|
const consumer = createConsumer()
|
6
|
-
|
6
|
+
let subscription = null
|
7
|
+
|
8
|
+
const createSubscription = () => consumer.subscriptions.create("Hotwire::Livereload::ReloadChannel", {
|
7
9
|
received,
|
8
10
|
|
9
11
|
connected() {
|
@@ -15,8 +17,16 @@ consumer.subscriptions.create("Hotwire::Livereload::ReloadChannel", {
|
|
15
17
|
},
|
16
18
|
})
|
17
19
|
|
20
|
+
subscription = createSubscription()
|
21
|
+
|
18
22
|
document.addEventListener("turbo:load", () => {
|
19
23
|
scrollPosition.restore()
|
20
24
|
scrollPosition.remove()
|
25
|
+
|
26
|
+
if (subscription) {
|
27
|
+
consumer.subscriptions.remove(subscription)
|
28
|
+
subscription = null
|
29
|
+
}
|
30
|
+
subscription = createSubscription()
|
21
31
|
})
|
22
32
|
|
@@ -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
|
@@ -16,6 +17,7 @@ module Hotwire
|
|
16
17
|
#{root}/app/helpers
|
17
18
|
]
|
18
19
|
config.hotwire_livereload.listen_options ||= {}
|
20
|
+
config.hotwire_livereload.debounce_delay_ms = 0
|
19
21
|
|
20
22
|
initializer "hotwire_livereload.assets" do
|
21
23
|
if Rails.application.config.respond_to?(:assets)
|
@@ -31,6 +33,7 @@ module Hotwire
|
|
31
33
|
|
32
34
|
initializer "hotwire_livereload.set_configs" do |app|
|
33
35
|
options = app.config.hotwire_livereload
|
36
|
+
skip_listen_paths = options.skip_listen_paths.map(&:to_s).uniq
|
34
37
|
|
35
38
|
unless options.disable_default_listeners
|
36
39
|
default_listen_paths = %w[
|
@@ -55,11 +58,20 @@ module Hotwire
|
|
55
58
|
.uniq
|
56
59
|
.map { |p| Rails.root.join(p) }
|
57
60
|
.select { |p| Dir.exist?(p) }
|
61
|
+
.reject { |p| skip_listen_paths.include?(p.to_s) }
|
58
62
|
end
|
59
63
|
end
|
60
64
|
|
61
65
|
config.after_initialize do |app|
|
62
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
|
+
|
63
75
|
options = app.config.hotwire_livereload
|
64
76
|
listen_paths = options.listen_paths.map(&:to_s).uniq
|
65
77
|
force_reload_paths = options.force_reload_paths.map(&:to_s).uniq.join("|")
|
@@ -74,11 +86,7 @@ module Hotwire
|
|
74
86
|
end
|
75
87
|
|
76
88
|
options = {changed: changed, force_reload: force_reload}
|
77
|
-
|
78
|
-
Hotwire::Livereload.turbo_stream(options)
|
79
|
-
else
|
80
|
-
Hotwire::Livereload.action_cable(options)
|
81
|
-
end
|
89
|
+
@trigger_reload.call(options)
|
82
90
|
end
|
83
91
|
end
|
84
92
|
@listener.start
|
@@ -111,5 +119,27 @@ module Hotwire
|
|
111
119
|
|
112
120
|
puma_process || rails_server
|
113
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
|
114
144
|
end
|
115
145
|
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.
|
4
|
+
version: 1.4.1
|
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-
|
11
|
+
date: 2024-09-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|