isomorfeus-asset-manager 0.14.9 → 0.14.13

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72c3557faab5046cf4a3f166cde680d0e4cd00d4829d60e036f466c6f69dcd5f
4
- data.tar.gz: 42198b62586fa62d3516ccf553b79b415dd77830cadd40631a66c9c252f9f6b0
3
+ metadata.gz: e6df344a7cb61a035481d5f3c40716027d0b738ba935f8777ac32e2a5a68128d
4
+ data.tar.gz: 60b9863456423a6de7dba3533c36a65f186ecfa73637747fb18d8fe369b0d078
5
5
  SHA512:
6
- metadata.gz: b8ec3a05a2caa23313493e65b5500ec4e11203e97518531b753550e02f37c2b12117c104a4e2a4769c40696caa83064050a3b1dcf96ca92a4751b040f87ecd0c
7
- data.tar.gz: 3d78711a4350ea69d54ca3426df1886dd39c8249e7be67b396e3d253b5f3bcdd0cc39d7f1caf2fee0e499a4ff086f1e8fc730cb0ad9c7ec0b465a2d64cd8e370
6
+ metadata.gz: 9812fc459b7874bd1934f8f0a71becb77cdd716beec36ef446489c30e430d7fccde80ecb3bdb6cfe4227b612dc3cf4830f3c58d2ec98cfbbaed0b57cb883874d
7
+ data.tar.gz: c2d17965c1b479219c824ffb29116f87b9a5c8c4df7758f8f67d89e340c5cf57933fee47e2df5483c154bae92e2ebdf32a3f429ea4b3e3b6fa1c3f154f08f5e3
data/README.md CHANGED
@@ -12,4 +12,4 @@ No need to install esbuild separately, everything bundled ready to go.
12
12
  However, if within the project the 'esbuild' npm package is installed in node_modules, that version will be used instead.
13
13
 
14
14
  ### Community and Support
15
- At the [Isomorfeus Framework Project](http://isomorfeus.com)
15
+ At the [Isomorfeus Framework Project](https://isomorfeus.com)
@@ -1,28 +1,36 @@
1
1
  module Isomorfeus
2
2
  class AssetManager
3
3
  class Asset
4
- attr_reader :bundle, :bundle_size
5
- attr_reader :bundle_gz, :bundle_gz_size
6
- attr_reader :bundle_map, :bundle_map_size
7
- attr_reader :bundle_map_gz, :bundle_map_gz_size
8
- attr_reader :css, :css_size
9
- attr_reader :css_gz, :css_gz_size
10
- attr_reader :css_map, :css_map_size
11
- attr_reader :css_map_gz, :css_map_gz_size
12
- attr_reader :mtime, :ruby_imports, :target
13
- attr_reader :mutex
4
+ class << self
5
+ alias_method :_original_new, :new
6
+ def new(target = :browser)
7
+ return BrowserAsset.new if target == :browser
8
+ return NodeAsset.new if target == :node
9
+ raise "unknown target #{traget}"
10
+ end
11
+ end
12
+
13
+ attr_reader :bundle_ruby_modules, :hash, :target
14
+ attr_reader :mtime, :js_imports, :ruby_imports, :mutex
14
15
 
15
16
  def initialize(target = :browser)
16
- @mutex = Mutex.new
17
- raise "Unknown asset target!" unless %i[browser node].include?(target)
18
17
  @target = target
18
+ @mutex = Mutex.new
19
19
  @bundled = false
20
- @css_bundled = false
21
- @ruby_compiled = false
20
+ @bundle_ruby_modules = {}
21
+ @hash = { css: {}, js: {}}
22
22
  @js_imports = []
23
23
  @ruby_imports = []
24
24
  end
25
25
 
26
+ def browser?
27
+ target == :browser
28
+ end
29
+
30
+ def node?
31
+ target == :node
32
+ end
33
+
26
34
  def add_js_import(*args)
27
35
  @js_imports << Isomorfeus::AssetManager::JsImport.new(*args)
28
36
  end
@@ -31,113 +39,25 @@ module Isomorfeus
31
39
  @ruby_imports << Isomorfeus::AssetManager::RubyImport.new(*args)
32
40
  end
33
41
 
34
- def bundle=(b)
35
- @bundled = true
36
- @bundle = b
37
- @bundle_size = @bundle.size
38
- unless @target == :node
39
- @bundle_gz = Zlib::gzip(b, level: Zlib::BEST_COMPRESSION)
40
- @bundle_gz_size = @bundle_gz.size
41
- end
42
- @bundle
43
- end
44
-
45
- def bundle_map=(m)
46
- @bundled = true
47
- @bundle_map = m
48
- unless @target == :node
49
- @bundle_map_gz = Zlib::gzip(m, level: Zlib::BEST_COMPRESSION)
50
- @bundle_map_gz_size = @bundle_map_gz.size
51
- end
52
- @bundle_map
42
+ def bundle
43
+ @hash[:js][:js][:raw]
53
44
  end
54
45
 
55
46
  def bundled?
56
47
  @bundled
57
48
  end
58
49
 
59
- def css=(b)
50
+ def bundled!
60
51
  @bundled = true
61
- if b
62
- @has_css = true
63
- @css = b
64
- @css_size = @css.size
65
- unless @target == :node
66
- @css_gz = Zlib::gzip(b, level: Zlib::BEST_COMPRESSION)
67
- @css_gz_size = @css_gz.size
68
- end
69
- end
70
- @css
71
52
  end
72
53
 
73
- def css_map=(m)
74
- @bundled = true
75
- if m
76
- @has_css = true
77
- @css_map = m
78
- @css_map_size = @css_map.size
79
- unless @target == :node
80
- @css_map_gz = Zlib::gzip(m, level: Zlib::BEST_COMPRESSION)
81
- @css_map_gz_size = @css_map_gz.size
82
- end
83
- end
84
- @css_map
85
- end
86
-
87
- def has_css?
88
- @has_css
89
- end
90
-
91
- def ruby_modules
92
- @ruby_imports.map(&:module_name)
54
+ def unbundle!
55
+ @bundled = false
93
56
  end
94
57
 
95
58
  def touch
96
59
  @mtime = (Time.now.to_f * (10 ** 9)).to_i
97
60
  end
98
-
99
- def to_s
100
- js = @target == :node ? '' : "if (typeof globalThis !== 'undefined' && typeof global === 'undefined') { globalThis.global = globalThis; }\n"
101
- unless @js_imports.empty?
102
- js << "#{@js_imports.map(&:to_s).join("\n")}"
103
- end
104
- js << "\n" if !@js_imports.empty? && !@ruby_imports.empty?
105
- unless @ruby_imports.empty?
106
- if Isomorfeus.development? && @target == :browser
107
- js << <<~JAVASCRIPT
108
- // Isomorfeus Asset Manager HMR code begin
109
- let ws_protocol = (window.location.protocol == 'https:') ? 'wss:' : 'ws:';
110
- let ws_url = ws_protocol + '//' + window.location.host + "#{Isomorfeus.assets_websocket_path}";
111
- let hmr_ws = new WebSocket(ws_url);
112
- hmr_ws.onmessage = function(event) {
113
- let update = JSON.parse(event.data);
114
- if (typeof update.error !== 'undefined') { console.error(update.error); return; }
115
- if (typeof update.locale !== 'undefined') {
116
- console.log('Updating locale ', update.locale);
117
- try { Opal.Isomorfeus.I18n.Init.$reload_from_server(); }
118
- catch { console.log('Coulnt update locale ', update.locale) }
119
- return;
120
- }
121
- let start_index = 'Opal.modules[\\"'.length;
122
- let end_index = update.javascript.indexOf('"', start_index);
123
- let opal_module_name = update.javascript.substr(start_index, end_index - start_index);
124
- console.log('Updating ', opal_module_name);
125
- if (typeof Opal !== 'undefined' && typeof Opal.require_table !== "undefined" && Opal.require_table['corelib/module']) {
126
- try {
127
- eval(update.javascript);
128
- if (Opal.require_table[opal_module_name]) { Opal.load.call(Opal, opal_module_name); }
129
- else { Opal.require.call(Opal, opal_module_name); }
130
- Opal.Isomorfeus.$force_render();
131
- } catch (e) { console.error(e); return; }
132
- }
133
- }
134
- // Isomorfeus Asset Manager HMR code end
135
- JAVASCRIPT
136
- end
137
- js << "#{@ruby_imports.map(&:to_s).join("\n")}"
138
- end
139
- js
140
- end
141
61
  end
142
62
  end
143
63
  end
@@ -0,0 +1,128 @@
1
+ module Isomorfeus
2
+ class AssetManager
3
+ class BrowserAsset < Asset
4
+ def self.new
5
+ _original_new
6
+ end
7
+
8
+ def initialize(target = :browser)
9
+ super(:browser)
10
+ end
11
+
12
+ def browser?
13
+ true
14
+ end
15
+
16
+ def node?
17
+ false
18
+ end
19
+
20
+ def build_ruby_and_save(asset_key, asset_name, imports_path)
21
+ @ruby_imports.each do |ruby_import|
22
+ module_name = ruby_import.module_name
23
+ asset_dir = File.join(imports_path, asset_name)
24
+ out_file = File.join(asset_dir, "#{module_name}.rb.js")
25
+ next if Isomorfeus.production? && File.exist?(out_file)
26
+ result = Opal::Builder.build(ruby_import.resolved_path, { esm: true })
27
+ js = result.to_s
28
+ if Isomorfeus.production?
29
+ FileUtils.mkdir_p(asset_dir) unless Dir.exist?(asset_dir)
30
+ FileUtils.mkdir_p(File.join(*[asset_dir].concat(module_name.split('/')[0...-1]))) if module_name.include?('/')
31
+ File.write(out_file, js)
32
+ else
33
+ js << "\n//# sourceMappingURL=#{Isomorfeus.assets_path}/#{asset_name}/#{module_name}.rb.js.map\n"
34
+ @bundle_ruby_modules[module_name] = { js: { raw: js }, map: { raw: Oj.dump(result.source_map.as_json, mode: :strict) }}
35
+ end
36
+ end
37
+ end
38
+
39
+ def save_entry(asset_key, asset_name, imports_path)
40
+ entry = File.join(imports_path, asset_key)
41
+ File.write(entry, generate_entry(asset_name))
42
+ entry
43
+ end
44
+
45
+ def bundle_css(asset_name, output_path)
46
+ filename = File.join(output_path, asset_name + '.css')
47
+ @hash[:css][:css] = { raw: File.read(filename) } if File.exist?(filename)
48
+ end
49
+
50
+ def bundle_css_map(asset_name, output_path)
51
+ filename = File.join(output_path, asset_name + '.css.map')
52
+ @hash[:css][:map] = { raw: File.read(filename) } if File.exist?(filename)
53
+ end
54
+
55
+ def bundle_js(asset_key, asset_name, imports_path, output_path)
56
+ js = File.read(File.join(output_path, asset_key))
57
+ js << ruby_imports_to_s(asset_name, imports_path) unless Isomorfeus.production?
58
+ @hash[:js][:js] = { raw: js }
59
+ end
60
+
61
+ def bundle_js_map(asset_key, output_path)
62
+ filename = File.join(output_path, asset_key + '.map')
63
+ @hash[:js][:map] = { raw: File.read(filename) } if File.exist?(filename)
64
+ end
65
+
66
+ def ruby_imports_to_s(asset_name, out_dir)
67
+ s = @ruby_imports.size - 1
68
+ return '' if s < 0
69
+ js = "async function iam_load_ruby_modules() {\n"
70
+ @ruby_imports.each do |import|
71
+ js << import.to_dev_s(asset_name)
72
+ end
73
+ js << "}\niam_load_ruby_modules();\n"
74
+ end
75
+
76
+ def generate_entry(asset_name)
77
+ js = "if (typeof globalThis !== 'undefined' && typeof global === 'undefined') { globalThis.global = globalThis; }\n"
78
+ js << "#{@js_imports.map(&:to_s).join("\n")}"
79
+ if @ruby_imports.any?
80
+ if Isomorfeus.development?
81
+ js << <<~JAVASCRIPT
82
+ // Isomorfeus Asset Manager HMR code begin
83
+ let ws_protocol = (window.location.protocol == 'https:') ? 'wss:' : 'ws:';
84
+ let ws_url = ws_protocol + '//' + window.location.host + "#{Isomorfeus.hmr_websocket_path}";
85
+ let hmr_ws_fun = function() {
86
+ let hmr_ws = new WebSocket(ws_url);
87
+ hmr_ws.onopen = function(event) { console.log("Isomorfeus Asset Manager HMR socket connected"); }
88
+ hmr_ws.onmessage = function(event) {
89
+ let update = JSON.parse(event.data);
90
+ if (typeof update.error !== 'undefined') { console.error(update.error); return; }
91
+ if (typeof update.locale !== 'undefined') {
92
+ console.log('Isomorfeus Asset Manager updating locale ', update.locale);
93
+ try { Opal.Isomorfeus.I18n.Init.$reload_from_server(); }
94
+ catch { console.log('Isomorfeus Asset Manager could not update locale ', update.locale) }
95
+ return;
96
+ }
97
+ let start_index = 'Opal.modules[\\"'.length;
98
+ let end_index = update.javascript.indexOf('"', start_index);
99
+ let opal_module_name = update.javascript.substr(start_index, end_index - start_index);
100
+ console.log('Isomorfeus Asset Manager updating ', opal_module_name);
101
+ if (typeof Opal !== 'undefined' && typeof Opal.require_table !== "undefined" && Opal.require_table['corelib/module']) {
102
+ try {
103
+ window.eval(update.javascript);
104
+ if (Opal.require_table[opal_module_name]) { Opal.load.call(Opal, opal_module_name); }
105
+ else { Opal.require.call(Opal, opal_module_name); }
106
+ Opal.Isomorfeus.$force_render();
107
+ } catch (e) { console.error(e); return; }
108
+ }
109
+ };
110
+ hmr_ws.onclose = function(event) {
111
+ setTimeout(function() {
112
+ console.log("Isomorfeus Asset Manager reconnecting HMR socket");
113
+ hmr_ws_fun();
114
+ }, 2000);
115
+ };
116
+ }
117
+ hmr_ws_fun()
118
+ // Isomorfeus Asset Manager HMR code end
119
+ JAVASCRIPT
120
+ elsif Isomorfeus.production?
121
+ js << "#{@ruby_imports.map { |i| i.to_s(asset_name) }.join("\n")}"
122
+ end
123
+ end
124
+ js
125
+ end
126
+ end
127
+ end
128
+ end
@@ -8,7 +8,7 @@ module Isomorfeus
8
8
  attr_accessor :root
9
9
  attr_accessor :app_root
10
10
  attr_accessor :assets_path
11
- attr_accessor :assets_websocket_path
11
+ attr_accessor :hmr_websocket_path
12
12
  attr_accessor :asset_manager_tmpdir
13
13
  attr_accessor :asset_manager_hmr_channel
14
14
  attr_accessor :asset_manager_hmr_dirs
@@ -67,7 +67,7 @@ module Isomorfeus
67
67
  self.hmr_listener = nil
68
68
  self.asset_manager_hmr_channel = :isomorfeus_asset_manager_module_updates
69
69
  self.asset_manager_hmr_dirs = %w[channels components data locales operations policies]
70
- self.assets_websocket_path = '/_assets_websocket'
70
+ self.hmr_websocket_path = '/_asset_manager_hmr_websocket'
71
71
  self.assets_path = '/assets'
72
72
  self.assets = {
73
73
  'web.js' => Isomorfeus::AssetManager::Asset.new(:browser),
@@ -0,0 +1,56 @@
1
+ module Isomorfeus
2
+ class AssetManager
3
+ class NodeAsset < Asset
4
+ def self.new
5
+ _original_new
6
+ end
7
+
8
+ def initialize(target = :node)
9
+ super(:node)
10
+ end
11
+
12
+ def browser?
13
+ false
14
+ end
15
+
16
+ def node?
17
+ true
18
+ end
19
+
20
+ def bundle
21
+ @hash[:js][:js][:raw]
22
+ end
23
+
24
+ def build_ruby_and_save(asset_key, asset_name, imports_path)
25
+ @ruby_imports.each do |ruby_import|
26
+ module_name = ruby_import.module_name
27
+ asset_dir = File.join(imports_path, asset_name)
28
+ out_file = File.join(asset_dir, "#{module_name}.rb.js")
29
+ next if Isomorfeus.production? && File.exist?(out_file)
30
+ result = Opal::Builder.build(ruby_import.resolved_path, { esm: true })
31
+ FileUtils.mkdir_p(asset_dir) unless Dir.exist?(asset_dir)
32
+ FileUtils.mkdir_p(File.join(*[asset_dir].concat(module_name.split('/')[0...-1]))) if module_name.include?('/')
33
+ File.write(out_file, result.to_s)
34
+ end
35
+ nil
36
+ end
37
+
38
+ def save_entry(asset_key, asset_name, imports_path)
39
+ entry = File.join(imports_path, asset_key)
40
+ File.write(entry, generate_entry(asset_name))
41
+ entry
42
+ end
43
+
44
+ def bundle_js(asset_key, asset_name, imports_path, output_path)
45
+ js = File.read(File.join(output_path, asset_key))
46
+ @hash[:js][:js] = { raw: js }
47
+ end
48
+
49
+ def generate_entry(asset_name)
50
+ js = ''
51
+ js << "#{@js_imports.map(&:to_s).join("\n")}"
52
+ js << "#{@ruby_imports.map { |i| i.to_s(asset_name) }.join("\n")}"
53
+ end
54
+ end
55
+ end
56
+ end
@@ -4,12 +4,13 @@ module Isomorfeus
4
4
  class AssetManager
5
5
  class RackMiddleware
6
6
  WS_RESPONSE = [0, {}, []].freeze
7
+ C_ENCODINGS = %w[br gzip].freeze
8
+
7
9
  attr_reader :asset_manager
8
10
 
9
11
  def initialize(app)
10
12
  @app = app
11
13
  @asset_manager = Isomorfeus::AssetManager.new
12
- @compressible_types = %w[application/javascript text/javascript text/css]
13
14
  if Isomorfeus.assets_path.end_with?('/')
14
15
  @assets_path = Isomorfeus.assets_path
15
16
  @assets_path_size = @assets_path.size
@@ -25,88 +26,81 @@ module Isomorfeus
25
26
  path_info = env['PATH_INFO']
26
27
  if path_info.start_with?(@assets_path)
27
28
 
28
- if path_info.end_with?('.js')
29
- # get js
30
- asset_key = path_info[@assets_path_size..-1]
31
- if Isomorfeus.assets.key?(asset_key)
29
+ if !Isomorfeus.production?
30
+ if path_info.end_with?('.rb.js')
31
+ asset_key_module_name = path_info[@assets_path_size..-7]
32
+ asset_key, module_name = asset_key_module_name.split('/')
33
+ asset_key += '.js'
34
+ if Isomorfeus.assets.key?(asset_key)
35
+ asset = Isomorfeus.assets[asset_key]
36
+ if asset && asset.browser?
37
+ if asset.bundle_ruby_modules.key?(module_name)
38
+ headers = { Rack::CONTENT_TYPE => 'application/javascript' }
39
+ asset_manager.transition(asset_key, asset)
40
+ return [200, headers, get_content(env, headers, asset, asset_key, asset.bundle_ruby_modules[module_name][:js])]
41
+ end
42
+ end
43
+ end
44
+
45
+ elsif path_info.end_with?('.rb.js.map')
46
+ asset_key_module_name = path_info[@assets_path_size..-11]
47
+ asset_key, module_name = asset_key_module_name.split('/')
48
+ asset_key += '.js'
32
49
  asset = Isomorfeus.assets[asset_key]
33
- if asset && asset.target != :node
34
- asset_manager.transition(asset_key, asset)
35
- headers = {}
36
- headers['Last-Modified'] = asset.mtime
37
- headers[Rack::CONTENT_TYPE] = 'application/javascript'
38
- if should_gzip?(env)
39
- headers['Content-Encoding'] = "gzip"
40
- headers[Rack::CONTENT_LENGTH] = asset.bundle_gz_size
41
- return [200, headers, asset.bundle_gz]
42
- else
43
- headers[Rack::CONTENT_LENGTH] = asset.bundle_size
44
- return [200, headers, asset.bundle]
50
+ if asset && asset.browser?
51
+ if asset.bundle_ruby_modules.key?(module_name)
52
+ headers = { Rack::CONTENT_TYPE => 'application/json' }
53
+ asset_manager.transition(asset_key, asset)
54
+ return [200, headers, get_content(env, headers, asset, asset_key, asset.bundle_ruby_modules[module_name][:map])]
45
55
  end
46
56
  end
57
+
58
+ elsif path_info.end_with?('.js.map')
59
+ asset_key = path_info[@assets_path_size..-5]
60
+ asset = Isomorfeus.assets[asset_key]
61
+ if asset && asset.browser?
62
+ headers = { Rack::CONTENT_TYPE => 'application/json' }
63
+ asset_manager.transition(asset_key, asset)
64
+ return [200, headers, get_content(env, headers, asset, asset_key, asset.hash[:js][:map])]
65
+ end
66
+
67
+ elsif path_info.end_with?('.css.map')
68
+ # get css source map
69
+ asset_key = path_info[@assets_path_size..-9] + '.js'
70
+ asset = Isomorfeus.assets[asset_key]
71
+ if asset && asset.browser?
72
+ headers = { Rack::CONTENT_TYPE => 'application/json' }
73
+ asset_manager.transition(asset_key, asset)
74
+ content = get_content(env, headers, asset, asset_key, asset.hash[:css][:map])
75
+ return [200, headers, content]
76
+ end
47
77
  end
78
+ end
48
79
 
49
- elsif path_info.end_with?('.js.map')
50
- # get js source map
51
- asset_key = path_info[@assets_path_size..-5]
52
- asset = Isomorfeus.assets[asset_key]
53
- if asset && asset.target != :node
54
- asset_manager.transition(asset_key, asset) unless asset.bundled?
55
- headers = {}
56
- headers['Last-Modified'] = asset.mtime
57
- headers[Rack::CONTENT_TYPE] = 'application/json'
58
- if should_gzip?(env)
59
- headers['Content-Encoding'] = "gzip"
60
- headers[Rack::CONTENT_LENGTH] = asset.bundle_map_gz_size
61
- return [200, headers, asset.bundle_map_gz]
62
- else
63
- headers[Rack::CONTENT_LENGTH] = asset.bundle_map_size
64
- return [200, headers, asset.bundle_map]
80
+ if path_info.end_with?('.js')
81
+ asset_key = path_info[@assets_path_size..-1]
82
+ if Isomorfeus.assets.key?(asset_key)
83
+ asset = Isomorfeus.assets[asset_key]
84
+ if asset && asset.browser?
85
+ headers = { Rack::CONTENT_TYPE => 'application/javascript' }
86
+ asset_manager.transition(asset_key, asset)
87
+ return [200, headers, get_content(env, headers, asset, asset_key, asset.hash[:js][:js])]
65
88
  end
66
89
  end
67
90
 
68
91
  elsif path_info.end_with?('.css')
69
- # get css
70
92
  asset_key = path_info[@assets_path_size..-5] + '.js'
71
93
  asset = Isomorfeus.assets[asset_key]
72
- if asset && asset.target != :node
94
+ if asset && asset.browser?
95
+ headers = { Rack::CONTENT_TYPE => 'text/css' }
73
96
  asset_manager.transition(asset_key, asset)
74
- headers = {}
75
- headers['Last-Modified'] = asset.mtime
76
- headers[Rack::CONTENT_TYPE] = 'text/css'
77
- if should_gzip?(env)
78
- headers['Content-Encoding'] = "gzip"
79
- headers[Rack::CONTENT_LENGTH] = asset.css_gz_size
80
- return [200, headers, asset.css_gz]
81
- else
82
- headers[Rack::CONTENT_LENGTH] = asset.css_size
83
- return [200, headers, asset.css]
84
- end
85
- end
86
-
87
- elsif path_info.end_with?('.css.map')
88
- # get css source map
89
- asset_key = path_info[@assets_path_size..-9] + '.js'
90
- asset = Isomorfeus.assets[asset_key]
91
- if asset && asset.target != :node
92
- asset_manager.transition(asset_key, asset) unless asset.bundled?
93
- headers = {}
94
- headers['Last-Modified'] = asset.mtime
95
- headers[Rack::CONTENT_TYPE] = 'application/json'
96
- if should_gzip?(env)
97
- headers['Content-Encoding'] = "gzip"
98
- headers[Rack::CONTENT_LENGTH] = asset.css_map_gz_size
99
- return [200, headers, asset.css_map_gz]
100
- else
101
- headers[Rack::CONTENT_LENGTH] = asset.css_map_size
102
- return [200, headers, asset.css_map]
103
- end
97
+ return [200, headers, get_content(env, headers, asset, asset_key, asset.hash[:css][:css])]
104
98
  end
105
99
  end
106
100
 
107
101
  return [404, {}, 'not found']
108
102
  # hot reloading subscription
109
- elsif Isomorfeus.development? && path_info == Isomorfeus.assets_websocket_path
103
+ elsif Isomorfeus.development? && path_info == Isomorfeus.hmr_websocket_path
110
104
  if env['rack.upgrade?'] == :websocket
111
105
  env['rack.upgrade'] = Isomorfeus::AssetManager::ServerSocketProcessor.new
112
106
  end
@@ -119,11 +113,29 @@ module Isomorfeus
119
113
  @app.call(env)
120
114
  end
121
115
 
122
- def should_gzip?(env)
123
- return true if env.key?('HTTP_ACCEPT_ENCODING') && env['HTTP_ACCEPT_ENCODING'].match?(/\bgzip\b/)
124
- return false if /\bno-transform\b/.match?(env[Rack::CACHE_CONTROL].to_s) || env['Content-Encoding']&.!~(/\bidentity\b/)
125
- return false if @compressible_types && !(env.key?(Rack::CONTENT_TYPE) && @compressible_types.include?(env[Rack::CONTENT_TYPE][/[^;]*/]))
126
- true
116
+ def get_content(env, headers, asset, asset_key, content_hash)
117
+ request = Rack::Request.new(env)
118
+ best_encoding = Rack::Utils.select_best_encoding(C_ENCODINGS, request.accept_encoding)
119
+ content = ''
120
+ case best_encoding
121
+ when 'gzip'
122
+ headers['Content-Encoding'] = "gzip"
123
+ unless content_hash.key?(:gzip)
124
+ asset.mutex.synchronize { content_hash[:gzip] = Zlib::gzip(content_hash[:raw], level: Zlib::BEST_COMPRESSION) unless content_hash.key?(:gzip) }
125
+ end
126
+ content = content_hash[:gzip]
127
+ when 'br'
128
+ headers['Content-Encoding'] = "br"
129
+ unless content_hash.key?(:br)
130
+ asset.mutex.synchronize { content_hash[:br] = Brotli.deflate(content_hash[:raw], quality: Isomorfeus.production? ? 9 : 5) unless content_hash.key?(:br) }
131
+ end
132
+ content = content_hash[:br]
133
+ else
134
+ content = content_hash[:raw]
135
+ end
136
+ headers[Rack::CONTENT_LENGTH] = content.size
137
+ headers['Last-Modified'] = asset.mtime
138
+ content
127
139
  end
128
140
  end
129
141
  end
@@ -13,8 +13,12 @@ module Isomorfeus
13
13
  @resolved_path ||= resolve_path
14
14
  end
15
15
 
16
- def to_s
17
- "import(\"./#{@module_name}.js\");\n"
16
+ def to_s(asset_name)
17
+ "import(\"./#{asset_name}/#{@module_name}.rb.js\");\n"
18
+ end
19
+
20
+ def to_dev_s(asset_name)
21
+ "await import(\"#{Isomorfeus.assets_path}/#{asset_name}/#{@module_name}.rb.js\");\n"
18
22
  end
19
23
 
20
24
  private
@@ -1,5 +1,5 @@
1
1
  module Isomorfeus
2
2
  class AssetManager
3
- VERSION = '0.14.9'
3
+ VERSION = '0.14.13'
4
4
  end
5
5
  end