proscenium 0.2.0-x86_64-darwin → 0.3.0-x86_64-darwin
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 +29 -4
- data/bin/esbuild +0 -0
- data/lib/proscenium/compilers/esbuild/resolve_plugin.js +6 -0
- data/lib/proscenium/compilers/esbuild.bench.js +3 -2
- data/lib/proscenium/compilers/esbuild.js +8 -5
- data/lib/proscenium/middleware/base.rb +2 -2
- data/lib/proscenium/middleware/esbuild.rb +11 -6
- data/lib/proscenium/phlex/component.rb +9 -0
- data/lib/proscenium/phlex/react_component.rb +25 -0
- data/lib/proscenium/phlex.rb +24 -0
- data/lib/proscenium/railtie.rb +1 -0
- data/lib/proscenium/runtime/auto_reload.js +21 -3
- data/lib/proscenium/version.rb +1 -1
- data/{app/components → lib/proscenium/view_component}/react_component.rb +2 -2
- data/lib/proscenium/view_component.rb +5 -2
- metadata +19 -4
- data/app/components/application_component.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 41451bb7fb99e0c3a26cc8e9e76e9db9da134f027c6178b504eb6241066e4617
|
4
|
+
data.tar.gz: 7ed47753820edebfc0f38a95030af31d02ce5b8290cbf5e48febe289a5db71f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc0b1bda992c1b2e0e740d7089e0c229bccf65c34b8254a8603cf040337d4ce1353856397c9fef2487fbed7daee5b08d459bed835d20fdc7f469dc9d026e7209
|
7
|
+
data.tar.gz: 14024fd83e150ddcd6352a607c7f8696de46595d4db00a5a27928cc2cd4c0a2ce16804fb2ea0e06ada793c3fa42ff7771def88becd9777d2d8a00df76a44f6c3
|
data/README.md
CHANGED
@@ -110,6 +110,10 @@ resulting in conflicts. For example, esm.sh also supports a `?bundle` param, bun
|
|
110
110
|
dependencies into a single file. Instead, you should install the module locally using your favourite
|
111
111
|
package manager.
|
112
112
|
|
113
|
+
Note that `?bundle` will only bundle that exact path. It will not bundle any descendant imports. You
|
114
|
+
can bundle all imports within a file by using the `?bundle-all` query string. Use this with caution,
|
115
|
+
as you could end up swallowing everything, resulting in a very large file.
|
116
|
+
|
113
117
|
## Import Map
|
114
118
|
|
115
119
|
Import map for both JS and CSS is supported out of the box, and works with no regard to the browser
|
@@ -246,6 +250,31 @@ p {
|
|
246
250
|
}
|
247
251
|
```
|
248
252
|
|
253
|
+
## Cache Busting
|
254
|
+
|
255
|
+
By default, all assets are not cached by the browser. But if in production, you populate the
|
256
|
+
`REVISION` env variable, all CSS and JS URL's will be appended with its value as a query string, and
|
257
|
+
the `Cache-Control` response header will be set to `public` and a max-age of 30 days.
|
258
|
+
|
259
|
+
For example, if you set `REVISION=v1`, URL's will be appended with `?v1`: `/my/imported/file.js?v1`.
|
260
|
+
|
261
|
+
It is assumed that the `REVISION` env var will be unique between deploys. If it isn't, then assets
|
262
|
+
will continue to be cached as the same version between deploys. I recommend you assign a version
|
263
|
+
number or to use the Git commit hash of the deploy. Just make sure it is unique for each deploy.
|
264
|
+
|
265
|
+
You can set the `cache_query_string` config option directly to define any query string you wish:
|
266
|
+
|
267
|
+
```ruby
|
268
|
+
Rails.application.config.proscenium.cache_query_string = 'my-cache-busting-version-string'
|
269
|
+
```
|
270
|
+
|
271
|
+
The cache is set with a `max-age` of 30 days. You can customise this with the `cache_max_age` config
|
272
|
+
option:
|
273
|
+
|
274
|
+
```ruby
|
275
|
+
Rails.application.config.proscenium.cache_max_age = 12.months.to_i
|
276
|
+
```
|
277
|
+
|
249
278
|
## How It Works
|
250
279
|
|
251
280
|
Proscenium provides a Rails middleware that proxies requests for your frontend code. By default, it will simply search for a file of the same name in your Rails root. For example, a request for '/app/views/layouts/application.js' or '/lib/hooks.js' will return that exact file relative to your Rails root.
|
@@ -258,10 +287,6 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
258
287
|
|
259
288
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
260
289
|
|
261
|
-
### Compile the compilers
|
262
|
-
|
263
|
-
`deno compile --no-config -o bin/compilers/esbuild --import-map import_map.json -A lib/proscenium/compilers/esbuild.js`
|
264
|
-
|
265
290
|
## Contributing
|
266
291
|
|
267
292
|
Bug reports and pull requests are welcome on GitHub at https://github.com/joelmoss/proscenium. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/joelmoss/proscenium/blob/master/CODE_OF_CONDUCT.md).
|
data/bin/esbuild
CHANGED
Binary file
|
@@ -24,6 +24,8 @@ export default setup('resolve', (build, options) => {
|
|
24
24
|
args.path = path
|
25
25
|
args.suffix = `?${query}`
|
26
26
|
args.queryParams = new URLSearchParams(query)
|
27
|
+
} else if (options.cacheQueryString && options.cacheQueryString !== '') {
|
28
|
+
args.suffix = `?${options.cacheQueryString}`
|
27
29
|
}
|
28
30
|
|
29
31
|
// Mark remote modules as external.
|
@@ -133,6 +135,10 @@ export default setup('resolve', (build, options) => {
|
|
133
135
|
result.external = true
|
134
136
|
}
|
135
137
|
|
138
|
+
if (result.suffix && result.suffix !== '') {
|
139
|
+
result.path = `${result.path}${result.suffix}`
|
140
|
+
}
|
141
|
+
|
136
142
|
return result
|
137
143
|
}
|
138
144
|
})
|
@@ -3,11 +3,12 @@ import { join } from 'std/path/mod.ts'
|
|
3
3
|
import compile from './esbuild.js'
|
4
4
|
|
5
5
|
const root = join(Deno.cwd(), 'test', 'internal')
|
6
|
+
const lightningcssBin = join(Deno.cwd(), 'bin', 'lightningcss')
|
6
7
|
|
7
8
|
Deno.bench('esbuild js', async () => {
|
8
|
-
await compile(['lib/foo.js'], { root })
|
9
|
+
await compile(['lib/foo.js'], { root, lightningcssBin })
|
9
10
|
})
|
10
11
|
|
11
12
|
Deno.bench('esbuild css', async () => {
|
12
|
-
await compile(['lib/foo.css'], { root })
|
13
|
+
await compile(['lib/foo.css'], { root, lightningcssBin })
|
13
14
|
})
|
@@ -26,15 +26,17 @@ import throwCompileError from './esbuild/compile_error.js'
|
|
26
26
|
* <PATHS_ARG>... One or more file paths or globs to compile.
|
27
27
|
*
|
28
28
|
* OPTIONS:
|
29
|
-
* --root
|
29
|
+
* --root <PATH>
|
30
30
|
* Relative or absolute path to the root or current working directory when compilation will
|
31
31
|
* take place.
|
32
|
-
* --import-map
|
32
|
+
* --import-map <PATH>
|
33
33
|
* Path to an import map, relative to the <root>.
|
34
|
-
* --lightningcss-bin
|
34
|
+
* --lightningcss-bin <PATH>
|
35
35
|
* Path to the lightningcss CLI binary.
|
36
36
|
* --write
|
37
37
|
* Write output to the filesystem according to esbuild logic.
|
38
|
+
* --cache-query-string <STRING>
|
39
|
+
* Query string to append to all imports as a cache buster. Example: `v1`.
|
38
40
|
* --debug
|
39
41
|
* Debug output,
|
40
42
|
*/
|
@@ -42,10 +44,11 @@ if (import.meta.main) {
|
|
42
44
|
!Deno.env.get('RAILS_ENV') && Deno.env.set('RAILS_ENV', 'development')
|
43
45
|
|
44
46
|
const { _: paths, ...options } = parseArgs(Deno.args, {
|
45
|
-
string: ['root', 'import-map', 'lightningcss-bin'],
|
47
|
+
string: ['root', 'import-map', 'lightningcss-bin', 'cache-query-string'],
|
46
48
|
boolean: ['write', 'debug'],
|
47
49
|
alias: {
|
48
50
|
'import-map': 'importMap',
|
51
|
+
'cache-query-string': 'cacheQueryString',
|
49
52
|
'lightningcss-bin': 'lightningcssBin'
|
50
53
|
}
|
51
54
|
})
|
@@ -127,7 +130,7 @@ async function main(paths = [], options = {}) {
|
|
127
130
|
bundle: true,
|
128
131
|
plugins: [
|
129
132
|
envPlugin(),
|
130
|
-
resolvePlugin({ runtimeDir, importMap, debug }),
|
133
|
+
resolvePlugin({ runtimeDir, importMap, debug, cacheQueryString: options.cacheQueryString }),
|
131
134
|
cssPlugin({ lightningcssBin: options.lightningcssBin, debug })
|
132
135
|
],
|
133
136
|
metafile: write,
|
@@ -60,8 +60,8 @@ module Proscenium
|
|
60
60
|
response.content_type = content_type
|
61
61
|
response['X-Proscenium-Middleware'] = name
|
62
62
|
|
63
|
-
if Proscenium.config.cache_query_string
|
64
|
-
response['Cache-Control'] = "public, max-age=#{
|
63
|
+
if Proscenium.config.cache_query_string && Proscenium.config.cache_max_age
|
64
|
+
response['Cache-Control'] = "public, max-age=#{Proscenium.config.cache_max_age}"
|
65
65
|
end
|
66
66
|
|
67
67
|
yield response if block_given?
|
@@ -15,9 +15,11 @@ module Proscenium
|
|
15
15
|
|
16
16
|
def attempt
|
17
17
|
benchmark :esbuild do
|
18
|
-
render_response build(
|
19
|
-
"#{cli} --root #{root}
|
20
|
-
|
18
|
+
render_response build([
|
19
|
+
"#{cli} --root #{root}",
|
20
|
+
cache_query_string,
|
21
|
+
"--lightningcss-bin #{lightningcss_cli} #{path}"
|
22
|
+
].compact.join(' '))
|
21
23
|
end
|
22
24
|
rescue CompileError => e
|
23
25
|
render_response "export default #{e.detail.to_json}" do |response|
|
@@ -33,9 +35,7 @@ module Proscenium
|
|
33
35
|
|
34
36
|
def cli
|
35
37
|
if ENV['PROSCENIUM_TEST']
|
36
|
-
|
37
|
-
'deno run -q --import-map import_map.json -A', 'lib/proscenium/compilers/esbuild.js'
|
38
|
-
].join(' ')
|
38
|
+
'deno run -q --import-map import_map.json -A lib/proscenium/compilers/esbuild.js'
|
39
39
|
else
|
40
40
|
Gem.bin_path 'proscenium', 'esbuild'
|
41
41
|
end
|
@@ -48,6 +48,11 @@ module Proscenium
|
|
48
48
|
Gem.bin_path 'proscenium', 'lightningcss'
|
49
49
|
end
|
50
50
|
end
|
51
|
+
|
52
|
+
def cache_query_string
|
53
|
+
q = Proscenium.config.cache_query_string
|
54
|
+
q ? "--cache-query-string #{q}" : nil
|
55
|
+
end
|
51
56
|
end
|
52
57
|
end
|
53
58
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Renders a div for use with component-manager.
|
5
|
+
#
|
6
|
+
class Proscenium::Phlex::ReactComponent < Proscenium::Phlex::Component
|
7
|
+
attr_accessor :props, :lazy
|
8
|
+
|
9
|
+
# @param props: [Hash]
|
10
|
+
# @param lazy: [Boolean] Lazy load the component using IntersectionObserver. Default: true.
|
11
|
+
def initialize(props: {}, lazy: true) # rubocop:disable Lint/MissingSuper
|
12
|
+
@props = props
|
13
|
+
@lazy = lazy
|
14
|
+
end
|
15
|
+
|
16
|
+
# @yield the given block to a `div` within the top level component div. If not given,
|
17
|
+
# `<div>loading...</div>` will be rendered. Use this to display a loading UI while the component
|
18
|
+
# is loading and rendered.
|
19
|
+
def template(&block)
|
20
|
+
div class: ['componentManagedByProscenium', '@component'],
|
21
|
+
data: { component: { path: virtual_path, props: props, lazy: lazy }.to_json } do
|
22
|
+
block ? div(&block) : div { 'loading...' }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/proscenium/phlex.rb
CHANGED
@@ -1,7 +1,30 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'phlex'
|
4
|
+
|
3
5
|
module Proscenium
|
4
6
|
class Phlex < ::Phlex::View
|
7
|
+
extend ActiveSupport::Autoload
|
8
|
+
|
9
|
+
autoload :Component
|
10
|
+
autoload :ReactComponent
|
11
|
+
|
12
|
+
module Helpers
|
13
|
+
def side_load_javascripts(...)
|
14
|
+
if (output = @_view_context.side_load_javascripts(...))
|
15
|
+
@_target << output
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
%i[side_load_stylesheets proscenium_dev].each do |name|
|
20
|
+
define_method name do
|
21
|
+
if (output = @_view_context.send(name))
|
22
|
+
@_target << output
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
5
28
|
module Sideload
|
6
29
|
def template(...)
|
7
30
|
Proscenium::SideLoad.append self.class.path if Rails.application.config.proscenium.side_load
|
@@ -18,6 +41,7 @@ module Proscenium
|
|
18
41
|
child.path = path.delete_prefix(::Rails.root.to_s).delete_suffix('.rb')[1..]
|
19
42
|
|
20
43
|
child.prepend Sideload
|
44
|
+
child.include Helpers
|
21
45
|
|
22
46
|
super
|
23
47
|
end
|
data/lib/proscenium/railtie.rb
CHANGED
@@ -29,6 +29,7 @@ module Proscenium
|
|
29
29
|
config.proscenium = ActiveSupport::OrderedOptions.new
|
30
30
|
config.proscenium.side_load = true
|
31
31
|
config.proscenium.cache_query_string = Rails.env.production? && ENV.fetch('REVISION', nil)
|
32
|
+
config.proscenium.cache_max_age = 2_592_000 # 30 days
|
32
33
|
config.proscenium.auto_reload = Rails.env.development?
|
33
34
|
config.proscenium.auto_reload_paths ||= %w[lib app config]
|
34
35
|
config.proscenium.auto_reload_extensions ||= /\.(css|jsx?)$/
|
@@ -1,5 +1,4 @@
|
|
1
|
-
import { createConsumer } from 'https://esm.sh/@rails/actioncable@
|
2
|
-
import debounce from 'https://esm.sh/debounce@1.2.1'
|
1
|
+
import { createConsumer } from 'https://esm.sh/v96/@rails/actioncable@7.0.4/es2022/actioncable.js'
|
3
2
|
|
4
3
|
export default socketPath => {
|
5
4
|
const uid = (Date.now() + ((Math.random() * 100) | 0)).toString()
|
@@ -9,7 +8,7 @@ export default socketPath => {
|
|
9
8
|
received: debounce(() => {
|
10
9
|
console.log('[Proscenium] Files changed; reloading...')
|
11
10
|
location.reload()
|
12
|
-
}, 200),
|
11
|
+
}, 200, true),
|
13
12
|
|
14
13
|
connected() {
|
15
14
|
console.log('[Proscenium] Auto-reload websocket connected')
|
@@ -20,3 +19,22 @@ export default socketPath => {
|
|
20
19
|
}
|
21
20
|
})
|
22
21
|
}
|
22
|
+
|
23
|
+
function debounce(func, wait, immediate) {
|
24
|
+
let timeout
|
25
|
+
|
26
|
+
return function () {
|
27
|
+
const args = arguments
|
28
|
+
|
29
|
+
const later = () => {
|
30
|
+
timeout = null
|
31
|
+
!immediate && func.apply(this, args)
|
32
|
+
}
|
33
|
+
|
34
|
+
const callNow = immediate && !timeout
|
35
|
+
clearTimeout(timeout)
|
36
|
+
timeout = setTimeout(later, wait)
|
37
|
+
|
38
|
+
callNow && func.apply(this, args)
|
39
|
+
}
|
40
|
+
}
|
data/lib/proscenium/version.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
class ReactComponent <
|
3
|
+
class Proscenium::ViewComponent::ReactComponent < Proscenium::ViewComponent
|
4
4
|
attr_accessor :props, :lazy
|
5
5
|
|
6
6
|
# @param props: [Hash]
|
@@ -15,7 +15,7 @@ class ReactComponent < ApplicationComponent
|
|
15
15
|
def call
|
16
16
|
tag.div class: ['componentManagedByProscenium', css_module(:component)],
|
17
17
|
data: { component: { path: virtual_path, props: props, lazy: lazy } } do
|
18
|
-
tag.div content
|
18
|
+
tag.div content || 'loading...'
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
@@ -1,12 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require 'view_component'
|
4
|
+
|
5
|
+
class Proscenium::ViewComponent < ViewComponent::Base
|
4
6
|
extend ActiveSupport::Autoload
|
5
7
|
|
6
8
|
autoload :TagBuilder
|
9
|
+
autoload :ReactComponent
|
7
10
|
|
8
11
|
def render_in(...)
|
9
|
-
cssm.compile_class_names(super)
|
12
|
+
cssm.compile_class_names(super(...))
|
10
13
|
end
|
11
14
|
|
12
15
|
def before_render
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: proscenium
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: x86_64-darwin
|
6
6
|
authors:
|
7
7
|
- Joel Moss
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-10-
|
11
|
+
date: 2022-10-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actioncable
|
@@ -92,6 +92,20 @@ dependencies:
|
|
92
92
|
- - "~>"
|
93
93
|
- !ruby/object:Gem::Version
|
94
94
|
version: '3.13'
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: phlex
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - "~>"
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: 0.4.0
|
102
|
+
type: :runtime
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - "~>"
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: 0.4.0
|
95
109
|
- !ruby/object:Gem::Dependency
|
96
110
|
name: railties
|
97
111
|
requirement: !ruby/object:Gem::Requirement
|
@@ -140,8 +154,6 @@ files:
|
|
140
154
|
- README.md
|
141
155
|
- app/channels/proscenium/connection.rb
|
142
156
|
- app/channels/proscenium/reload_channel.rb
|
143
|
-
- app/components/application_component.rb
|
144
|
-
- app/components/react_component.rb
|
145
157
|
- bin/esbuild
|
146
158
|
- bin/lightningcss
|
147
159
|
- config/routes.rb
|
@@ -171,6 +183,8 @@ files:
|
|
171
183
|
- lib/proscenium/middleware/runtime.rb
|
172
184
|
- lib/proscenium/middleware/static.rb
|
173
185
|
- lib/proscenium/phlex.rb
|
186
|
+
- lib/proscenium/phlex/component.rb
|
187
|
+
- lib/proscenium/phlex/react_component.rb
|
174
188
|
- lib/proscenium/precompile.rb
|
175
189
|
- lib/proscenium/railtie.rb
|
176
190
|
- lib/proscenium/runtime/auto_reload.js
|
@@ -180,6 +194,7 @@ files:
|
|
180
194
|
- lib/proscenium/utils.js
|
181
195
|
- lib/proscenium/version.rb
|
182
196
|
- lib/proscenium/view_component.rb
|
197
|
+
- lib/proscenium/view_component/react_component.rb
|
183
198
|
- lib/proscenium/view_component/tag_builder.rb
|
184
199
|
- lib/tasks/assets.rake
|
185
200
|
homepage: https://github.com/joelmoss/proscenium
|