react-rails-hot-loader 0.0.1 → 0.1.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 +4 -4
- data/.travis.yml +4 -1
- data/Guardfile +12 -0
- data/README.md +12 -5
- data/lib/assets/react-rails-hot-loader.js +16 -26
- data/lib/hot_loader.rb +16 -5
- data/lib/hot_loader/asset_change_set.rb +10 -5
- data/lib/hot_loader/asset_path.rb +2 -0
- data/lib/hot_loader/railtie.rb +1 -3
- data/lib/hot_loader/server.rb +36 -27
- data/lib/hot_loader/version.rb +1 -1
- data/react-rails-hot-loader.gemspec +9 -2
- metadata +80 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 120d5f5ea466039d5d1aea66acdfd7a6b2d2b47c
|
4
|
+
data.tar.gz: 10591893cb60c6fdc558ec3efeece0910b79be9d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 243026941a4eed56d3b40af15007b960a9779d4fc04a491af319bc1f053069c70399f527f670e9f5059c49880ac837e397fce283ce1ff6dd9d80fa12faa4d257
|
7
|
+
data.tar.gz: 5f541a0af462ef1a961250cdf2573acffe7e7c1de737962a0ff86c46d52485c54d5fc10e294d369692f54412abf05b2e3ee823a2a57e1bcf636eab8a688a2bbc
|
data/.travis.yml
CHANGED
data/Guardfile
CHANGED
@@ -3,3 +3,15 @@ guard :minitest do
|
|
3
3
|
watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}#{m[2]}_test.rb" }
|
4
4
|
watch(%r{^test/test_helper\.rb$}) { 'test' }
|
5
5
|
end
|
6
|
+
|
7
|
+
guard :bundler do
|
8
|
+
require 'guard/bundler'
|
9
|
+
require 'guard/bundler/verify'
|
10
|
+
helper = Guard::Bundler::Verify.new
|
11
|
+
|
12
|
+
files = ['Gemfile']
|
13
|
+
files += Dir['*.gemspec'] if files.any? { |f| helper.uses_gemspec?(f) }
|
14
|
+
|
15
|
+
# Assume files are symlinked from somewhere
|
16
|
+
files.each { |file| watch(helper.real_path(file)) }
|
17
|
+
end
|
data/README.md
CHANGED
@@ -1,7 +1,11 @@
|
|
1
|
-
# React::Rails::HotLoader
|
1
|
+
# React::Rails::HotLoader
|
2
2
|
|
3
3
|
Reload React.js components with Ruby on Rails & [`react-rails`](http://github.com/reactjs/react-rails).
|
4
4
|
|
5
|
+
When you edit components, they'll be reloaded by the browser & re-mounted in the page.
|
6
|
+
|
7
|
+
[](http://badge.fury.io/rb/react-rails-hot-loader) [](https://travis-ci.org/rmosolgo/react-rails-hot-loader) [](https://codeclimate.com/github/rmosolgo/react-rails-hot-loader) [](https://codeclimate.com/github/rmosolgo/react-rails-hot-loader/coverage)
|
8
|
+
|
5
9
|
## Installation
|
6
10
|
|
7
11
|
Add this line to your application's Gemfile:
|
@@ -20,24 +24,28 @@ Or install it yourself as:
|
|
20
24
|
|
21
25
|
## Usage
|
22
26
|
|
23
|
-
- Add an initializer
|
27
|
+
- Add an initializer:
|
24
28
|
|
25
29
|
```ruby
|
30
|
+
# app/config/initializers/react_rails_hot_loader.rb
|
26
31
|
if Rails.env.development?
|
27
32
|
React::Rails::HotLoader.start()
|
28
33
|
end
|
29
34
|
```
|
30
35
|
|
31
|
-
- Include the
|
36
|
+
- Include the JavaScript:
|
32
37
|
|
33
38
|
```js
|
34
|
-
|
39
|
+
// app/assets/javascripts/application.js
|
40
|
+
//= require react-rails-hot-loader
|
35
41
|
```
|
36
42
|
|
37
43
|
(When not `Rails.env.development?`, this requires an empty file, so don't worry about leaving it in production deploys.)
|
38
44
|
|
39
45
|
- Restart your development server
|
40
46
|
|
47
|
+
- Edit files in `/app/assets/javascripts` & save changes -- they'll be reloaded in the client and React components will be remounted.
|
48
|
+
|
41
49
|
## Doeses & Doesn'ts
|
42
50
|
|
43
51
|
`react-rails-hot-loader` ...
|
@@ -53,7 +61,6 @@ Or install it yourself as:
|
|
53
61
|
|
54
62
|
- Handle Passenger occasionally killing background threads :(
|
55
63
|
- Replace pinging with file watching
|
56
|
-
- Test Server, AssetPath
|
57
64
|
- Add `rails g react-rails-hot-loader:install` to add initializer and JS
|
58
65
|
|
59
66
|
## License
|
@@ -1,22 +1,33 @@
|
|
1
|
-
ReactRailsHotLoader = {
|
1
|
+
var ReactRailsHotLoader = {
|
2
2
|
since: null,
|
3
3
|
port: 8082,
|
4
|
-
host: window.location.
|
4
|
+
host: window.location.hostname,
|
5
5
|
shouldLog: true,
|
6
6
|
|
7
7
|
start: function() {
|
8
8
|
this._resetSince()
|
9
9
|
var wsURL = "ws://" + this.host + ":" + this.port
|
10
|
-
this.log("
|
10
|
+
this.log("connecting to " + wsURL)
|
11
11
|
this._socket = new WebSocket(wsURL)
|
12
12
|
|
13
13
|
var _this = this
|
14
14
|
|
15
|
+
this._socket.onopen = function() { _this.log("connected") }
|
16
|
+
this._socket.onclose = function() { _this.log("disconnected") }
|
17
|
+
|
15
18
|
this._socket.onmessage = function(message) {
|
16
19
|
var changes = JSON.parse(message.data)
|
17
|
-
_this.log("updating " + changes.
|
18
|
-
changes.
|
20
|
+
_this.log("updating: " + changes.changed_file_names.join(", ") )
|
21
|
+
changes.changed_asset_contents.forEach(function(jsCode) {
|
22
|
+
try {
|
23
|
+
eval.call(window, jsCode)
|
24
|
+
} catch (err) {
|
25
|
+
_this.log(err)
|
26
|
+
}
|
27
|
+
})
|
28
|
+
ReactRailsUJS.mountComponents()
|
19
29
|
_this._resetSince()
|
30
|
+
_this.log("update finished")
|
20
31
|
}
|
21
32
|
|
22
33
|
this._interval = setInterval(function() {
|
@@ -33,27 +44,6 @@ ReactRailsHotLoader = {
|
|
33
44
|
clearInterval(this._interval)
|
34
45
|
},
|
35
46
|
|
36
|
-
_reloadAsset: function(path) {
|
37
|
-
var _this = this
|
38
|
-
var _handleResponse = function(js) {
|
39
|
-
try {
|
40
|
-
eval.call(window, js)
|
41
|
-
} catch (err) {
|
42
|
-
_this.log(err)
|
43
|
-
}
|
44
|
-
ReactRailsUJS.mountComponents()
|
45
|
-
var name = path.split("/").pop()
|
46
|
-
_this.log("reloaded " + name)
|
47
|
-
}
|
48
|
-
|
49
|
-
$.ajax({
|
50
|
-
type: "GET",
|
51
|
-
url: path,
|
52
|
-
success: _handleResponse,
|
53
|
-
error: _handleResponse,
|
54
|
-
})
|
55
|
-
},
|
56
|
-
|
57
47
|
_resetSince: function() {
|
58
48
|
// Ruby prefers seconds.
|
59
49
|
this.since = Date.now() / 1000
|
data/lib/hot_loader.rb
CHANGED
@@ -2,19 +2,30 @@ module React
|
|
2
2
|
module Rails
|
3
3
|
module HotLoader
|
4
4
|
mattr_accessor :server
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
|
6
|
+
# Create a new server with `options` & start it
|
7
|
+
def self.start(options={})
|
8
|
+
server_class = options.delete(:server_class) || Server
|
9
|
+
self.server = server_class.new(options)
|
10
|
+
restart
|
8
11
|
end
|
9
12
|
|
13
|
+
# Restart the server with the same options
|
10
14
|
def self.restart
|
11
15
|
server.restart
|
12
16
|
rescue StandardError => err
|
13
|
-
|
17
|
+
React::Rails::HotLoader.error(err)
|
14
18
|
end
|
15
19
|
|
16
20
|
def self.log(message)
|
17
|
-
|
21
|
+
msg = "[HotLoader] #{message}"
|
22
|
+
::Rails.logger.info(msg)
|
23
|
+
::Rails.logger.flush
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.error(err)
|
27
|
+
msg = "#{err.class.name}: #{err}\n #{err.backtrace.join("\n")}"
|
28
|
+
log(msg)
|
18
29
|
end
|
19
30
|
end
|
20
31
|
end
|
@@ -2,26 +2,31 @@ module React
|
|
2
2
|
module Rails
|
3
3
|
module HotLoader
|
4
4
|
class AssetChangeSet
|
5
|
-
attr_reader :since, :path, :changed_files, :
|
5
|
+
attr_reader :since, :path, :changed_files, :changed_file_names, :changed_asset_contents
|
6
6
|
# initialize with a path and time
|
7
7
|
# to find files which changed since that time
|
8
8
|
def initialize(since:, path: ::Rails.root.join("app/assets/javascripts"))
|
9
9
|
@since = since
|
10
10
|
@path = path.to_s
|
11
|
-
asset_glob = path.to_s + "/**/*.js
|
11
|
+
asset_glob = path.to_s + "/**/*.js*"
|
12
12
|
@changed_files = Dir.glob(asset_glob).select { |f| File.mtime(f) >= since }
|
13
|
-
@
|
13
|
+
@changed_file_names = changed_files.map { |f| f.split("/").last }
|
14
|
+
@changed_asset_contents = changed_files.map do |f|
|
15
|
+
logical_path = f.sub(path.to_s, "").sub(/^\//, '')
|
16
|
+
::Rails.application.assets[logical_path].to_s
|
17
|
+
end
|
14
18
|
end
|
15
19
|
|
16
20
|
def any?
|
17
|
-
|
21
|
+
changed_files.any?
|
18
22
|
end
|
19
23
|
|
20
24
|
def as_json(options={})
|
21
25
|
{
|
22
26
|
since: since,
|
23
27
|
path: path,
|
24
|
-
|
28
|
+
changed_file_names: changed_file_names,
|
29
|
+
changed_asset_contents: changed_asset_contents,
|
25
30
|
}
|
26
31
|
end
|
27
32
|
end
|
data/lib/hot_loader/railtie.rb
CHANGED
@@ -3,8 +3,6 @@ module React
|
|
3
3
|
module HotLoader
|
4
4
|
class Railtie < ::Rails::Railtie
|
5
5
|
config.before_initialize do |app|
|
6
|
-
# We want to include different files in dev/prod.
|
7
|
-
# The production file is empty!
|
8
6
|
asset_path = React::Rails::HotLoader::AssetPath.new(dummy: !(::Rails.env.development?))
|
9
7
|
app.config.assets.paths << asset_path.to_s
|
10
8
|
end
|
@@ -14,7 +12,7 @@ module React
|
|
14
12
|
begin
|
15
13
|
React::Rails::HotLoader.restart
|
16
14
|
rescue StandardError => err
|
17
|
-
React::Rails::HotLoader.
|
15
|
+
React::Rails::HotLoader.error(err)
|
18
16
|
end
|
19
17
|
end
|
20
18
|
end
|
data/lib/hot_loader/server.rb
CHANGED
@@ -10,49 +10,58 @@ module React
|
|
10
10
|
@host = host
|
11
11
|
@port = port
|
12
12
|
@change_set_class = change_set_class
|
13
|
-
@thread = nil
|
14
13
|
end
|
15
14
|
|
15
|
+
# Restarts the server _if_ it has stopped
|
16
16
|
def restart
|
17
|
-
if
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
17
|
+
return if running?
|
18
|
+
start
|
19
|
+
rescue StandardError => err
|
20
|
+
React::Rails::HotLoader.error(err)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def running?
|
26
|
+
@server_thread && @server_thread.alive?
|
27
|
+
end
|
28
|
+
|
29
|
+
def start
|
30
|
+
@server_thread = Thread.new do
|
31
|
+
begin
|
32
|
+
serve
|
33
|
+
rescue StandardError => err
|
34
|
+
React::Rails::HotLoader.error(err)
|
25
35
|
end
|
26
36
|
end
|
27
37
|
end
|
28
38
|
|
29
39
|
def serve
|
30
40
|
EM.run {
|
31
|
-
React::Rails::HotLoader.log("starting WS server
|
41
|
+
React::Rails::HotLoader.log("starting WS server: ws://#{host}:#{port}")
|
32
42
|
|
33
43
|
EM::WebSocket.run(host: host, port: port) do |ws|
|
34
|
-
ws.onopen
|
35
|
-
|
36
|
-
ws.
|
37
|
-
begin
|
38
|
-
since_time = Time.at(msg.to_i)
|
39
|
-
changes = change_set_class.new(since: since_time)
|
40
|
-
if changes.any?
|
41
|
-
React::Rails::HotLoader.log("received message: #{msg}")
|
42
|
-
React::Rails::HotLoader.log("sent response: #{changes.to_json}")
|
43
|
-
ws.send(changes.to_json)
|
44
|
-
end
|
45
|
-
rescue StandardError => err
|
46
|
-
React::Rails::HotLoader.log("message error: #{err}\n #{err.backtrace.join("\n")}")
|
47
|
-
end
|
48
|
-
}
|
49
|
-
|
50
|
-
ws.onclose { React::Rails::HotLoader.log("closed a connection") }
|
44
|
+
ws.onopen { React::Rails::HotLoader.log("opened a connection") }
|
45
|
+
ws.onmessage { |msg| handle_message(ws, msg) }
|
46
|
+
ws.onclose { React::Rails::HotLoader.log("closed a connection") }
|
51
47
|
end
|
52
48
|
|
53
49
|
React::Rails::HotLoader.log("started WS server")
|
54
50
|
}
|
55
51
|
end
|
52
|
+
|
53
|
+
# Check for any changes since `msg`, respond if there are any changes
|
54
|
+
def handle_message(ws, msg)
|
55
|
+
# React::Rails::HotLoader.log("received message: #{msg}")
|
56
|
+
since_time = Time.at(msg.to_i)
|
57
|
+
changes = change_set_class.new(since: since_time)
|
58
|
+
if changes.any?
|
59
|
+
React::Rails::HotLoader.log("sent changes: #{changes.changed_file_names}")
|
60
|
+
ws.send(changes.to_json)
|
61
|
+
end
|
62
|
+
rescue StandardError => err
|
63
|
+
React::Rails::HotLoader.error(err)
|
64
|
+
end
|
56
65
|
end
|
57
66
|
end
|
58
67
|
end
|
data/lib/hot_loader/version.rb
CHANGED
@@ -17,12 +17,19 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
|
+
spec.required_ruby_version = '>= 2.1.0'
|
21
|
+
|
20
22
|
spec.add_runtime_dependency "em-websocket"
|
23
|
+
spec.add_runtime_dependency "rails"
|
21
24
|
spec.add_runtime_dependency "react-rails"
|
22
25
|
|
23
26
|
spec.add_development_dependency "bundler", "~> 1.10"
|
24
|
-
spec.add_development_dependency "
|
25
|
-
spec.add_development_dependency "minitest"
|
27
|
+
spec.add_development_dependency "codeclimate-test-reporter"
|
26
28
|
spec.add_development_dependency "guard"
|
29
|
+
spec.add_development_dependency "guard-bundler"
|
27
30
|
spec.add_development_dependency "guard-minitest"
|
31
|
+
spec.add_development_dependency "minitest"
|
32
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
33
|
+
spec.add_development_dependency "sqlite3"
|
34
|
+
spec.add_development_dependency "websocket-client-simple"
|
28
35
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: react-rails-hot-loader
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Mosolgo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-07-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: em-websocket
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rails
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: react-rails
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -53,21 +67,21 @@ dependencies:
|
|
53
67
|
- !ruby/object:Gem::Version
|
54
68
|
version: '1.10'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
70
|
+
name: codeclimate-test-reporter
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
|
-
- - "
|
73
|
+
- - ">="
|
60
74
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
75
|
+
version: '0'
|
62
76
|
type: :development
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
|
-
- - "
|
80
|
+
- - ">="
|
67
81
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
82
|
+
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
84
|
+
name: guard
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
72
86
|
requirements:
|
73
87
|
- - ">="
|
@@ -81,7 +95,7 @@ dependencies:
|
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: '0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
|
-
name: guard
|
98
|
+
name: guard-bundler
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
86
100
|
requirements:
|
87
101
|
- - ">="
|
@@ -108,6 +122,62 @@ dependencies:
|
|
108
122
|
- - ">="
|
109
123
|
- !ruby/object:Gem::Version
|
110
124
|
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: minitest
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: rake
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '10.0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '10.0'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: sqlite3
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: websocket-client-simple
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
111
181
|
description: Tie into the `react-rails` gem to notify the client of changed files
|
112
182
|
& reload assets on the client when they are changed.
|
113
183
|
email:
|
@@ -147,7 +217,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
147
217
|
requirements:
|
148
218
|
- - ">="
|
149
219
|
- !ruby/object:Gem::Version
|
150
|
-
version:
|
220
|
+
version: 2.1.0
|
151
221
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
152
222
|
requirements:
|
153
223
|
- - ">="
|