opal-webpack-loader 0.6.6 → 0.7.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/bin/opal-webpack-compile-server +28 -9
- data/lib/opal-webpack-loader/compile_server.rb +109 -140
- data/lib/opal-webpack-loader/compile_worker.rb +96 -0
- data/lib/opal-webpack-loader/installer_cli.rb +9 -5
- data/lib/opal-webpack-loader/load_path_manager.rb +55 -0
- data/lib/opal-webpack-loader/templates/application_web_worker.js.erb +11 -0
- data/lib/opal-webpack-loader/templates/debug.js.erb +31 -7
- data/lib/opal-webpack-loader/templates/development.js.erb +31 -7
- data/lib/opal-webpack-loader/templates/opal_web_worker_loader.rb.erb +9 -0
- data/lib/opal-webpack-loader/templates/production.js.erb +27 -5
- data/lib/opal-webpack-loader/version.rb +1 -1
- data/spec/installer_spec.rb +4 -0
- data/spec/owl_spec.rb +3 -4
- metadata +6 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0d16462b0c87b2e4b5bfd45379a397ed582943e2d392080e58c44b81cbd500db
|
4
|
+
data.tar.gz: 6c0274bbc3dacbb1c735bf4078526a1669512ba1074d318b28018067ce70563d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b41086c5835da79c0199c0a259aafab20bd96f68e07097321c6426e7b0e464f11e1e7e724064f009bdf0a50643450f77e341665ad5d9ace677c0f18701113f3
|
7
|
+
data.tar.gz: ccf1621264e8a7109f804dcf9a8f61d328dcd2ebca83087a7c6d84f22928558695dcb1d1d3c652bfac5cc8fe1ab7aa2360d4f506cfbfd3ec5fd6335896744580
|
@@ -1,38 +1,57 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'opal-webpack-loader/compile_server'
|
3
|
+
require 'opal-webpack-loader/compile_worker'
|
4
|
+
require 'opal-webpack-loader/load_path_manager'
|
3
5
|
require 'open3'
|
4
6
|
|
7
|
+
at_exit do
|
8
|
+
if OpalWebpackLoader::CompileServer.unlink_socket?
|
9
|
+
if File.exist?(OpalWebpackLoader::CompileServer::OWCS_SOCKET_PATH)
|
10
|
+
File.unlink(OpalWebpackLoader::CompileServer::OWCS_SOCKET_PATH)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
5
15
|
puts "args: #{ARGV}"
|
6
16
|
|
7
17
|
if ARGV[0] == 'stop' || ARGV[0] == 'kill'
|
8
|
-
|
18
|
+
OpalWebpackLoader::CompileServer.stop
|
9
19
|
else
|
10
20
|
if ARGV[0] == 'start'
|
11
|
-
|
12
|
-
|
21
|
+
OpalWebpackLoader::CompileServer.stop(false)
|
22
|
+
number_of_workers = ARGV[1].to_i
|
23
|
+
if number_of_workers == 0
|
24
|
+
number_of_workers == 4
|
25
|
+
runargs = ARGV[1..-1]
|
26
|
+
else
|
27
|
+
runargs = ARGV[2..-1]
|
28
|
+
end
|
13
29
|
else
|
14
|
-
|
30
|
+
raise 'arguments must be either "stop" or "start number_of_workers process_to_run --with args"'
|
31
|
+
exit(1)
|
15
32
|
end
|
16
33
|
|
17
|
-
|
34
|
+
OpalWebpackLoader::LoadPathManager.create_load_paths_cache
|
35
|
+
|
36
|
+
pid = fork { OpalWebpackLoader::CompileServer.new.start(number_of_workers) }
|
18
37
|
|
19
38
|
have_socket = false
|
20
39
|
start_time = Time.now
|
21
40
|
begin
|
22
41
|
until have_socket
|
23
|
-
if File.exist?(
|
42
|
+
if File.exist?(OpalWebpackLoader::CompileServer::OWCS_SOCKET_PATH)
|
24
43
|
have_socket = true
|
25
44
|
else
|
26
45
|
if Time.now - start_time > 60
|
27
46
|
puts "opal-webpack-compile-server didnt start in time. Exiting"
|
28
|
-
|
47
|
+
OpalWebpackLoader::CompileServer.stop(false)
|
29
48
|
Process.kill("TERM", pid)
|
30
49
|
exit 1
|
31
50
|
end
|
32
51
|
end
|
33
52
|
end
|
34
53
|
rescue Exception => e
|
35
|
-
|
54
|
+
OpalWebpackLoader::CompileServer.stop(false)
|
36
55
|
puts "opal-webpack-compile-server couldn't start:"
|
37
56
|
puts e.backtrace.join("\n")
|
38
57
|
puts e.message
|
@@ -54,7 +73,7 @@ else
|
|
54
73
|
|
55
74
|
thread.join # don't exit until the external process is done
|
56
75
|
end
|
57
|
-
rescue Interrupt
|
76
|
+
rescue Interrupt
|
58
77
|
puts "opal-webpack-compile-server got interrupted. Exiting with drama."
|
59
78
|
Process.kill("TERM", pid)
|
60
79
|
exit 0
|
@@ -1,173 +1,142 @@
|
|
1
|
-
require 'oj'
|
2
|
-
require 'eventmachine'
|
3
|
-
require 'opal/paths'
|
4
|
-
require 'opal/source_map'
|
5
|
-
require 'source_map'
|
6
|
-
require 'opal/compiler'
|
7
1
|
require 'socket'
|
8
2
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
module OpalWebpackCompileServer
|
18
|
-
OWL_CACHE_DIR = './.owl_cache/'
|
19
|
-
OWL_LP_CACHE = OWL_CACHE_DIR + 'load_paths.json'
|
20
|
-
OWCS_SOCKET_PATH = OWL_CACHE_DIR + 'owcs_socket'
|
3
|
+
module OpalWebpackLoader
|
4
|
+
class CompileServer
|
5
|
+
OWL_CACHE_DIR = File.join('.','.owl_cache/')
|
6
|
+
OWL_LP_CACHE = File.join(OWL_CACHE_DIR, 'load_paths.json')
|
7
|
+
OWCS_SOCKET_PATH = File.join(OWL_CACHE_DIR, 'owcs_socket')
|
8
|
+
SIGNALS = %w[QUIT INT TERM TTIN TTOU]
|
9
|
+
TIMEOUT = 15
|
21
10
|
|
22
|
-
|
23
|
-
|
24
|
-
@received_data = ''
|
25
|
-
super(*args)
|
11
|
+
def self.unlink_socket?
|
12
|
+
@unlink
|
26
13
|
end
|
27
14
|
|
28
|
-
def
|
29
|
-
@
|
15
|
+
def self.unlink_socket_on_exit
|
16
|
+
@unlink = true
|
17
|
+
end
|
30
18
|
|
31
|
-
|
19
|
+
def self.dont_unlink_socket_on_exit
|
20
|
+
@unlink = false
|
21
|
+
end
|
32
22
|
|
33
|
-
|
34
|
-
|
35
|
-
|
23
|
+
def self.stop(do_exit = true)
|
24
|
+
if File.exist?(OWCS_SOCKET_PATH)
|
25
|
+
dont_unlink_socket_on_exit
|
26
|
+
begin
|
27
|
+
s = UNIXSocket.new(OWCS_SOCKET_PATH)
|
28
|
+
s.send("command:stop\x04", 0)
|
29
|
+
s.close
|
30
|
+
rescue
|
31
|
+
# socket cant be reached so owlcs is already dead, delete socket
|
32
|
+
unlink_socket_on_exit
|
33
|
+
end
|
34
|
+
exit(0) if do_exit
|
36
35
|
end
|
36
|
+
end
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
@
|
41
|
-
|
42
|
-
|
43
|
-
filename = request_json["filename"]
|
44
|
-
source = File.read(filename)
|
38
|
+
def initialize
|
39
|
+
@read_pipe, @write_pipe = IO.pipe
|
40
|
+
@workers = {}
|
41
|
+
@signal_queue = []
|
42
|
+
end
|
45
43
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
44
|
+
def start(number_of_workers = 4)
|
45
|
+
$PROGRAM_NAME = 'owl compile server'
|
46
|
+
@number_of_workers = number_of_workers
|
47
|
+
@server_pid = Process.pid
|
48
|
+
$stderr.sync = $stdout.sync = true
|
49
|
+
@socket = UNIXServer.new(OWCS_SOCKET_PATH)
|
50
|
+
spawn_workers
|
51
|
+
SIGNALS.each { |sig| trap_deferred(sig) }
|
52
|
+
trap('CHLD') { @write_pipe.write_nonblock('.') }
|
53
|
+
|
54
|
+
loop do
|
55
|
+
reap_workers
|
56
|
+
case (mode = @signal_queue.shift)
|
57
|
+
when nil
|
58
|
+
kill_runaway_workers
|
59
|
+
spawn_workers
|
60
|
+
when 'QUIT', 'TERM', 'INT'
|
61
|
+
@workers.each_pair do |pid, _worker|
|
62
|
+
Process.kill('TERM', pid)
|
63
|
+
end
|
64
|
+
break
|
65
|
+
when 'TTIN'
|
66
|
+
@number_of_workers += 1
|
67
|
+
when 'TTOU'
|
68
|
+
unless @number_of_workers <= 0
|
69
|
+
Config.workers -= 1
|
70
|
+
kill_worker('QUIT', @workers.keys.max)
|
56
71
|
end
|
57
|
-
result['required_trees'] = c.required_trees
|
58
|
-
Oj.dump(result, {})
|
59
|
-
rescue Exception => e
|
60
|
-
Oj.dump({ 'error' => { 'name' => e.class, 'message' => e.message, 'backtrace' => e.backtrace.join("\n") } }, {})
|
61
72
|
end
|
73
|
+
reap_workers
|
74
|
+
ready = IO.select([@read_pipe], nil, nil, 1) || next
|
75
|
+
ready.first && ready.first.first || next
|
76
|
+
@read_pipe.read_nonblock(1)
|
77
|
+
OpalWebpackLoader::CompileServer.unlink_socket_on_exit
|
62
78
|
end
|
63
|
-
|
64
|
-
callback = proc do |json|
|
65
|
-
self.send_data(json)
|
66
|
-
close_connection_after_writing
|
67
|
-
end
|
68
|
-
|
69
|
-
EM.defer(operation, callback)
|
70
79
|
end
|
71
|
-
end
|
72
80
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
next if entry == '.'
|
80
|
-
next if entry == '..'
|
81
|
-
next unless entry
|
82
|
-
absolute_path = File.join(path, entry)
|
83
|
-
if File.directory?(absolute_path)
|
84
|
-
more_path_entries = get_load_path_entries(absolute_path)
|
85
|
-
path_entries.push(*more_path_entries) if more_path_entries.size > 0
|
86
|
-
elsif (absolute_path.end_with?('.rb') || absolute_path.end_with?('.js')) && File.file?(absolute_path)
|
87
|
-
path_entries.push(absolute_path)
|
88
|
-
end
|
81
|
+
private
|
82
|
+
|
83
|
+
def reap_workers
|
84
|
+
loop do
|
85
|
+
pid, status = Process.waitpid2(-1, Process::WNOHANG) || break
|
86
|
+
reap_worker(pid, status)
|
89
87
|
end
|
90
|
-
|
88
|
+
rescue Errno::ECHILD
|
91
89
|
end
|
92
90
|
|
93
|
-
def
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
%x{
|
100
|
-
bundle exec ruby -e 'if File.exist?("app_loader.rb"); require "./app_loader.rb"; else; require "bundler/setup"; Bundler.require; set :run, false if defined? Sinatra; end; puts Opal.paths'
|
101
|
-
}
|
102
|
-
end
|
103
|
-
if $? == 0
|
104
|
-
load_path_lines = load_paths.split("\n")
|
105
|
-
load_path_lines.pop if load_path_lines.last == ''
|
106
|
-
|
107
|
-
load_path_entries = []
|
108
|
-
|
109
|
-
cwd = Dir.pwd
|
110
|
-
|
111
|
-
load_path_lines.each do |path|
|
112
|
-
next if path.start_with?(cwd)
|
113
|
-
more_path_entries = get_load_path_entries(path)
|
114
|
-
load_path_entries.push(*more_path_entries) if more_path_entries.size > 0
|
115
|
-
end
|
116
|
-
cache_obj = { 'opal_load_paths' => load_path_lines, 'opal_load_path_entries' => load_path_entries }
|
117
|
-
Dir.mkdir(OpalWebpackCompileServer::OWL_CACHE_DIR) unless Dir.exist?(OpalWebpackCompileServer::OWL_CACHE_DIR)
|
118
|
-
File.write(OpalWebpackCompileServer::OWL_LP_CACHE, Oj.dump(cache_obj, {}))
|
119
|
-
load_path_lines
|
120
|
-
else
|
121
|
-
raise 'Error getting load paths!'
|
122
|
-
exit(2)
|
91
|
+
def reap_worker(pid, status)
|
92
|
+
worker = @workers.delete(pid)
|
93
|
+
begin
|
94
|
+
worker.tempfile.close
|
95
|
+
rescue
|
96
|
+
nil
|
123
97
|
end
|
98
|
+
puts "OpalWebpackLoader::CompileServer: Reaped worker #{worker.number} (PID:#{pid}) status: #{status.exitstatus}"
|
124
99
|
end
|
125
|
-
end
|
126
100
|
|
127
|
-
|
128
|
-
|
129
|
-
|
101
|
+
def kill_worker(signal, pid)
|
102
|
+
Process.kill(signal, pid)
|
103
|
+
rescue Errno::ESRCH
|
130
104
|
end
|
131
105
|
|
132
|
-
def
|
133
|
-
|
106
|
+
def kill_runaway_workers
|
107
|
+
now = Time.now
|
108
|
+
@workers.each_pair do |pid, worker|
|
109
|
+
(now - worker.tempfile.ctime) <= TIMEOUT && next
|
110
|
+
$stderr.puts "worker #{worker.number} (PID:#{pid}) has timed out"
|
111
|
+
kill_worker('KILL', pid)
|
112
|
+
end
|
134
113
|
end
|
135
114
|
|
136
|
-
def
|
137
|
-
@
|
115
|
+
def init_worker(worker)
|
116
|
+
@write_pipe.close
|
117
|
+
@read_pipe.close
|
118
|
+
@workers.each_pair { |_, w| w.tempfile.close }
|
119
|
+
worker.start
|
138
120
|
end
|
139
121
|
|
140
|
-
def
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
end
|
151
|
-
exit(0) if do_exit
|
122
|
+
def spawn_workers
|
123
|
+
worker_number = -1
|
124
|
+
until (worker_number += 1) == @number_of_workers
|
125
|
+
@workers.value?(worker_number) && next
|
126
|
+
tempfile = Tempfile.new('')
|
127
|
+
tempfile.unlink
|
128
|
+
tempfile.sync = true
|
129
|
+
worker = OpalWebpackLoader::CompileWorker.new(@server_pid, @socket, tempfile, worker_number)
|
130
|
+
pid = fork { init_worker(worker) }
|
131
|
+
@workers[pid] = worker
|
152
132
|
end
|
153
133
|
end
|
154
134
|
|
155
|
-
def
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
exit(1)
|
160
|
-
else
|
161
|
-
unlink_on_exit
|
162
|
-
load_paths = OpalWebpackCompileServer::LoadPathManager.get_load_paths
|
163
|
-
if load_paths
|
164
|
-
Opal.append_paths(*load_paths)
|
165
|
-
# Process.daemon(true)
|
166
|
-
EventMachine.run do
|
167
|
-
EventMachine.start_unix_domain_server(OWCS_SOCKET_PATH, OpalWebpackCompileServer::Compiler)
|
168
|
-
end
|
169
|
-
end
|
135
|
+
def trap_deferred(signal)
|
136
|
+
trap(signal) do |_|
|
137
|
+
@signal_queue << signal
|
138
|
+
@write_pipe.write_nonblock('.')
|
170
139
|
end
|
171
140
|
end
|
172
141
|
end
|
173
|
-
end
|
142
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'oj'
|
2
|
+
require 'opal/paths'
|
3
|
+
require 'opal/source_map'
|
4
|
+
require 'source_map'
|
5
|
+
require 'opal/compiler'
|
6
|
+
require 'socket'
|
7
|
+
|
8
|
+
module OpalWebpackLoader
|
9
|
+
class CompileWorker
|
10
|
+
SIGNALS = %w[QUIT TTIN TTOU]
|
11
|
+
|
12
|
+
attr_reader :number, :tempfile
|
13
|
+
|
14
|
+
def initialize(master_pid, socket, tempfile, number)
|
15
|
+
@master_pid = master_pid
|
16
|
+
@socket = socket
|
17
|
+
@tempfile = tempfile
|
18
|
+
@number = number
|
19
|
+
end
|
20
|
+
|
21
|
+
def ==(other_number)
|
22
|
+
number == other_number
|
23
|
+
end
|
24
|
+
|
25
|
+
def start
|
26
|
+
$PROGRAM_NAME = "owl compile worker #{number}"
|
27
|
+
SIGNALS.each { |sig| trap(sig, 'IGNORE') }
|
28
|
+
trap('CHLD', 'DEFAULT')
|
29
|
+
alive = true
|
30
|
+
%w[TERM INT].each { |sig| trap(sig) { exit(0) } }
|
31
|
+
trap('QUIT') do
|
32
|
+
alive = false
|
33
|
+
begin
|
34
|
+
@socket.close
|
35
|
+
rescue
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
ret = nil
|
40
|
+
i = 0
|
41
|
+
while alive && @master_pid == Process.ppid
|
42
|
+
tempfile.chmod(i += 1)
|
43
|
+
|
44
|
+
if ret
|
45
|
+
begin
|
46
|
+
client = @socket.accept_nonblock
|
47
|
+
request = client.gets("\x04")
|
48
|
+
|
49
|
+
if request.start_with?('command:stop')
|
50
|
+
OpalWebpackLoader::CompileServer.unlink_socket_on_exit
|
51
|
+
Process.kill('TERM', @master_pid)
|
52
|
+
exit(0)
|
53
|
+
else
|
54
|
+
result = compile(request)
|
55
|
+
client.write result
|
56
|
+
client.flush
|
57
|
+
client.close
|
58
|
+
end
|
59
|
+
rescue Errno::EAGAIN, Errno::EWOULDBLOCK
|
60
|
+
end
|
61
|
+
end
|
62
|
+
tempfile.chmod(i += 1)
|
63
|
+
ret = begin
|
64
|
+
IO.select([@socket], nil, nil, OpalWebpackLoader::CompileServer::TIMEOUT / 2) || next
|
65
|
+
rescue Errno::EBADF
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def compile(request)
|
73
|
+
request_json = Oj.load(request.chop!, {})
|
74
|
+
|
75
|
+
compile_source_map = request_json["source_map"]
|
76
|
+
filename = request_json["filename"]
|
77
|
+
source = File.read(filename)
|
78
|
+
|
79
|
+
begin
|
80
|
+
c = Opal::Compiler.new(source, file: filename, es6_modules: true)
|
81
|
+
c.compile
|
82
|
+
result = { 'javascript' => c.result }
|
83
|
+
if compile_source_map
|
84
|
+
result['source_map'] = c.source_map.as_json
|
85
|
+
result['source_map']['sourcesContent'] = [source]
|
86
|
+
result['source_map']['file'] = filename
|
87
|
+
result['source_map']['names'] = result['source_map']['names'].map(&:to_s)
|
88
|
+
end
|
89
|
+
result['required_trees'] = c.required_trees
|
90
|
+
Oj.dump(result, {})
|
91
|
+
rescue Exception => e
|
92
|
+
Oj.dump({ 'error' => { 'name' => e.class, 'message' => e.message, 'backtrace' => e.backtrace.join("\n") } }, {})
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -162,7 +162,7 @@ module OpalWebpackLoader
|
|
162
162
|
install_webpack_config
|
163
163
|
install_package_json
|
164
164
|
install_js_entries
|
165
|
-
|
165
|
+
install_opal_entries
|
166
166
|
install_procfile
|
167
167
|
end
|
168
168
|
|
@@ -172,10 +172,12 @@ module OpalWebpackLoader
|
|
172
172
|
create_file_from_template('application_common.js.erb', File.join(@js_entrypoints_directory, 'application_common.js'),erb_hash)
|
173
173
|
create_file_from_template('application_debug.js.erb', File.join(@js_entrypoints_directory, 'application_debug.js'), erb_hash)
|
174
174
|
create_file_from_template('application_ssr.js.erb', File.join(@js_entrypoints_directory, 'application_ssr.js'), erb_hash)
|
175
|
+
create_file_from_template('application_web_worker.js.erb', File.join(@js_entrypoints_directory, 'application_web_worker.js'), erb_hash)
|
175
176
|
end
|
176
177
|
|
177
|
-
def
|
178
|
+
def install_opal_entries
|
178
179
|
create_file_from_template('opal_loader.rb.erb', File.join(@opal_directory, "#{options[:opal_name]}_loader.rb"), {})
|
180
|
+
create_file_from_template('opal_web_worker_loader.rb.erb', File.join(@opal_directory, "#{options[:opal_name]}_web_worker_loader.rb"), {})
|
179
181
|
end
|
180
182
|
|
181
183
|
def install_package_json
|
@@ -226,24 +228,26 @@ module OpalWebpackLoader
|
|
226
228
|
end
|
227
229
|
|
228
230
|
def debug_script
|
229
|
-
"bundle exec opal-webpack-compile-server start webpack-dev-server --config #{File.join(@webpack_config_directory, 'debug.js')}"
|
231
|
+
"bundle exec opal-webpack-compile-server start 4 webpack-dev-server --config #{File.join(@webpack_config_directory, 'debug.js')}"
|
230
232
|
end
|
231
233
|
|
232
234
|
def development_script
|
233
|
-
"bundle exec opal-webpack-compile-server start webpack-dev-server --config #{File.join(@webpack_config_directory, 'development.js')}"
|
235
|
+
"bundle exec opal-webpack-compile-server start 4 webpack-dev-server --config #{File.join(@webpack_config_directory, 'development.js')}"
|
234
236
|
end
|
235
237
|
|
236
238
|
def production_script
|
237
|
-
"bundle exec opal-webpack-compile-server start webpack --config=#{File.join(@webpack_config_directory, 'production.js')}"
|
239
|
+
"bundle exec opal-webpack-compile-server start 4 webpack --config=#{File.join(@webpack_config_directory, 'production.js')}"
|
238
240
|
end
|
239
241
|
|
240
242
|
def install_webpack_config
|
241
243
|
erb_hash = {
|
242
244
|
asset_output_directory: File.join(@conf_rel_prefix, @asset_output_directory),
|
245
|
+
default_targets: 'browser',
|
243
246
|
js_entry: File.join(@conf_rel_prefix, @js_entrypoints_directory, 'application.js'),
|
244
247
|
js_common_entry: File.join(@conf_rel_prefix, @js_entrypoints_directory, 'application_common.js'),
|
245
248
|
js_debug_entry: File.join(@conf_rel_prefix, @js_entrypoints_directory, 'application_debug.js'),
|
246
249
|
js_ssr_entry: File.join(@conf_rel_prefix, @js_entrypoints_directory, 'application_ssr.js'),
|
250
|
+
js_web_worker_entry: File.join(@conf_rel_prefix, @js_entrypoints_directory, 'application_web_worker.js'),
|
247
251
|
opal_directory: File.join(@conf_rel_prefix, @opal_directory),
|
248
252
|
stylesheets_directory: File.join(@conf_rel_prefix, @styles_directory),
|
249
253
|
hmr_hook: ''
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module OpalWebpackLoader
|
2
|
+
class LoadPathManager
|
3
|
+
def self.get_load_path_entries(path)
|
4
|
+
path_entries = []
|
5
|
+
return [] unless Dir.exist?(path)
|
6
|
+
dir_entries = Dir.entries(path)
|
7
|
+
dir_entries.each do |entry|
|
8
|
+
next if entry == '.'
|
9
|
+
next if entry == '..'
|
10
|
+
next unless entry
|
11
|
+
absolute_path = File.join(path, entry)
|
12
|
+
if File.directory?(absolute_path)
|
13
|
+
more_path_entries = get_load_path_entries(absolute_path)
|
14
|
+
path_entries.push(*more_path_entries) if more_path_entries.size > 0
|
15
|
+
elsif (absolute_path.end_with?('.rb') || absolute_path.end_with?('.js')) && File.file?(absolute_path)
|
16
|
+
path_entries.push(absolute_path)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
path_entries
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.create_load_paths_cache
|
23
|
+
load_paths = if File.exist?(File.join('bin', 'rails'))
|
24
|
+
%x{
|
25
|
+
bundle exec rails runner "puts (Rails.configuration.respond_to?(:assets) ? (Rails.configuration.assets.paths + Opal.paths).uniq : Opal.paths)"
|
26
|
+
}
|
27
|
+
else
|
28
|
+
%x{
|
29
|
+
bundle exec ruby -e 'if File.exist?("app_loader.rb"); require "./app_loader.rb"; else; require "bundler/setup"; Bundler.require; set :run, false if defined? Sinatra; end; puts Opal.paths'
|
30
|
+
}
|
31
|
+
end
|
32
|
+
if $? == 0
|
33
|
+
load_path_lines = load_paths.split("\n")
|
34
|
+
load_path_lines.pop if load_path_lines.last == ''
|
35
|
+
|
36
|
+
load_path_entries = []
|
37
|
+
|
38
|
+
cwd = Dir.pwd
|
39
|
+
|
40
|
+
load_path_lines.each do |path|
|
41
|
+
next if path.start_with?(cwd)
|
42
|
+
more_path_entries = get_load_path_entries(path)
|
43
|
+
load_path_entries.push(*more_path_entries) if more_path_entries.size > 0
|
44
|
+
end
|
45
|
+
cache_obj = { 'opal_load_paths' => load_path_lines, 'opal_load_path_entries' => load_path_entries }
|
46
|
+
Dir.mkdir(OpalWebpackLoader::CompileServer::OWL_CACHE_DIR) unless Dir.exist?(OpalWebpackLoader::CompileServer::OWL_CACHE_DIR)
|
47
|
+
File.write(OpalWebpackLoader::CompileServer::OWL_LP_CACHE, Oj.dump(cache_obj, {}))
|
48
|
+
load_path_lines
|
49
|
+
else
|
50
|
+
raise 'Error getting load paths!'
|
51
|
+
exit(2)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
// entry file for browser webworkers
|
2
|
+
// import npm modules that are only valid to use within browser webworkers
|
3
|
+
// import ...;
|
4
|
+
|
5
|
+
// import and load opal ruby files
|
6
|
+
import init_webworker from '<%= opal_name %>_webworker_loader.rb';
|
7
|
+
init_webworker();
|
8
|
+
Opal.load('<%= opal_name %>_webworker_loader');
|
9
|
+
|
10
|
+
// allow for hot reloading
|
11
|
+
if (module.hot) { module.hot.accept(); }
|
@@ -5,7 +5,7 @@ const chokidar = require('chokidar');
|
|
5
5
|
const OwlResolver = require('opal-webpack-loader/resolver'); // to resolve ruby files
|
6
6
|
const ExtraWatchWebpackPlugin = require('extra-watch-webpack-plugin'); // to watch for added ruby files
|
7
7
|
|
8
|
-
|
8
|
+
const common_config = {
|
9
9
|
context: path.resolve(__dirname, '<%= opal_directory %>'),
|
10
10
|
mode: "development",
|
11
11
|
optimization: {
|
@@ -20,10 +20,6 @@ module.exports = {
|
|
20
20
|
// devtool: 'cheap-eval-source-map', // less accurate
|
21
21
|
// devtool: 'inline-source-map', // slowest
|
22
22
|
// devtool: 'inline-cheap-source-map',
|
23
|
-
entry: {
|
24
|
-
application: [path.resolve(__dirname, '<%= js_debug_entry %>')],
|
25
|
-
application_ssr: [path.resolve(__dirname, '<%= js_ssr_entry %>')]
|
26
|
-
},
|
27
23
|
output: {
|
28
24
|
// webpack-dev-server keeps the output in memory
|
29
25
|
filename: '[name].js',
|
@@ -145,8 +141,36 @@ module.exports = {
|
|
145
141
|
// poll: 50,
|
146
142
|
ignored: /\bnode_modules\b/
|
147
143
|
},
|
148
|
-
contentBase: path.resolve(__dirname, 'public')
|
149
|
-
// watchContentBase: true
|
144
|
+
contentBase: path.resolve(__dirname, 'public'),
|
145
|
+
// watchContentBase: true,
|
146
|
+
// writeToDisk: true, // TODO this may need to be activated for ssr to work in development
|
147
|
+
useLocalIp: true
|
150
148
|
}
|
151
149
|
};
|
152
150
|
|
151
|
+
const browser_config = {
|
152
|
+
target: 'web',
|
153
|
+
entry: {
|
154
|
+
application: [path.resolve(__dirname, '<%= js_entry %>')]
|
155
|
+
}
|
156
|
+
};
|
157
|
+
|
158
|
+
const ssr_config = {
|
159
|
+
target: 'node',
|
160
|
+
entry: {
|
161
|
+
application_ssr: [path.resolve(__dirname, '<%= js_ssr_entry %>')]
|
162
|
+
}
|
163
|
+
};
|
164
|
+
|
165
|
+
const web_worker_config = {
|
166
|
+
target: 'webworker',
|
167
|
+
entry: {
|
168
|
+
web_worker: [path.resolve(__dirname, '<%= js_web_worker_entry %>')]
|
169
|
+
}
|
170
|
+
};
|
171
|
+
|
172
|
+
const browser = Object.assign({}, common_config, browser_config);
|
173
|
+
const ssr = Object.assign({}, common_config, ssr_config);
|
174
|
+
const web_worker = Object.assign({}, common_config, web_worker_config);
|
175
|
+
|
176
|
+
module.exports = [ <%= default_targets %> ];
|
@@ -5,7 +5,7 @@ const chokidar = require('chokidar');
|
|
5
5
|
const OwlResolver = require('opal-webpack-loader/resolver'); // to resolve ruby files
|
6
6
|
const ExtraWatchWebpackPlugin = require('extra-watch-webpack-plugin'); // to watch for added ruby files
|
7
7
|
|
8
|
-
|
8
|
+
const common_config = {
|
9
9
|
context: path.resolve(__dirname, '<%= opal_directory %>'),
|
10
10
|
mode: "development",
|
11
11
|
optimization: {
|
@@ -15,10 +15,6 @@ module.exports = {
|
|
15
15
|
maxAssetSize: 20000000,
|
16
16
|
maxEntrypointSize: 20000000
|
17
17
|
},
|
18
|
-
entry: {
|
19
|
-
application: [path.resolve(__dirname, '<%= js_entry %>')],
|
20
|
-
application_ssr: [path.resolve(__dirname, '<%= js_ssr_entry %>')]
|
21
|
-
},
|
22
18
|
output: {
|
23
19
|
// webpack-dev-server keeps the output in memory
|
24
20
|
filename: '[name].js',
|
@@ -129,8 +125,36 @@ module.exports = {
|
|
129
125
|
// poll: 50,
|
130
126
|
ignored: /\bnode_modules\b/
|
131
127
|
},
|
132
|
-
contentBase: path.resolve(__dirname, 'public')
|
133
|
-
// watchContentBase: true
|
128
|
+
contentBase: path.resolve(__dirname, 'public'),
|
129
|
+
// watchContentBase: true,
|
130
|
+
// writeToDisk: true,
|
131
|
+
useLocalIp: true
|
134
132
|
}
|
135
133
|
};
|
136
134
|
|
135
|
+
const browser_config = {
|
136
|
+
target: 'web',
|
137
|
+
entry: {
|
138
|
+
application: [path.resolve(__dirname, '<%= js_entry %>')]
|
139
|
+
}
|
140
|
+
};
|
141
|
+
|
142
|
+
const ssr_config = {
|
143
|
+
target: 'node',
|
144
|
+
entry: {
|
145
|
+
application_ssr: [path.resolve(__dirname, '<%= js_ssr_entry %>')]
|
146
|
+
}
|
147
|
+
};
|
148
|
+
|
149
|
+
const web_worker_config = {
|
150
|
+
target: 'webworker',
|
151
|
+
entry: {
|
152
|
+
webworker: [path.resolve(__dirname, '<%= js_web_worker_entry %>')]
|
153
|
+
}
|
154
|
+
};
|
155
|
+
|
156
|
+
const browser = Object.assign({}, common_config, browser_config);
|
157
|
+
const ssr = Object.assign({}, common_config, ssr_config);
|
158
|
+
const web_worker = Object.assign({}, common_config, web_worker_config);
|
159
|
+
|
160
|
+
module.exports = [ <%= default_targets %> ];
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require 'opal'
|
2
|
+
|
3
|
+
# the gem opal-autoloader may be used, so its not necessary to use 'require' all the time,
|
4
|
+
# just using 'require_tree' to bundle everything is enough:
|
5
|
+
#
|
6
|
+
# require 'opal-autoloader'
|
7
|
+
# require_tree 'my_app' # for a sub directory 'my_app'
|
8
|
+
|
9
|
+
|
@@ -3,7 +3,7 @@ const OwlResolver = require('opal-webpack-loader/resolver');
|
|
3
3
|
const CompressionPlugin = require("compression-webpack-plugin"); // for gzipping the packs
|
4
4
|
const ManifestPlugin = require('webpack-manifest-plugin'); // for generating the manifest
|
5
5
|
|
6
|
-
|
6
|
+
const common_config = {
|
7
7
|
context: path.resolve(__dirname, '<%= opal_directory %>'),
|
8
8
|
mode: "production",
|
9
9
|
optimization: {
|
@@ -13,10 +13,6 @@ module.exports = {
|
|
13
13
|
maxAssetSize: 20000000,
|
14
14
|
maxEntrypointSize: 20000000
|
15
15
|
},
|
16
|
-
entry: {
|
17
|
-
application: [path.resolve(__dirname, '<%= js_entry %>')],
|
18
|
-
application_ssr: [path.resolve(__dirname, '<%= js_ssr_entry %>')]
|
19
|
-
},
|
20
16
|
output: {
|
21
17
|
filename: '[name]-[chunkhash].js', // include fingerprint in file name, so browsers get the latest
|
22
18
|
path: path.resolve(__dirname, '<%= asset_output_directory %>'),
|
@@ -92,3 +88,29 @@ module.exports = {
|
|
92
88
|
}
|
93
89
|
};
|
94
90
|
|
91
|
+
const browser_config = {
|
92
|
+
target: 'web',
|
93
|
+
entry: {
|
94
|
+
application: [path.resolve(__dirname, '<%= js_entry %>')]
|
95
|
+
}
|
96
|
+
};
|
97
|
+
|
98
|
+
const ssr_config = {
|
99
|
+
target: 'node',
|
100
|
+
entry: {
|
101
|
+
application_ssr: [path.resolve(__dirname, '<%= js_ssr_entry %>')]
|
102
|
+
}
|
103
|
+
};
|
104
|
+
|
105
|
+
const web_worker_config = {
|
106
|
+
target: 'webworker',
|
107
|
+
entry: {
|
108
|
+
web_worker: [path.resolve(__dirname, '<%= js_web_worker_entry %>')]
|
109
|
+
}
|
110
|
+
};
|
111
|
+
|
112
|
+
const browser = Object.assign({}, common_config, browser_config);
|
113
|
+
const ssr = Object.assign({}, common_config, ssr_config);
|
114
|
+
const web_worker = Object.assign({}, common_config, web_worker_config);
|
115
|
+
|
116
|
+
module.exports = [ <%= default_targets %> ];
|
data/spec/installer_spec.rb
CHANGED
@@ -27,7 +27,9 @@ RSpec.describe 'owl installer' do
|
|
27
27
|
expect(File.exist?(File.join('app', 'assets', 'javascripts', 'application_common.js'))).to be true
|
28
28
|
expect(File.exist?(File.join('app', 'assets', 'javascripts', 'application_debug.js'))).to be true
|
29
29
|
expect(File.exist?(File.join('app', 'assets', 'javascripts', 'application_ssr.js'))).to be true
|
30
|
+
expect(File.exist?(File.join('app', 'assets', 'javascripts', 'application_web_worker.js'))).to be true
|
30
31
|
expect(File.exist?(File.join('app', 'opal', 'opal_loader.rb'))).to be true
|
32
|
+
expect(File.exist?(File.join('app', 'opal', 'opal_web_worker_loader.rb'))).to be true
|
31
33
|
expect(File.exist?(File.join('config', 'initializers', 'opal_webpack_loader.rb'))).to be true
|
32
34
|
expect(File.exist?(File.join('config', 'webpack', 'debug.js'))).to be true
|
33
35
|
expect(File.exist?(File.join('config', 'webpack', 'development.js'))).to be true
|
@@ -48,7 +50,9 @@ RSpec.describe 'owl installer' do
|
|
48
50
|
expect(File.exist?(File.join('app', 'assets', 'javascripts', 'application_common.js'))).to be true
|
49
51
|
expect(File.exist?(File.join('app', 'assets', 'javascripts', 'application_debug.js'))).to be true
|
50
52
|
expect(File.exist?(File.join('app', 'assets', 'javascripts', 'application_ssr.js'))).to be true
|
53
|
+
expect(File.exist?(File.join('app', 'assets', 'javascripts', 'application_web_worker.js'))).to be true
|
51
54
|
expect(File.exist?(File.join('app', 'hyperhyper', 'hyperhyper_loader.rb'))).to be true
|
55
|
+
expect(File.exist?(File.join('app', 'hyperhyper', 'hyperhyper_web_worker_loader.rb'))).to be true
|
52
56
|
expect(File.exist?(File.join('config', 'initializers', 'opal_webpack_loader.rb'))).to be true
|
53
57
|
expect(File.exist?(File.join('config', 'webpack', 'debug.js'))).to be true
|
54
58
|
expect(File.exist?(File.join('config', 'webpack', 'development.js'))).to be true
|
data/spec/owl_spec.rb
CHANGED
@@ -15,19 +15,18 @@ RSpec.describe 'owl' do
|
|
15
15
|
|
16
16
|
after do
|
17
17
|
Dir.chdir('..') if Dir.pwd.end_with?('railing')
|
18
|
-
|
18
|
+
FileUtils.rm_rf('railing') if Dir.exist?('railing')
|
19
19
|
Dir.chdir('..')
|
20
20
|
Dir.chdir('..')
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'can run the production build script' do
|
24
|
-
`bundle exec rails new railing --skip-git --skip-bundle --skip-sprockets --skip-spring --skip-bootsnap`
|
24
|
+
`bundle exec rails new railing --skip-git --skip-bundle --skip-sprockets --skip-javascript --skip-spring --skip-bootsnap`
|
25
25
|
expect(Dir.exist?('railing')).to be true
|
26
26
|
Dir.chdir('railing')
|
27
27
|
arg_val = %w[rails]
|
28
28
|
expect(Dir.exist?(File.join('railing', 'config', 'webpack'))).to be false
|
29
29
|
OpalWebpackLoader::Installer::CLI.start(arg_val)
|
30
|
-
FileUtils.mv(File.join('app', 'assets', 'javascripts', 'application.js_owl_new'), File.join('app', 'assets', 'javascripts', 'application.js´'))
|
31
30
|
gemfile = File.read('Gemfile')
|
32
31
|
gemfile << <<~GEMS
|
33
32
|
|
@@ -67,7 +66,7 @@ RSpec.describe 'owl' do
|
|
67
66
|
|
68
67
|
after do
|
69
68
|
Dir.chdir('..') if Dir.pwd.end_with?('flattering')
|
70
|
-
|
69
|
+
FileUtils.rm_rf('flattering') if Dir.exist?('flattering')
|
71
70
|
Dir.chdir('..')
|
72
71
|
Dir.chdir('..')
|
73
72
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opal-webpack-loader
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jan Biedermann
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-04-
|
11
|
+
date: 2019-04-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: opal
|
@@ -24,20 +24,6 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 0.11.0
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: eventmachine
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 1.2.7
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: 1.2.7
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: oj
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -150,7 +136,9 @@ files:
|
|
150
136
|
- bin/owl-install
|
151
137
|
- lib/opal-webpack-loader.rb
|
152
138
|
- lib/opal-webpack-loader/compile_server.rb
|
139
|
+
- lib/opal-webpack-loader/compile_worker.rb
|
153
140
|
- lib/opal-webpack-loader/installer_cli.rb
|
141
|
+
- lib/opal-webpack-loader/load_path_manager.rb
|
154
142
|
- lib/opal-webpack-loader/manifest.rb
|
155
143
|
- lib/opal-webpack-loader/rails_view_helper.rb
|
156
144
|
- lib/opal-webpack-loader/templates/Procfile.erb
|
@@ -160,10 +148,12 @@ files:
|
|
160
148
|
- lib/opal-webpack-loader/templates/application_common.js.erb
|
161
149
|
- lib/opal-webpack-loader/templates/application_debug.js.erb
|
162
150
|
- lib/opal-webpack-loader/templates/application_ssr.js.erb
|
151
|
+
- lib/opal-webpack-loader/templates/application_web_worker.js.erb
|
163
152
|
- lib/opal-webpack-loader/templates/debug.js.erb
|
164
153
|
- lib/opal-webpack-loader/templates/development.js.erb
|
165
154
|
- lib/opal-webpack-loader/templates/initializer.rb.erb
|
166
155
|
- lib/opal-webpack-loader/templates/opal_loader.rb.erb
|
156
|
+
- lib/opal-webpack-loader/templates/opal_web_worker_loader.rb.erb
|
167
157
|
- lib/opal-webpack-loader/templates/package.json.erb
|
168
158
|
- lib/opal-webpack-loader/templates/production.js.erb
|
169
159
|
- lib/opal-webpack-loader/templates/webpacker_development.js_example
|