isomorfeus-asset-manager 0.14.11 → 0.14.15

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: 78b774bc55cc59e8fee7021c0cad65221b01885e932f7881cf6f006e45898400
4
- data.tar.gz: 76c7b73948ed055aeeca30847e307ef1e7ef7174075463abbfff04555e032df3
3
+ metadata.gz: 2d12a6934f43c1c263059200fe3fae784c11235faeee871bd439e71ec4bd4e40
4
+ data.tar.gz: e952047d1849071d3e46cb8f2a7b49039f8c60099d4e7f7877301ff9e3d2223a
5
5
  SHA512:
6
- metadata.gz: 9e05e0fdb8f88f717638ba1aece5332d737e7e7e16f0262519386eebb4e92b21af5e31176e76dabed2d19afed09a3b8652922c0365c49625cac3e4827e72f722
7
- data.tar.gz: 8a67ce45a8dad7badc69a5e4cff9d617ff0f5bd9e9316d369fc335e190793110696f684ac2289dd31874eeaba25d06e63dcd9f1d543870b7197d61168d813b96
6
+ metadata.gz: cc5328b6425a14068d993b276c67752e9a4658e37f036b7acc941022ea6be7136ed3c0a0f449e15af417c9c19810f60300a6c44b69fba458909e448d32aec605
7
+ data.tar.gz: e68a2ad8c0b69756b37f656f39befc1b8acee6ac9d792a583c8923adfbdf77b510f39b5bf188372f75c850d51569a2c64cc71ff958448a26917ab5d4c76a9f8b
data/README.md CHANGED
@@ -6,10 +6,14 @@
6
6
 
7
7
  Convenient and well performing on demand asset bundling for the isomorfeus framework project, internally using esbuild (esbuild-wasm).
8
8
 
9
- Version follows esbuild version: 0.13.x comes with esbuild 0.13.y.
9
+ Version follows esbuild version: 0.14.x comes with esbuild 0.14.y.
10
10
 
11
11
  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
15
  At the [Isomorfeus Framework Project](https://isomorfeus.com)
16
+
17
+ ### Targets
18
+ By default bundles for browsers using the 'es6' target of esbuild.
19
+ By default bundles for node using the 'node16' target of esbuild.
@@ -1,180 +1,63 @@
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 :bundle_ruby_modules
9
- attr_reader :css, :css_size
10
- attr_reader :css_gz, :css_gz_size
11
- attr_reader :css_map, :css_map_size
12
- attr_reader :css_map_gz, :css_map_gz_size
13
- attr_reader :mtime, :ruby_imports, :target
14
- 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
15
15
 
16
16
  def initialize(target = :browser)
17
- @mutex = Mutex.new
18
- raise "Unknown asset target!" unless %i[browser node].include?(target)
19
17
  @target = target
18
+ @mutex = Mutex.new
20
19
  @bundled = false
21
- @css_bundled = false
22
- @ruby_compiled = false
20
+ @bundle_ruby_modules = {}
21
+ @hash = { css: {}, js: {}}
23
22
  @js_imports = []
24
23
  @ruby_imports = []
25
24
  end
26
25
 
27
- def add_js_import(*args)
28
- @js_imports << Isomorfeus::AssetManager::JsImport.new(*args)
26
+ def browser?
27
+ target == :browser
29
28
  end
30
29
 
31
- def add_ruby_import(*args)
32
- @ruby_imports << Isomorfeus::AssetManager::RubyImport.new(*args)
30
+ def node?
31
+ target == :node
33
32
  end
34
33
 
35
- def bundle=(b)
36
- @bundled = true
37
- @bundle = b
38
- @bundle_size = @bundle.size
39
- unless @target == :node
40
- @bundle_gz = Zlib::gzip(b, level: Zlib::BEST_COMPRESSION)
41
- @bundle_gz_size = @bundle_gz.size
42
- end
43
- @bundle
34
+ def add_js_import(*args)
35
+ @js_imports << Isomorfeus::AssetManager::JsImport.new(*args)
44
36
  end
45
37
 
46
- def bundle_map=(m)
47
- @bundled = true
48
- @bundle_map = m
49
- unless @target == :node
50
- @bundle_map_gz = Zlib::gzip(m, level: Zlib::BEST_COMPRESSION)
51
- @bundle_map_gz_size = @bundle_map_gz.size
52
- end
53
- @bundle_map
38
+ def add_ruby_import(*args)
39
+ @ruby_imports << Isomorfeus::AssetManager::RubyImport.new(*args)
54
40
  end
55
41
 
56
- def bundle_ruby_modules=(m)
57
- @bundled = true
58
- @bundle_ruby_modules = m
59
- if !Isomorfeus.production? && @target != :node
60
- @bundle_ruby_modules.each do |key, mod_hash|
61
- mod_hash[:js_size] = mod_hash[:js].size
62
- mod_hash[:js_gz] = Zlib::gzip(mod_hash[:js], level: Zlib::BEST_COMPRESSION)
63
- mod_hash[:js_gz_size] = mod_hash[:js_gz].size
64
- mod_hash[:map_size] = mod_hash[:map].size
65
- mod_hash[:map_gz] = Zlib::gzip(mod_hash[:map], level: Zlib::BEST_COMPRESSION)
66
- mod_hash[:map_gz_size] = mod_hash[:map_gz].size
67
- end
68
- end
69
- @bundle_ruby_modules
42
+ def bundle
43
+ @hash[:js][:js][:raw]
70
44
  end
71
45
 
72
46
  def bundled?
73
47
  @bundled
74
48
  end
75
49
 
76
- def css=(b)
50
+ def bundled!
77
51
  @bundled = true
78
- if b
79
- @has_css = true
80
- @css = b
81
- @css_size = @css.size
82
- unless @target == :node
83
- @css_gz = Zlib::gzip(b, level: Zlib::BEST_COMPRESSION)
84
- @css_gz_size = @css_gz.size
85
- end
86
- end
87
- @css
88
- end
89
-
90
- def css_map=(m)
91
- @bundled = true
92
- if m
93
- @has_css = true
94
- @css_map = m
95
- @css_map_size = @css_map.size
96
- unless @target == :node
97
- @css_map_gz = Zlib::gzip(m, level: Zlib::BEST_COMPRESSION)
98
- @css_map_gz_size = @css_map_gz.size
99
- end
100
- end
101
- @css_map
102
- end
103
-
104
- def has_css?
105
- @has_css
106
52
  end
107
53
 
108
- def ruby_modules
109
- @ruby_imports.map(&:module_name)
110
- end
111
-
112
- def ruby_imports_to_s(asset_name)
113
- s = @ruby_imports.size - 1
114
- return '' if s < 0
115
- js = "async function iam_load_ruby_modules() {\n"
116
- @ruby_imports.each do |import|
117
- js << ' await ' << import.to_dev_s(asset_name)
118
- end
119
- js << "}\niam_load_ruby_modules();\n"
54
+ def unbundle!
55
+ @bundled = false
120
56
  end
121
57
 
122
58
  def touch
123
59
  @mtime = (Time.now.to_f * (10 ** 9)).to_i
124
60
  end
125
-
126
- def to_s
127
- js = @target == :node ? '' : "if (typeof globalThis !== 'undefined' && typeof global === 'undefined') { globalThis.global = globalThis; }\n"
128
- unless @js_imports.empty?
129
- js << "#{@js_imports.map(&:to_s).join("\n")}"
130
- end
131
- js << "\n" if !@js_imports.empty? && !@ruby_imports.empty?
132
- unless @ruby_imports.empty?
133
- if Isomorfeus.development? && @target == :browser
134
- js << <<~JAVASCRIPT
135
- // Isomorfeus Asset Manager HMR code begin
136
- let ws_protocol = (window.location.protocol == 'https:') ? 'wss:' : 'ws:';
137
- let ws_url = ws_protocol + '//' + window.location.host + "#{Isomorfeus.assets_websocket_path}";
138
- let hmr_ws_fun = function() {
139
- let hmr_ws = new WebSocket(ws_url);
140
- hmr_ws.onopen = function(event) { console.log("Isomorfeus Asset Manager HMR socket connected"); }
141
- hmr_ws.onmessage = function(event) {
142
- let update = JSON.parse(event.data);
143
- if (typeof update.error !== 'undefined') { console.error(update.error); return; }
144
- if (typeof update.locale !== 'undefined') {
145
- console.log('Isomorfeus Asset Manager updating locale ', update.locale);
146
- try { Opal.Isomorfeus.I18n.Init.$reload_from_server(); }
147
- catch { console.log('Isomorfeus Asset Manager could not update locale ', update.locale) }
148
- return;
149
- }
150
- let start_index = 'Opal.modules[\\"'.length;
151
- let end_index = update.javascript.indexOf('"', start_index);
152
- let opal_module_name = update.javascript.substr(start_index, end_index - start_index);
153
- console.log('Isomorfeus Asset Manager updating ', opal_module_name);
154
- if (typeof Opal !== 'undefined' && typeof Opal.require_table !== "undefined" && Opal.require_table['corelib/module']) {
155
- try {
156
- eval(update.javascript);
157
- if (Opal.require_table[opal_module_name]) { Opal.load.call(Opal, opal_module_name); }
158
- else { Opal.require.call(Opal, opal_module_name); }
159
- Opal.Isomorfeus.$force_render();
160
- } catch (e) { console.error(e); return; }
161
- }
162
- };
163
- hmr_ws.onclose = function(event) {
164
- setTimeout(function() {
165
- console.log("Isomorfeus Asset Manager reconnecting HMR socket");
166
- hmr_ws_fun();
167
- }, 2000);
168
- };
169
- }
170
- hmr_ws_fun()
171
- // Isomorfeus Asset Manager HMR code end
172
- JAVASCRIPT
173
- end
174
- js << "#{@ruby_imports.map(&:to_s).join("\n")}" if Isomorfeus.production? || target == :node
175
- end
176
- js
177
- end
178
61
  end
179
62
  end
180
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 = '/_asset_manager_hmr_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
@@ -32,20 +33,11 @@ module Isomorfeus
32
33
  asset_key += '.js'
33
34
  if Isomorfeus.assets.key?(asset_key)
34
35
  asset = Isomorfeus.assets[asset_key]
35
- if asset && asset.target != :node
36
- asset_manager.transition(asset_key, asset)
36
+ if asset && asset.browser?
37
37
  if asset.bundle_ruby_modules.key?(module_name)
38
- headers = {}
39
- headers['Last-Modified'] = asset.mtime
40
- headers[Rack::CONTENT_TYPE] = 'application/javascript'
41
- if should_gzip?(env)
42
- headers['Content-Encoding'] = "gzip"
43
- headers[Rack::CONTENT_LENGTH] = asset.bundle_ruby_modules[module_name][:js_gz_size]
44
- return [200, headers, asset.bundle_ruby_modules[module_name][:js_gz]]
45
- else
46
- headers[Rack::CONTENT_LENGTH] = asset.bundle_ruby_modules[module_name][:js_size]
47
- return [200, headers, asset.bundle_ruby_modules[module_name][:js]]
48
- end
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])]
49
41
  end
50
42
  end
51
43
  end
@@ -55,58 +47,32 @@ module Isomorfeus
55
47
  asset_key, module_name = asset_key_module_name.split('/')
56
48
  asset_key += '.js'
57
49
  asset = Isomorfeus.assets[asset_key]
58
- if asset && asset.target != :node
59
- asset_manager.transition(asset_key, asset) unless asset.bundled?
50
+ if asset && asset.browser?
60
51
  if asset.bundle_ruby_modules.key?(module_name)
61
- headers = {}
62
- headers['Last-Modified'] = asset.mtime
63
- headers[Rack::CONTENT_TYPE] = 'application/json'
64
- if should_gzip?(env)
65
- headers['Content-Encoding'] = "gzip"
66
- headers[Rack::CONTENT_LENGTH] = asset.bundle_ruby_modules[module_name][:map_gz_size]
67
- return [200, headers, asset.bundle_ruby_modules[module_name][:map_gz]]
68
- else
69
- headers[Rack::CONTENT_LENGTH] = asset.bundle_ruby_modules[module_name][:map_size]
70
- return [200, headers, asset.bundle_ruby_modules[module_name][:map]]
71
- end
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])]
72
55
  end
73
56
  end
74
57
 
75
58
  elsif path_info.end_with?('.js.map')
76
59
  asset_key = path_info[@assets_path_size..-5]
77
60
  asset = Isomorfeus.assets[asset_key]
78
- if asset && asset.target != :node
79
- asset_manager.transition(asset_key, asset) unless asset.bundled?
80
- headers = {}
81
- headers['Last-Modified'] = asset.mtime
82
- headers[Rack::CONTENT_TYPE] = 'application/json'
83
- if should_gzip?(env)
84
- headers['Content-Encoding'] = "gzip"
85
- headers[Rack::CONTENT_LENGTH] = asset.bundle_map_gz_size
86
- return [200, headers, asset.bundle_map_gz]
87
- else
88
- headers[Rack::CONTENT_LENGTH] = asset.bundle_map_size
89
- return [200, headers, asset.bundle_map]
90
- end
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])]
91
65
  end
92
66
 
93
67
  elsif path_info.end_with?('.css.map')
94
68
  # get css source map
95
69
  asset_key = path_info[@assets_path_size..-9] + '.js'
96
70
  asset = Isomorfeus.assets[asset_key]
97
- if asset && asset.target != :node
98
- asset_manager.transition(asset_key, asset) unless asset.bundled?
99
- headers = {}
100
- headers['Last-Modified'] = asset.mtime
101
- headers[Rack::CONTENT_TYPE] = 'application/json'
102
- if should_gzip?(env)
103
- headers['Content-Encoding'] = "gzip"
104
- headers[Rack::CONTENT_LENGTH] = asset.css_map_gz_size
105
- return [200, headers, asset.css_map_gz]
106
- else
107
- headers[Rack::CONTENT_LENGTH] = asset.css_map_size
108
- return [200, headers, asset.css_map]
109
- end
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]
110
76
  end
111
77
  end
112
78
  end
@@ -115,45 +81,26 @@ module Isomorfeus
115
81
  asset_key = path_info[@assets_path_size..-1]
116
82
  if Isomorfeus.assets.key?(asset_key)
117
83
  asset = Isomorfeus.assets[asset_key]
118
- if asset && asset.target != :node
84
+ if asset && asset.browser?
85
+ headers = { Rack::CONTENT_TYPE => 'application/javascript' }
119
86
  asset_manager.transition(asset_key, asset)
120
- headers = {}
121
- headers['Last-Modified'] = asset.mtime
122
- headers[Rack::CONTENT_TYPE] = 'application/javascript'
123
- if should_gzip?(env)
124
- headers['Content-Encoding'] = "gzip"
125
- headers[Rack::CONTENT_LENGTH] = asset.bundle_gz_size
126
- return [200, headers, asset.bundle_gz]
127
- else
128
- headers[Rack::CONTENT_LENGTH] = asset.bundle_size
129
- return [200, headers, asset.bundle]
130
- end
87
+ return [200, headers, get_content(env, headers, asset, asset_key, asset.hash[:js][:js])]
131
88
  end
132
89
  end
133
90
 
134
91
  elsif path_info.end_with?('.css')
135
- # get css
136
92
  asset_key = path_info[@assets_path_size..-5] + '.js'
137
93
  asset = Isomorfeus.assets[asset_key]
138
- if asset && asset.target != :node
94
+ if asset && asset.browser?
95
+ headers = { Rack::CONTENT_TYPE => 'text/css' }
139
96
  asset_manager.transition(asset_key, asset)
140
- headers = {}
141
- headers['Last-Modified'] = asset.mtime
142
- headers[Rack::CONTENT_TYPE] = 'text/css'
143
- if should_gzip?(env)
144
- headers['Content-Encoding'] = "gzip"
145
- headers[Rack::CONTENT_LENGTH] = asset.css_gz_size
146
- return [200, headers, asset.css_gz]
147
- else
148
- headers[Rack::CONTENT_LENGTH] = asset.css_size
149
- return [200, headers, asset.css]
150
- end
97
+ return [200, headers, get_content(env, headers, asset, asset_key, asset.hash[:css][:css])]
151
98
  end
152
99
  end
153
100
 
154
101
  return [404, {}, 'not found']
155
102
  # hot reloading subscription
156
- elsif Isomorfeus.development? && path_info == Isomorfeus.assets_websocket_path
103
+ elsif Isomorfeus.development? && path_info == Isomorfeus.hmr_websocket_path
157
104
  if env['rack.upgrade?'] == :websocket
158
105
  env['rack.upgrade'] = Isomorfeus::AssetManager::ServerSocketProcessor.new
159
106
  end
@@ -166,11 +113,29 @@ module Isomorfeus
166
113
  @app.call(env)
167
114
  end
168
115
 
169
- def should_gzip?(env)
170
- return true if env.key?('HTTP_ACCEPT_ENCODING') && env['HTTP_ACCEPT_ENCODING'].match?(/\bgzip\b/)
171
- return false if /\bno-transform\b/.match?(env[Rack::CACHE_CONTROL].to_s) || env['Content-Encoding']&.!~(/\bidentity\b/)
172
- return false if @compressible_types && !(env.key?(Rack::CONTENT_TYPE) && @compressible_types.include?(env[Rack::CONTENT_TYPE][/[^;]*/]))
173
- 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
174
139
  end
175
140
  end
176
141
  end
@@ -13,12 +13,12 @@ module Isomorfeus
13
13
  @resolved_path ||= resolve_path
14
14
  end
15
15
 
16
- def to_s
17
- "import(\"./#{@module_name}.rb.js\");\n"
16
+ def to_s(asset_name)
17
+ "import(\"./#{asset_name}/#{@module_name}.rb.js\");\n"
18
18
  end
19
19
 
20
20
  def to_dev_s(asset_name)
21
- "import(\"#{Isomorfeus.assets_path}/#{asset_name}/#{@module_name}.rb.js\");\n"
21
+ "await import(\"#{Isomorfeus.assets_path}/#{asset_name}/#{@module_name}.rb.js\");\n"
22
22
  end
23
23
 
24
24
  private
@@ -1,5 +1,5 @@
1
1
  module Isomorfeus
2
2
  class AssetManager
3
- VERSION = '0.14.11'
3
+ VERSION = '0.14.15'
4
4
  end
5
5
  end