svelte-on-rails 20.0.18 → 21.0.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: 7711f39780f053fa47efe51b4f6c2de5b31afd3ff0feb28728003caa96618a40
4
- data.tar.gz: 85d5e6687e93b28d79746e1ea535f193d1f8e76b368f40a4a925642fbc67ae52
3
+ metadata.gz: d147f7ea42b28a7d979d93b2ba336fe2076763d1b05d248ff6b2d17dc293ef10
4
+ data.tar.gz: b33ff7321a8db1c2b58350d8a433d75329727f625030e96a53e70ecaf093b572
5
5
  SHA512:
6
- metadata.gz: eb80a3bff65909ddaa0d1a27f81b34f5d31e6f101ba4c138b8def261774c9bffecbc748933323f320c49bb47f5efc8bd6395c0893f941d4fd4f311a309533d54
7
- data.tar.gz: 6054c173995e79a91fb770d5fc924a4795e6c7fdd6c934961872d4a7dedeb525de3b15b998f08d3b5a67ff3524d43472389934c57f7791dca6fcc03a57c7175a
6
+ metadata.gz: 063f55d363284af5924f1a07966b1da39f1b17c123ad93060b29fa6832941d77337de852d9a9f9b38fe9cf4489a3d59852bc50b1a067176ddd1ca67db5a11b15
7
+ data.tar.gz: 06fc37fa2b5fa1cebdfb8fc4758b9fa27e87a0d7b09484df648dee441ffc2df5a79f48da79d6549adf06c139289b233a0628f5d4c07d353eb6df54f753d4c403
@@ -16,6 +16,7 @@ module SvelteOnRails
16
16
 
17
17
  @boot_key = SecureRandom.hex(3) # currently not used, more for debugging purposes
18
18
  @configs = redis_cache_store_configs
19
+ set_config_defaults
19
20
 
20
21
  @component_paths_cache = {}
21
22
  @request_metrics = {}
@@ -36,9 +37,11 @@ module SvelteOnRails
36
37
  merged_configs = configs_base.deep_merge(env_configs || {})
37
38
 
38
39
  # cleanup
39
- @configs = merged_configs.reject { |k, _| environments.include?(k.to_s) }
40
+ polished_configs = merged_configs.reject { |k, _| environments.include?(k.to_s) }
41
+ @configs = @configs.merge(polished_configs)
42
+
43
+ # DEFAULTS
40
44
 
41
- # caching defaults
42
45
  if @configs[:redis_cache_store]
43
46
  store = @configs[:redis_cache_store]
44
47
  if store['expires_in'].is_a?(String)
@@ -54,10 +57,18 @@ module SvelteOnRails
54
57
  @redis_instance = Redis.new(url: redis_cache_store[:url])
55
58
  end
56
59
 
57
- validate_configs
60
+ validate_serialized_configs
61
+ custom_config_validations
58
62
  validate_npm_packages
59
63
  end
60
64
 
65
+ def set_config_defaults
66
+ @configs[:ssr_server] = true
67
+ @configs[:ssr_server_workers] = 1
68
+ @configs[:ssr_fallback_renderer] = false
69
+ @configs[:ssr_error_tag] = true
70
+ end
71
+
61
72
  def redis_cache_store
62
73
  (@configs[:redis_cache_store] || {}).transform_keys(&:to_sym)
63
74
  end
@@ -139,7 +150,9 @@ module SvelteOnRails
139
150
  end
140
151
 
141
152
  def ssr_server_bin_path
142
- Rails.root.join(Pathname('node_modules/@csedl/svelte-on-rails/bin/svelte-ssr-server.js'))
153
+ wk = @configs[:ssr_server_workers]
154
+ str = wk > 1 ? 'cluster' : 'server'
155
+ Rails.root.join(Pathname("node_modules/@csedl/svelte-on-rails/bin/svelte-ssr-#{str}.js"))
143
156
  end
144
157
 
145
158
  def initialize_request_metrics(request_uuid)
@@ -184,7 +197,7 @@ module SvelteOnRails
184
197
  ActiveSupport::Duration.build(number.send(unit))
185
198
  end
186
199
 
187
- def validate_configs
200
+ def validate_serialized_configs
188
201
 
189
202
  # custom validations
190
203
 
@@ -196,9 +209,13 @@ module SvelteOnRails
196
209
 
197
210
  keys = {
198
211
  vite_source_dir: { required: :string },
199
- use_ssr_server: { required: :boolean },
200
212
  use_caching: { required: :boolean },
201
213
 
214
+ ssr_server: { optional: :boolean },
215
+ ssr_server_workers: { optional: :integer },
216
+ ssr_fallback_renderer: { optional: :boolean },
217
+ ssr_error_tag: { optional: :boolean },
218
+
202
219
  cache_expiration_hours: { optional: :integer },
203
220
  components_subdir: { optional: :string },
204
221
  default_components_root: { required: :string },
@@ -262,6 +279,15 @@ module SvelteOnRails
262
279
 
263
280
  end
264
281
 
282
+ def custom_config_validations
283
+ if !@configs[:ssr_server] && !@configs[:ssr_fallback_renderer]
284
+ raise "[SOR] Configuration error: Either :ssr_server or :ssr_fallback_renderer must be set to true"
285
+ end
286
+ if @configs[:ssr_server_workers] < 1
287
+ raise "[SOR] Configuration error: :ssr_server_workers must be greater than 0"
288
+ end
289
+ end
290
+
265
291
  def validate_npm_packages
266
292
  pkg = JSON.parse(File.read(Rails.root.join('package.json')))
267
293
  deps = (pkg['dependencies'] || {}).merge(pkg['devDependencies'] || {})
@@ -280,12 +306,20 @@ module SvelteOnRails
280
306
  raise "[Svelte-on-Rails] NPM-Package @csedl/svelte-on-rails: Could not detect version from: «#{sor}»"
281
307
  end
282
308
 
283
- if Gem::Version.new(version) < Gem::Version.new('14.0.0')
284
- raise "[Svelte-on-Rails] NPM-Package @csedl/svelte-on-rails: At least version 14.0.0 is required, but found: «#{sor}»"
309
+ # npm package version
310
+
311
+ if Gem::Version.new(version) < Gem::Version.new('15.0.0')
312
+ raise "[Svelte-on-Rails] NPM-Package @csedl/svelte-on-rails: At least version 15.0.0 is required, but found: «#{sor}»"
285
313
  end
286
314
 
287
- unless node_version_test.to_s.match(/v\d+\.\d+\.\d+/)
288
- raise "[Svelte-on-Rails] Node Version could not be detected.\nPlease check your Node.js installation:\n#{@node_bin_path_log.join("\n")}"
315
+ # check version
316
+ if @configs[:ssr]
317
+ unless node_version_test.to_s.match(/v\d+\.\d+\.\d+/)
318
+ raise "[Svelte-on-Rails] Node Version could not be detected.\nPlease check your Node.js installation:\n#{@node_bin_path_log.join("\n")}"
319
+ end
320
+ if Gem::Version.new(node_version_test.to_s.delete_prefix('v')) < Gem::Version.new('22.0.0')
321
+ raise "[Svelte-on-Rails] Node Version (#{}) is too old, at least version 22.0.0 is required"
322
+ end
289
323
  end
290
324
  end
291
325
 
@@ -153,16 +153,17 @@ module SvelteOnRails
153
153
  trace[0..last_match_index]
154
154
  end
155
155
 
156
+ # Log for debugging purposes
156
157
  def self.secure_debug_log(line)
157
- base = Rails.root.join('tmp')
158
+ # base = Rails.root.join('tmp')
158
159
 
159
- FileUtils.mkdir_p(base) unless File.directory?(base)
160
- path = File.join(base.to_s, 'sor.log')
160
+ # FileUtils.mkdir_p(base) unless File.directory?(base)
161
+ # path = File.join(base.to_s, 'svelte-on-rails.log')
161
162
 
162
- File.open(path, 'a') do |f|
163
- f.sync = true
164
- f.puts("[#{Time.now.utc.iso8601(3)}] [pid=#{Process.pid}] #{line}")
165
- end
163
+ # File.open(path, 'a') do |f|
164
+ # f.sync = true
165
+ # f.puts("[#{Time.now.utc.iso8601(3)}] [pid=#{Process.pid}] #{line}")
166
+ # end
166
167
  rescue => e
167
168
  # Last resort: write the failure itself to stderr; never raise.
168
169
  warn "[SOR] sor_debug_log failed: #{e.class}: #{e.message}"
@@ -164,16 +164,8 @@ module SvelteOnRails
164
164
  caller_locations.find { |loc| loc.to_s.include?(v_path) }.to_s.match(/^[\s\S]+(:[0-9]+(?=:in))/).to_s
165
165
  end
166
166
 
167
- r = if SvelteOnRails::SsrServer.instance.alive?
168
- SvelteOnRails::SsrServer.instance.render(
169
- component_paths,
170
- cached_props,
171
- debug?,
172
- caller_loc
173
- )
174
- else
175
- SvelteOnRails::Lib::FallbackRenderer.render(component_paths, cached_props, debug?)
176
- end
167
+ r = render_with_ssr_server(caller_loc) || render_with_fallback
168
+
177
169
  if r[:success]
178
170
  set_request_metrics(:rendered)
179
171
  else
@@ -237,6 +229,24 @@ module SvelteOnRails
237
229
 
238
230
  private
239
231
 
232
+ def render_with_ssr_server(caller_loc)
233
+ return {} unless @conf.configs[:ssr_server]
234
+
235
+ result = SvelteOnRails::SsrServer.instance.render(
236
+ component_paths,
237
+ cached_props,
238
+ debug?,
239
+ caller_loc
240
+ )
241
+ result[:success] ? result : render_with_fallback
242
+ end
243
+
244
+ def render_with_fallback
245
+ return {} unless @conf.configs[:ssr_fallback_renderer]
246
+
247
+ SvelteOnRails::Lib::FallbackRenderer.render(component_paths, cached_props, debug?)
248
+ end
249
+
240
250
  def run_vite_build
241
251
  r = @conf.vite_build
242
252
 
@@ -298,6 +308,11 @@ module SvelteOnRails
298
308
  end
299
309
 
300
310
  def resolve_ssr?(request)
311
+
312
+ # Setting SSR to false at the global level will disable SSR.
313
+ # Reason: In emergency cases, the developer may want to disable SSR.
314
+ return false if @conf.configs[:ssr] == false
315
+
301
316
  _ssr = if !@options[:ssr].nil?
302
317
  @options[:ssr]
303
318
  elsif !@conf.configs[:ssr].nil?
@@ -18,9 +18,9 @@ module SvelteOnRails
18
18
  app.config.after_initialize do
19
19
 
20
20
  if defined?(Rake) && Rake.respond_to?(:application) && Rake.application.top_level_tasks.any?
21
- puts "[Skipping svelte-on-rails because of top level task: #{Rake.application.top_level_tasks.join(', ')}]"
21
+ puts "[Skipping svelte-on-rails SSR-Server because of top level task: #{Rake.application.top_level_tasks.join(', ')}]"
22
22
  $stdout.flush
23
- else
23
+ elsif SvelteOnRails::Configuration.instance.configs[:ssr]
24
24
  SvelteOnRails::Lib::Utils.secure_debug_log("Initializing SSR client")
25
25
  SvelteOnRails::SsrServer.instance
26
26
  SvelteOnRails::Lib::Utils.secure_debug_log("Initializing SSR client finished")
@@ -28,13 +28,12 @@ module SvelteOnRails
28
28
  @logfile_path = Rails.root.join("log/svelte-ssr-server-#{Rails.env}.log")
29
29
  @logfile_max_lines = build_logfile_max_lines
30
30
  @socket_path = @helpers.socket_path
31
- @use_ssr_server = SvelteOnRails::Configuration.instance.configs[:use_ssr_server]
32
- @node_bin = SvelteOnRails::Configuration.instance.node_bin_path
33
- @ssr_server_bin_path = SvelteOnRails::Configuration.instance.ssr_server_bin_path
31
+ @ssr_server = SvelteOnRails::Configuration.instance.configs[:ssr_server]
32
+ @ssr_server_bin_path = @helpers.ssr_server_bin_path
34
33
 
35
34
  File.delete(restart_marker_file) if File.exist?(restart_marker_file)
36
35
 
37
- if @use_ssr_server
36
+ if @ssr_server
38
37
  # if !defined?(Rails::Server)
39
38
  # SvelteOnRails::Lib::Utils.secure_debug_log("Rails Server is not yet defined, SSR Server cannot be started because of initializing too early")
40
39
  # else
@@ -48,8 +47,8 @@ module SvelteOnRails
48
47
  File.delete(restart_marker_file) if File.exist?(restart_marker_file)
49
48
  end
50
49
  else
51
- SvelteOnRails::Lib::Utils.secure_debug_log("SSR Server NOT used => @use_ssr_server #{@use_ssr_server}")
52
- SvelteOnRails::Lib::Utils.secure_debug_log("SSR Server NOT used => @use_ssr_server #{defined?(Rails::Server)}")
50
+ SvelteOnRails::Lib::Utils.secure_debug_log("SSR Server NOT used => @ssr_server #{@ssr_server}")
51
+ SvelteOnRails::Lib::Utils.secure_debug_log("SSR Server NOT used => @ssr_server #{defined?(Rails::Server)}")
53
52
  end
54
53
 
55
54
  end
@@ -149,7 +148,6 @@ module SvelteOnRails
149
148
  end
150
149
 
151
150
  def ping?
152
- @alive = false
153
151
  shorten_logfile
154
152
  unless File.exist?(socket_path)
155
153
  return false
@@ -169,7 +167,7 @@ module SvelteOnRails
169
167
  unless r['version'].split('.').first.to_i >= 14
170
168
  puts "[SOR] WARNING: Required SSR Server version is at least 14.x, you have installed @csedl/svelte-on-rails: #{r['version']}"
171
169
  end
172
- @alive = r['status'] == 'alive'
170
+ r['status'] == 'alive'
173
171
  end
174
172
  end
175
173
 
@@ -182,17 +180,11 @@ module SvelteOnRails
182
180
  File.write(@helpers.ssr_server_ppid_file, Process.ppid.to_s)
183
181
 
184
182
  start = Time.now
185
- cmd = [
186
- "SVELTE_SSR_SERVER_STARTED_BY=#{started_by}",
187
- @node_bin,
188
- @ssr_server_bin_path,
189
- @socket_path
190
- ].join(' ')
191
183
 
192
184
  @node_server_output = {}
193
185
  Thread.new do
194
186
  stdout, stderr, status = Open3.capture3(
195
- cmd,
187
+ @helpers.start_node_server_command(started_by),
196
188
  chdir: Rails.root
197
189
  )
198
190
  @node_server_output = {
@@ -201,57 +193,30 @@ module SvelteOnRails
201
193
  status: status
202
194
  }
203
195
  end
204
- start_server_log(start, "Node Version: #{Configuration.instance.node_version_test}, package version: #{Configuration.instance.npm_package_version_test}")
205
- start_server_log(start, "Start running Svelte-SSR-Server... (#{started_by})")
196
+ @helpers.start_server_log(start, "Node Version: #{Configuration.instance.node_version_test}, package version: #{Configuration.instance.npm_package_version_test}")
197
+ @helpers.start_server_log(start, "Start running Svelte-SSR-Server... (#{started_by})")
206
198
 
207
199
  until node_server_pid do
208
200
  sleep 0.12
209
- start_server_log(start, "Waiting for node server process-id")
201
+ @helpers.start_server_log(start, "Waiting for node server process-id")
210
202
  start_server_timeout!(start)
211
203
  end
212
204
 
213
205
  until File.exist?(socket_path) do
214
206
  sleep 0.1
215
- start_server_log(start, "Waiting for socket to be created")
207
+ @helpers.start_server_log(start, "Waiting for socket to be created")
216
208
  start_server_timeout!(start)
217
209
  end
218
- start_server_log(start, "Socket created: #{socket_path}")
210
+ @helpers.start_server_log(start, "Socket created: #{socket_path}")
219
211
 
220
212
  until ping? do
221
- start_server_log(start, "Waiting for successful server-response")
213
+ @helpers.start_server_log(start, "Waiting for successful server-response")
222
214
  start_server_timeout!(start)
223
215
  sleep 0.1
224
216
  end
225
- start_server_log(start, "Server responded successfully")
226
-
227
- kill_leftover_processes
228
- end
229
-
230
- def kill_leftover_processes
231
- stdout, stderr, status = Open3.capture3(
232
- "ps aux | grep svelte"
233
- )
234
-
235
- leftover = stdout.split("\n").map do |line|
236
- if line.match?(/\/#{@socket_namespace}-[0-9]+.sock$/)
237
- unless line.match?(/\/#{@socket_namespace}-#{Process.ppid}.sock$/)
238
- line.match(/[0-9]+/).to_s.to_i
239
- end
240
- end
241
- end.compact
242
-
243
- stdout, stderr, status = Open3.capture3(
244
- "kill #{leftover.join(' ')}"
245
- )
246
-
247
- start_server_log(nil, "Killed #{leftover.length} leftover processes") if leftover.length >= 1
248
- end
249
-
250
- def kill_my_server
251
- Process.kill("SIGINT", (node_server_pid || 0)) if node_server_pid
252
- File.delete(@helpers.ssr_server_ppid_file)
253
- rescue
217
+ @helpers.start_server_log(start, "Server responded successfully")
254
218
 
219
+ @helpers.cleanup_leftover_processes
255
220
  end
256
221
 
257
222
  def restart_my_server(tag = nil)
@@ -274,10 +239,6 @@ module SvelteOnRails
274
239
  end
275
240
  end
276
241
 
277
- def alive?
278
- @alive
279
- end
280
-
281
242
  def node_server_pid
282
243
  stdout, stderr, status = Open3.capture3(
283
244
  "ps aux | grep svelte"
@@ -320,21 +281,6 @@ module SvelteOnRails
320
281
  end
321
282
  end
322
283
 
323
- def start_server_log(start_time, msg)
324
- line =
325
- if start_time
326
- ms = ((Time.now - start_time) * 1000).round(1)
327
- "[SOR] #{msg} (#{ms}ms)"
328
- else
329
- "[SOR] #{msg}"
330
- end
331
-
332
- puts line
333
- $stdout.flush
334
-
335
- SvelteOnRails::Lib::Utils.secure_debug_log(line)
336
- end
337
-
338
284
  def stop_server_timeout!(start_time, timeout: 2000)
339
285
  ms = ((Time.now - start_time) * 1000).round(1)
340
286
  if ms > timeout
@@ -385,7 +331,8 @@ module SvelteOnRails
385
331
  # For that reason they are within a separate class
386
332
 
387
333
  attr_reader :socket_namespace,
388
- :socket_path
334
+ :socket_path,
335
+ :ssr_server_bin_path
389
336
 
390
337
  def initialize
391
338
 
@@ -395,6 +342,8 @@ module SvelteOnRails
395
342
  Rails.env,
396
343
  ].join("-")
397
344
 
345
+ @ssr_server_bin_path = SvelteOnRails::Configuration.instance.ssr_server_bin_path
346
+
398
347
  end
399
348
 
400
349
  def ssr_server_ppid_file
@@ -417,6 +366,97 @@ module SvelteOnRails
417
366
  fallback
418
367
  end
419
368
 
369
+ def start_node_server_command(started_by, ppid: Process.ppid)
370
+ workers = SvelteOnRails::Configuration.instance.configs[:ssr_server_workers]
371
+ [
372
+ (started_by ? "SVELTE_SSR_SERVER_STARTED_BY=#{started_by}" : nil),
373
+ SvelteOnRails::Configuration.instance.node_bin_path,
374
+ @ssr_server_bin_path,
375
+ socket_path(ppid: ppid),
376
+ (workers > 1 ? "--workers=#{workers}" : nil)
377
+ ].compact.join(' ')
378
+ end
379
+
380
+ SsrProcess = Struct.new(:pid, :ppid, :socket_path, keyword_init: true)
381
+
382
+ def own_processes(current_ppid: Process.ppid)
383
+ scan_processes.select { |p| p.ppid == current_ppid }
384
+ end
385
+
386
+ def leftover_processes(current_ppid: Process.ppid)
387
+ scan_processes.reject { |p| p.ppid == current_ppid }
388
+ end
389
+
390
+ def leftover_sockets(current_ppid: Process.ppid)
391
+ scan_sockets.reject { |s| s[:ppid] == current_ppid }
392
+ end
393
+
394
+ def cleanup_leftover_processes(current_ppid: Process.ppid)
395
+ terminate_processes(leftover_processes(current_ppid: current_ppid), label: "leftover")
396
+ delete_sockets(leftover_sockets(current_ppid: current_ppid).map { |s| s[:path] }, label: "leftover")
397
+ end
398
+
399
+ def shutdown(current_ppid: Process.ppid)
400
+ terminate_processes(own_processes(current_ppid: current_ppid), label: "own")
401
+ ensure
402
+ File.delete(ssr_server_ppid_file) if File.exist?(ssr_server_ppid_file)
403
+ end
404
+
405
+ def start_server_log(start_time, msg)
406
+ line = start_time ? "[SOR] #{msg} (#{((Time.now - start_time) * 1000).round(1)}ms)" : "[SOR] #{msg}"
407
+ puts line
408
+ $stdout.flush
409
+ SvelteOnRails::Lib::Utils.secure_debug_log(line)
410
+ end
411
+
412
+ private
413
+
414
+ # Cluster mode: a primary + N workers share one socket path.
415
+ # SIGINT the primary first (lowest pid per socket group); survivors get SIGINT too.
416
+ def terminate_processes(processes, label:)
417
+ return if processes.empty?
418
+
419
+ processes.group_by(&:socket_path).values.flat_map { |g| g.sort_by(&:pid) }.each do |p|
420
+ Process.kill("SIGINT", p.pid) rescue Errno::ESRCH || Errno::EPERM
421
+ end
422
+
423
+ start_server_log(nil, "Killed #{processes.length} #{label} process#{'es' if processes.length != 1}")
424
+ end
425
+
426
+ def delete_sockets(socket_paths, label:)
427
+ return if socket_paths.empty?
428
+
429
+ socket_paths.uniq.each do |path|
430
+ File.delete(path) if File.exist?(path)
431
+ rescue Errno::ENOENT
432
+ # raced with primary's own cleanup — fine
433
+ end
434
+
435
+ start_server_log(nil, "Deleted #{socket_paths.size} #{label} socket#{'s' if socket_paths.size != 1}")
436
+ end
437
+
438
+ # All running SSR processes matching our namespace (any ppid).
439
+ def scan_processes
440
+ stdout, = Open3.capture3("ps aux | grep svelte | grep -v grep")
441
+ regex = %r{(/\S*#{Regexp.escape(@socket_namespace)}-(\d+)\.sock)\b}
442
+
443
+ stdout.each_line.filter_map do |line|
444
+ m = line.match(regex) or next
445
+ pid = Integer(line.split(/\s+/, 12)[1], exception: false) or next
446
+ SsrProcess.new(pid: pid, ppid: m[2].to_i, socket_path: m[1])
447
+ end
448
+ end
449
+
450
+ # All socket files on disk matching our namespace (any ppid).
451
+ # Looks in both the app's tmp/sockets dir and the macOS/BSD fallback dir.
452
+ def scan_sockets
453
+ dirs = [Rails.root.join("tmp/sockets").to_s, "/tmp/svelte"]
454
+ regex = /#{Regexp.escape(@socket_namespace)}-(\d+)\.sock\z/
455
+
456
+ dirs.flat_map { |d| Dir.glob(File.join(d, "#{@socket_namespace}-*.sock")) }
457
+ .filter_map { |path| (m = path.match(regex)) && { path: path, ppid: m[1].to_i } }
458
+ end
459
+
420
460
  end
421
461
 
422
462
  class SsrError < StandardError; end
@@ -48,8 +48,10 @@ module SvelteOnRails
48
48
  concat(rnd[:head].html_safe)
49
49
  concat(rnd[:html].html_safe)
50
50
  support.log_completed("returned from cache, with uncached props#{', (Fallback!)' if rnd[:fallback]}")
51
- else
51
+ elsif config.configs[:ssr_error_tag]
52
52
  sor_error_tag(support, wrapper_html, component_props, 'server-side-svelte-render-error', 'SVELTE RENDER FAILED')
53
+ else
54
+ render_empty_tag(support, wrapper_html, component_props)
53
55
  end
54
56
  end
55
57
  end
@@ -74,7 +76,11 @@ module SvelteOnRails
74
76
  r
75
77
  else
76
78
  log = "ERROR"
77
- sor_error_tag(support, wrapper_html, component_props, 'server-side-svelte-render-error', 'SVELTE RENDER FAILED')
79
+ if config.configs[:ssr_error_tag]
80
+ sor_error_tag(support, wrapper_html, component_props, 'server-side-svelte-render-error', 'SVELTE RENDER FAILED')
81
+ else
82
+ render_empty_tag(support, wrapper_html, component_props)
83
+ end
78
84
  end
79
85
  end
80
86
  support.log_completed(log)
@@ -92,8 +98,10 @@ module SvelteOnRails
92
98
  concat(rnd[:head].html_safe)
93
99
  concat(rnd[:html].html_safe)
94
100
  end
95
- else
101
+ elsif config.configs[:ssr_error_tag]
96
102
  sor_error_tag(support, wrapper_html, component_props, 'server-side-svelte-render-error', 'SVELTE RENDER FAILED')
103
+ else
104
+ render_empty_tag(support, wrapper_html, component_props)
97
105
  end
98
106
 
99
107
  support.log_completed("Rendered#{rnd[:fallback] ? ' (Fallback!)' : ''} #{'as empty element that will be mounted on the client side' unless support.ssr?}")
@@ -7,18 +7,31 @@ namespace :svelte_on_rails do
7
7
  desc "check ssr requirements and status"
8
8
  task :check do
9
9
 
10
+ line_width = 100
10
11
  configs = SvelteOnRails::Configuration.instance
11
12
  ppid_file = Rails.root.join("tmp", "pids", 'svelte_on_rails.ppid')
12
13
  ppid = (ppid_file.exist? ? File.read(ppid_file).chomp : nil)
13
14
  server_helpers = SvelteOnRails::SsrServerHelpers.new
14
15
  socket_path = server_helpers.socket_path(ppid: ppid)
16
+ curl_installed = system('which curl > /dev/null 2>&1')
17
+ if curl_installed
18
+ curl_cmd = "curl --unix-socket #{socket_path} http://localhost"
19
+ stdout, stderr, status = Open3.capture3(curl_cmd + '/health')
20
+ srv_details = (JSON.parse(stdout) rescue {})
21
+ end
15
22
 
16
- rails_env_warning(socket_path)
23
+ env_check = rails_env_check(socket_path)
17
24
 
18
- puts '=' * 80
19
- puts "Svelte on Rails SSR Server"
20
- puts "Rails env: #{Rails.env.upcase}"
21
- puts '=' * 80
25
+ puts
26
+ puts '=' * line_width
27
+ puts "Svelte on Rails SSR Server Status:"
28
+ puts " Rails env: #{Rails.env.upcase}"
29
+ if srv_details['uptime']
30
+ puts " Uptime: #{srv_details['uptime'].round(0)}sec"
31
+ else
32
+ puts " Status: not running"
33
+ end
34
+ puts '=' * line_width
22
35
  puts
23
36
  puts 'Node'
24
37
  puts label('Node bin') + configs.node_bin_path.to_s
@@ -29,41 +42,96 @@ namespace :svelte_on_rails do
29
42
  puts 'Rails instance'
30
43
  if !server_helpers.ssr_server_ppid_file.exist?
31
44
  puts label('Process.ppid') + "#{server_helpers.ssr_server_ppid_file} not found, rails seems not to run or the SsrServer is not initialized yet."
32
- else
45
+ elsif env_check == :clearly_correct
33
46
  puts label('Process.ppid') + ppid.to_s
34
47
  puts label('Socket') + socket_path.to_s
35
- puts 'Command for check the server instance:'
36
- puts " • curl --unix-socket #{socket_path} http://localhost"
48
+ else
49
+ puts 'Rails env could not be determinated, compared to the socket path, so, no socket path could be determined.'
37
50
  end
38
51
  puts
39
- puts '=' * 80
52
+ puts '=' * line_width
53
+ puts
40
54
  puts 'MORE DETAILS:'
41
55
  puts
42
56
  puts 'How was the node bin path determined:'
43
57
  configs.instance_variable_get(:@node_bin_path_log).each do |line|
44
58
  puts " • #{line}"
59
+ puts " • kill #{line}"
45
60
  end
46
61
  puts
62
+ puts 'Commands:'
63
+ puts " • node path/to/svelte-ssr-server.js path/to/socket.sock:"
64
+ puts " • #{server_helpers.start_node_server_command(nil)}"
65
+ if srv_details['pid']
66
+ puts " • #{curl_cmd}"
67
+ puts " • kill #{srv_details['pid']}" if srv_details['pid']
68
+ end
69
+ puts
70
+ if env_check == :clearly_correct
71
+ puts '=' * line_width
72
+ puts
73
+ puts 'NODE INSTANCE INFO:'
74
+ puts ' (output of the above mentioned curl command)'
75
+ puts
76
+ puts '-' * line_width
77
+ if curl_installed
78
+ stdout, stderr, status = Open3.capture3(curl_cmd)
79
+ if status.success?
80
+ puts stdout
81
+ else
82
+ puts "curl exited with status #{status.exitstatus}"
83
+ puts stderr unless stderr.to_s.strip.empty?
84
+ end
85
+ else
86
+ puts "curl is not installed on this machine, skipping execution."
87
+ end
88
+ puts
89
+ puts '=' * line_width
90
+ puts
91
+ end
47
92
 
48
93
  end
49
94
 
50
- def rails_env_warning(socket_path)
95
+ def rails_env_check(socket_path)
96
+
97
+ line_width = 100
98
+
51
99
  envs = guessed_rails_envs(socket_path.dirname)
100
+
52
101
  if envs == [Rails.env]
53
- # All good
102
+
103
+ :clearly_correct
104
+
105
+ elsif envs.empty?
106
+
107
+ puts
108
+ puts '*' * line_width
109
+ puts "WARNING: This Rails app seems not to run."
110
+ puts '*' * line_width
111
+ puts
112
+ :possible_correct
113
+
54
114
  elsif envs.include?(Rails.env)
55
- puts '*' * 80
115
+
116
+ puts
117
+ puts '*' * line_width
56
118
  puts "INFO: Based on the socket paths #{socket_path.dirname},"
57
119
  puts "this Rails app may run in #{envs.join(' or ')}."
58
120
  puts "You are running as #{Rails.env} (Rails.env) which may be right."
59
- puts '*' * 80
121
+ puts '*' * line_width
60
122
  puts
123
+ :possible_correct
124
+
61
125
  else
62
- puts '*' * 80
126
+
127
+ puts
128
+ puts '*' * line_width
63
129
  puts "WARNING: You are running as #{Rails.env} (Rails.env)"
64
130
  puts "But the rails app seems to run in #{envs.join(' or ')}"
65
- puts '*' * 80
131
+ puts '*' * line_width
66
132
  puts
133
+ :possible_wrong
134
+
67
135
  end
68
136
  end
69
137
 
@@ -18,28 +18,42 @@ aliases:
18
18
  #'@frontend': app/frontend/javascript
19
19
  #'@views': app/views
20
20
 
21
- use_ssr_server: true
22
- # For performance reasons, it is recommended to use it.
23
- # Find more info on the docs.
21
+ skip_ssr_header: 'X-Turbo-Request-ID'
22
+ # when ssr: :auto =>
23
+ # Skip SSR when this request header is present and non-empty (Turbo / prefetch / XHR requests)
24
+
25
+ ssr: :auto
26
+ # options: true, false, :auto
27
+ # :auto: render server side if request is initial request (works only with turbo, because it checks for the X-Turbo-Request-ID header)
28
+ # when not server-side rendered the components must be built as custom elements, see node-package @csedl/svelte-on-rails
29
+ # false disables SSR for all and overrides the ssr argument of the view helper.
30
+
31
+ ssr_server: true
32
+ # Node server on the backend for speedup server side rendering
33
+ # default: true for all environments, except test
34
+ # docs: https://svelte-on-rails.dev/configuration/svelte_ssr_server.html
35
+
36
+ ssr_server_workers: 1
37
+ # number of Node cluster workers; 1 = no cluster
38
+
39
+ ssr_fallback_renderer: false
40
+ # Node script that does not need a running node server
41
+ # default: false
42
+
43
+ ssr_error_tag: true
44
+ # Render the error tag when server side rendering fails
45
+ # default: true, except for production
24
46
 
25
47
  # redis_cache_store:
26
48
  # url: 'redis://localhost:6379/2'
27
49
  # expires_in: 90.minutes (=> default / fallback: 1 hour)
28
50
  # namespace: 'my-app-svelte-on-rails'
29
51
 
52
+
30
53
  use_caching: false
31
54
  # this is the default for the #svelte view-helper.
32
55
  # When set to true, the redis gem is required.
33
56
 
34
- ssr: :auto
35
- # options: true, false, :auto
36
- # :auto: render server side if request is initial request (works only with turbo, because it checks for the X-Turbo-Request-ID header)
37
- # when not server-side rendered the components must be built as custom elements, see node-package @csedl/svelte-on-rails
38
-
39
- skip_ssr_header: 'X-Turbo-Request-ID'
40
- # when ssr: :auto =>
41
- # Skip SSR when this request header is present and non-empty (Turbo / prefetch / XHR requests)
42
-
43
57
  debug: true
44
58
  # provides deeper logging with timestamps for performance improvements
45
59
 
@@ -81,4 +95,11 @@ test:
81
95
  watch_changes: true
82
96
  cache_expiration_hours: 15
83
97
 
84
- production:
98
+ staging:
99
+ ssr_error_tag: true
100
+ ssr_fallback_renderer: false
101
+
102
+ production:
103
+ ssr_error_tag: false
104
+ ssr_fallback_renderer: true
105
+ ssr_server_workers: 3
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: svelte-on-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 20.0.18
4
+ version: 21.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christian Sedlmair