isomorfeus-asset-manager 0.14.9 → 0.14.13
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/README.md +1 -1
- data/lib/isomorfeus/asset_manager/asset.rb +27 -107
- data/lib/isomorfeus/asset_manager/browser_asset.rb +128 -0
- data/lib/isomorfeus/asset_manager/config.rb +2 -2
- data/lib/isomorfeus/asset_manager/node_asset.rb +56 -0
- data/lib/isomorfeus/asset_manager/rack_middleware.rb +83 -71
- data/lib/isomorfeus/asset_manager/ruby_import.rb +6 -2
- data/lib/isomorfeus/asset_manager/version.rb +1 -1
- data/lib/isomorfeus/asset_manager.rb +28 -72
- data/lib/isomorfeus-asset-manager.rb +4 -0
- data/node_modules/.package-lock.json +3 -3
- data/node_modules/esbuild-wasm/esbuild.wasm +0 -0
- data/node_modules/esbuild-wasm/esm/browser.js +11 -5
- data/node_modules/esbuild-wasm/esm/browser.min.js +2 -2
- data/node_modules/esbuild-wasm/lib/browser.js +10 -5
- data/node_modules/esbuild-wasm/lib/browser.min.js +2 -2
- data/node_modules/esbuild-wasm/lib/main.js +15 -8
- data/node_modules/esbuild-wasm/package.json +1 -1
- data/node_modules/esbuild-wasm/wasm_exec.js +4 -1
- data/package.json +1 -1
- metadata +22 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6df344a7cb61a035481d5f3c40716027d0b738ba935f8777ac32e2a5a68128d
|
4
|
+
data.tar.gz: 60b9863456423a6de7dba3533c36a65f186ecfa73637747fb18d8fe369b0d078
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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](
|
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
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
attr_reader :
|
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
|
-
@
|
21
|
-
@
|
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
|
35
|
-
@
|
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
|
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
|
74
|
-
@bundled =
|
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 :
|
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.
|
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
|
29
|
-
|
30
|
-
|
31
|
-
|
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.
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
50
|
-
|
51
|
-
asset_key
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
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.
|
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.
|
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
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
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
|