bridgetown-lit-renderer 1.0.0 → 1.1.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 +4 -4
- data/.rubocop.yml +2 -13
- data/CHANGELOG.md +4 -0
- data/Gemfile +2 -0
- data/README.md +84 -9
- data/Rakefile +3 -1
- data/bridgetown-lit-renderer.gemspec +8 -4
- data/lib/bridgetown-lit-renderer/builder.rb +20 -70
- data/lib/bridgetown-lit-renderer/renderer.rb +130 -0
- data/lib/bridgetown-lit-renderer/version.rb +1 -1
- data/lib/bridgetown-lit-renderer.rb +1 -0
- data/package.json +2 -1
- data/src/serve.js +30 -0
- data/src/ssr_exec.js +30 -0
- data/yarn.lock +5 -0
- metadata +25 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e113f9942a7af9037d258ba59579880056c9f34e4c2b96021ba85d44408bef94
|
4
|
+
data.tar.gz: 50b03942311d65557165cfd0a39ec831180fb5762f0761447251e0d27750c688
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 88377734db394ff70b38ccd2af7af04c4d2398216a493fb8f36999be4482066e0e99c582d5596c75fb2c42104f7ce8e820057c34de239b8969d71610f989c14c
|
7
|
+
data.tar.gz: f0eaecd4d0df555280229fef0b6172a6015ca1a1535f8fb6536e1b17e7a596365af705b54814a8b6ff404153e6c85f3e88783185e52d405b7ccd5ca0d3229b5b
|
data/.rubocop.yml
CHANGED
@@ -5,18 +5,7 @@ inherit_gem:
|
|
5
5
|
|
6
6
|
AllCops:
|
7
7
|
TargetRubyVersion: 2.5
|
8
|
-
Include:
|
9
|
-
- lib/**/*.rb
|
10
|
-
- test/**/*.rb
|
11
8
|
|
12
9
|
Exclude:
|
13
|
-
-
|
14
|
-
- .
|
15
|
-
|
16
|
-
- Gemfile.lock
|
17
|
-
- CHANGELOG.md
|
18
|
-
- LICENSE.txt
|
19
|
-
- README.md
|
20
|
-
|
21
|
-
- script/**/*
|
22
|
-
- vendor/**/*
|
10
|
+
- "*.gemspec"
|
11
|
+
- test/helper.rb
|
data/CHANGELOG.md
CHANGED
@@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
9
9
|
|
10
10
|
- ...
|
11
11
|
|
12
|
+
## 1.1.0 - 2021-12-03
|
13
|
+
|
14
|
+
- Switch to processing SSR through Node sidecar server and various other performance & caching enhancements
|
15
|
+
|
12
16
|
## 1.0.0 - 2021-09-25
|
13
17
|
|
14
18
|
- First release (currently experimental stage).
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
# Bridgetown Lit Renderer
|
2
2
|
|
3
|
-
|
3
|
+
[![lit][lit]][lit-url]
|
4
|
+
[![gem][gem]][gem-url]
|
5
|
+
[![npm][npm]][npm-url]
|
6
|
+
[](https://bridgetown-lit-renderer.onrender.com)
|
7
|
+
|
8
|
+
Simple pipeline for SSR + hydration of Lit components in your [Bridgetown](https://www.bridgetownrb.com) site.
|
9
|
+
|
10
|
+
[Check out the demo site repo](https://github.com/bridgetownrb/lit-renderer-example), or keep reading to get started.
|
4
11
|
|
5
12
|
## Installation
|
6
13
|
|
@@ -9,7 +16,7 @@ Run this command to add this plugin to your site's Gemfile, along with Lit 2 and
|
|
9
16
|
```shell
|
10
17
|
$ bundle add bridgetown-lit-renderer -g bridgetown_plugins
|
11
18
|
|
12
|
-
$ yarn add lit @lit-labs/ssr
|
19
|
+
$ yarn add bridgetown-lit-renderer lit @lit-labs/ssr
|
13
20
|
```
|
14
21
|
|
15
22
|
Create a file in `config/lit-ssr.config.js` with the following:
|
@@ -41,9 +48,8 @@ export class HappyDaysElement extends LitElement {
|
|
41
48
|
:host {
|
42
49
|
display: block;
|
43
50
|
border: 2px dashed gray;
|
44
|
-
|
45
|
-
|
46
|
-
width: 20vw;
|
51
|
+
padding: 20px;
|
52
|
+
max-width: 300px;
|
47
53
|
}
|
48
54
|
`
|
49
55
|
|
@@ -61,10 +67,10 @@ export class HappyDaysElement extends LitElement {
|
|
61
67
|
customElements.define('happy-days', HappyDaysElement)
|
62
68
|
```
|
63
69
|
|
64
|
-
Finally, create a new `.erb` page somewhere in `src`, and add this
|
70
|
+
Finally, create a new `.erb` page somewhere in `src`, and add this to your template:
|
65
71
|
|
66
72
|
```erb
|
67
|
-
<%= lit data: {hello: "there"} do %>
|
73
|
+
<%= lit data: { hello: "there" } do %>
|
68
74
|
<happy-days hello="${data.hello}"></happy-days>
|
69
75
|
<% end %>
|
70
76
|
```
|
@@ -73,12 +79,74 @@ Now start up your Bridgetown site, visit the page, and if all goes well, you sho
|
|
73
79
|
|
74
80
|
You can reload the page several times and see that the timestamp doesn't change, because Lit's SSR + Hydration support knows not to re-render the component. However, if you change the `hello` attribute in the HTML, you'll get a re-render and thus see a new timestamp. _How cool is that?!_
|
75
81
|
|
76
|
-
### Configuration
|
82
|
+
### Usage and Configuration Options
|
83
|
+
|
84
|
+
The `lit` helper works in any Ruby template language and let's you pass data down to the Lit SSR build process. As long as your `data` value is an object that can be converted to JSON (via Ruby's `to_json`), you're set. In fact, you can even pass your page/resource front matter along for the ride:
|
85
|
+
|
86
|
+
```erb
|
87
|
+
<%= lit data: resource.data do %>
|
88
|
+
<page-header title="${data.title}"></page-header>
|
89
|
+
<% end %>
|
90
|
+
```
|
91
|
+
|
92
|
+
When the component is hydrated, it will utilize the same data that was passed at build time and avoid a client-side re-render. However, from that point forward you're free to mutate component attribute/properties to trigger re-renders as normal. [Check out Lit's `firstUpdated` method](https://lit.dev/docs/components/lifecycle/#reactive-update-cycle-completing) as a good place to start.
|
93
|
+
|
94
|
+
You also have the option of choosing a different entry point (aka your JS file that contains or imports one or more Lit components). The default is `./frontend/javascript/lit-components.js`, but you can specify any other file you wish (the path should be relative to your project root).
|
95
|
+
|
96
|
+
```erb
|
97
|
+
<%= lit data: resource.data, entry: "./frontend/javascript/components/headers.js" do %>
|
98
|
+
<page-header title="${data.title}"></page-header>
|
99
|
+
<% end %>
|
100
|
+
```
|
101
|
+
|
102
|
+
This would typically coincide with a strategy of having multiple Webpack entry points, and loading different entry points on different parts of your site. An exercise left for the reader…
|
103
|
+
|
104
|
+
### Technical and Performance Considerations
|
105
|
+
|
106
|
+
The Bridgetown Lit render helper works by compiling your entry point together with your code block via esbuild and caching the resulting JS snippet. A second pass combines your `data` with the snippet and executes it via a temporary "sidecar" Node server which utilizes Lit's SSR rendering pipeline. That output is again cached in a way which persists on-disk for use across builds.
|
107
|
+
|
108
|
+
This for performance reasons. If you have added a Lit template to a layout used by, say, a thousand products, your first build will indeed execute Lit SSR for those thousand products, but thereafter it will be cached. If you change the data for one product, such as a price, Lit SSR will reexecute _only_ for that one product. In addition, for a data-only change the previously compiled JS snippet via esbuild _won't_ need to be recompiled. Of course if you also modify either the HTML markup within the helper block or the entry point itself, recompilation must take place.
|
77
109
|
|
78
|
-
|
110
|
+
It's also recommended you don't include any Ruby template code _within_ the helper code block (e.g., using `<%= %>` tags) which results in constantly changing output, as that would necessitate recompiling with esbuild on a regular basis.
|
111
|
+
|
112
|
+
Thus with a bit of careful planning of which entry point(s) you create, the data you provide, and the structure of your HTML markup within the `lit` helper, you can achieve good Lit SSR performance while still taking full advantage of the Ruby templates and components you know and love.
|
113
|
+
|
114
|
+
(If you do run into major issues and want to outright disable the esbuild/SSR caching, you can add `disable_lit_caching: true` to your Bridgetown config.)
|
115
|
+
|
116
|
+
**A note about Lit templates:** in case you're wondering, the markup within the `lit` helper is actually executed inside Lit's `html` tagged template literal, and [all the usual rules of Lit templates apply](https://lit.dev/docs/templates/overview/). It's recommended you keep the markup within the helper block brief, and let the web component itself do most of the heavy lifting.
|
117
|
+
|
118
|
+
**Use only one root element.** Because of how the provided `hydrate-root` element works, which will wrap your markup in each `lit` code block, you should only have _one_ root element, and it should be a Lit component. For example, instead of doing this:
|
119
|
+
|
120
|
+
```erb
|
121
|
+
<%= lit do %>
|
122
|
+
<div>
|
123
|
+
<h2>Hmm...</h2>
|
124
|
+
<my-component>This doesn't seem right.</my-component>
|
125
|
+
</div>
|
126
|
+
<p>Huh.</p>
|
127
|
+
<% end %>
|
128
|
+
```
|
129
|
+
|
130
|
+
you should be doing this:
|
131
|
+
|
132
|
+
```erb
|
133
|
+
<%= lit do %>
|
134
|
+
<wrapper-component>
|
135
|
+
<div>
|
136
|
+
<h2>Hmm...</h2>
|
137
|
+
<my-component>This doesn't seem right.</my-component>
|
138
|
+
</div>
|
139
|
+
<p>Huh.</p>
|
140
|
+
</wrapper-component>
|
141
|
+
<% end %>
|
142
|
+
```
|
143
|
+
|
144
|
+
**Disabling hydration?** If for some reason you can't permit a `hydrate-root` element to wrap a Lit code block, you can pass a `hydrate_root: false` argument to the `lit` helper. This breaks hydration however, and likewise the [Declarative Shadow DOM (DSD)](https://web.dev/declarative-shadow-dom/) polyfill won't be loaded. (Currently DSD is only supported natively in Chromium-based browsers such as Chrome, Edge, and Brave.) It will thus be up to you to manage those features as you see fit.
|
79
145
|
|
80
146
|
## Testing
|
81
147
|
|
148
|
+
_Note: a proper site fixture and tests are in the works._
|
149
|
+
|
82
150
|
* Run `bundle exec rake test` to run the test suite
|
83
151
|
* Or run `script/cibuild` to validate with Rubocop and Minitest together.
|
84
152
|
|
@@ -90,3 +158,10 @@ You can reload the page several times and see that the timestamp doesn't change,
|
|
90
158
|
4. Commit your changes (`git commit -am 'Add some feature'`)
|
91
159
|
5. Push to the branch (`git push origin my-new-feature`)
|
92
160
|
6. Create a new Pull Request
|
161
|
+
|
162
|
+
[lit]: https://img.shields.io/badge/-Lit-324FFF?style=for-the-badge&logo=lit&logoColor=white"
|
163
|
+
[lit-url]: https://lit.dev
|
164
|
+
[gem]: https://img.shields.io/gem/v/bridgetown-lit-renderer.svg?style=for-the-badge&color=red
|
165
|
+
[gem-url]: https://rubygems.org/gems/bridgetown-lit-renderer
|
166
|
+
[npm]: https://img.shields.io/npm/v/bridgetown-lit-renderer.svg?style=for-the-badge
|
167
|
+
[npm-url]: https://npmjs.com/package/bridgetown-lit-renderer
|
data/Rakefile
CHANGED
@@ -11,16 +11,20 @@ Gem::Specification.new do |spec|
|
|
11
11
|
spec.homepage = "https://github.com/bridgetownrb/bridgetown-lit-renderer"
|
12
12
|
spec.license = "MIT"
|
13
13
|
|
14
|
-
spec.files = `git ls-files -z`.split("\x0").reject
|
14
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
15
|
+
f.match(%r!^(test|script|spec|features|frontend)/!)
|
16
|
+
end
|
15
17
|
spec.test_files = spec.files.grep(%r!^test/!)
|
16
18
|
spec.require_paths = ["lib"]
|
17
|
-
spec.metadata = { "yarn-add"
|
19
|
+
spec.metadata = { "yarn-add" => "bridgetown-lit-renderer@#{BridgetownLitRenderer::VERSION}",
|
20
|
+
"rubygems_mfa_required" => "true", }
|
18
21
|
|
19
22
|
spec.required_ruby_version = ">= 2.5.0"
|
20
23
|
|
21
24
|
spec.add_dependency "bridgetown", ">= 0.15", "< 2.0"
|
25
|
+
spec.add_dependency "random-port", ">= 0.5"
|
22
26
|
|
23
27
|
spec.add_development_dependency "bundler"
|
24
|
-
spec.add_development_dependency "rake", "~>
|
25
|
-
spec.add_development_dependency "rubocop-bridgetown", "~> 0.
|
28
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
29
|
+
spec.add_development_dependency "rubocop-bridgetown", "~> 0.3"
|
26
30
|
end
|
@@ -1,71 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module BridgetownLitRenderer
|
4
|
-
module Renderer
|
5
|
-
def self.reset_cache
|
6
|
-
@code_cache = {}
|
7
|
-
@lit_notice_printed = false
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.esbuild(code, site)
|
11
|
-
unless @lit_notice_printed
|
12
|
-
Bridgetown.logger.info "Lit SSR:", "Bundling with esbuild..."
|
13
|
-
@lit_notice_printed = true
|
14
|
-
end
|
15
|
-
|
16
|
-
IO.popen(["node", site.in_root_dir("./config/lit-ssr.config.js")], "r+") do |pipe|
|
17
|
-
pipe.puts({ code: code }.to_json)
|
18
|
-
pipe.close_write
|
19
|
-
pipe.read
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.render(code, data:, entry:, site:) # rubocop:disable Metrics/MethodLength
|
24
|
-
@code_cache ||= {}
|
25
|
-
cache_key = "#{code}#{entry}"
|
26
|
-
|
27
|
-
unless @code_cache[cache_key]
|
28
|
-
build_code = <<~JS
|
29
|
-
import { Readable } from "stream"
|
30
|
-
import { render } from "@lit-labs/ssr/lib/render-with-global-dom-shim.js"
|
31
|
-
import { html } from "lit"
|
32
|
-
import #{entry.to_json}
|
33
|
-
|
34
|
-
const ssrResult = render(html`
|
35
|
-
#{code}
|
36
|
-
`);
|
37
|
-
|
38
|
-
const _tmplStream = Readable.from(ssrResult)
|
39
|
-
|
40
|
-
let _tmplOutput = ""
|
41
|
-
_tmplStream.on('data', function(chunk) {
|
42
|
-
_tmplOutput += chunk;
|
43
|
-
});
|
44
|
-
|
45
|
-
_tmplStream.on('end',function() {
|
46
|
-
process.stdout.write("====== SSR ======") // marker to ensure stray console outputs don't end up in HTML
|
47
|
-
process.stdout.write(_tmplOutput)
|
48
|
-
});
|
49
|
-
JS
|
50
|
-
|
51
|
-
@code_cache[cache_key] = esbuild(build_code, site)
|
52
|
-
end
|
53
|
-
|
54
|
-
IO.popen(["node"], "r+") do |pipe|
|
55
|
-
pipe.puts "const data = #{data.to_json}; #{@code_cache[cache_key]}"
|
56
|
-
pipe.close_write
|
57
|
-
pipe.read
|
58
|
-
end.partition("====== SSR ======").last.html_safe
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
4
|
class Builder < Bridgetown::Builder
|
63
|
-
def
|
64
|
-
|
65
|
-
|
5
|
+
def build # rubocop:todo Metrics/AbcSize, Metrics/MethodLength
|
6
|
+
BridgetownLitRenderer::Renderer.instance.site = site
|
7
|
+
BridgetownLitRenderer::Renderer.instance.reset
|
8
|
+
hook :site, :post_render do
|
9
|
+
BridgetownLitRenderer::Renderer.stop_node_server
|
10
|
+
end
|
66
11
|
|
67
|
-
def build
|
68
|
-
BridgetownLitRenderer::Renderer.reset_cache
|
69
12
|
helper "lit", helpers_scope: true do |
|
70
13
|
data: {},
|
71
14
|
hydrate_root: true,
|
@@ -74,17 +17,24 @@ module BridgetownLitRenderer
|
|
74
17
|
|
|
75
18
|
code = view.capture(&block)
|
76
19
|
if hydrate_root
|
77
|
-
code = "<hydrate-root>#{code.sub(%r{
|
20
|
+
code = "<hydrate-root>#{code.sub(%r{<([a-zA-Z]+-[a-zA-Z-]*)}, "<\\1 defer-hydration")}</hydrate-root>" # rubocop:disable Layout/LineLength
|
78
21
|
end
|
79
22
|
|
80
|
-
|
81
|
-
|
23
|
+
render_fn = -> do
|
24
|
+
BridgetownLitRenderer::Renderer.instance.render(
|
25
|
+
code,
|
26
|
+
data: data,
|
27
|
+
entry: entry,
|
28
|
+
caching: !site.config.disable_lit_caching
|
29
|
+
)
|
82
30
|
end
|
83
31
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
32
|
+
next render_fn.() if site.config.disable_lit_caching
|
33
|
+
|
34
|
+
entry_key = BridgetownLitRenderer::Renderer.instance.entry_key(entry)
|
35
|
+
BridgetownLitRenderer::Renderer.instance.cache.getset(
|
36
|
+
"output-#{code}#{data}#{entry_key}"
|
37
|
+
) { render_fn.() }
|
88
38
|
end
|
89
39
|
end
|
90
40
|
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "random-port"
|
4
|
+
require "singleton"
|
5
|
+
|
6
|
+
module BridgetownLitRenderer
|
7
|
+
class Renderer
|
8
|
+
include Singleton
|
9
|
+
|
10
|
+
class << self
|
11
|
+
attr_accessor :serverpid, :serverport, :authtoken
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_accessor :site
|
15
|
+
|
16
|
+
def self.start_node_server
|
17
|
+
return if serverpid
|
18
|
+
|
19
|
+
self.authtoken = SecureRandom.hex(64)
|
20
|
+
self.serverport = RandomPort::Pool.new.acquire
|
21
|
+
|
22
|
+
self.serverpid = spawn(
|
23
|
+
{
|
24
|
+
"LIT_SSR_SERVER_PORT" => serverport.to_s,
|
25
|
+
"LIT_SSR_AUTH_TOKEN" => authtoken,
|
26
|
+
},
|
27
|
+
"node #{File.expand_path("../../src/serve.js", __dir__)}",
|
28
|
+
pgroup: true
|
29
|
+
)
|
30
|
+
Process.detach serverpid
|
31
|
+
sleep 0.5
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.stop_node_server
|
35
|
+
return unless serverpid
|
36
|
+
|
37
|
+
Process.kill("SIGTERM", -Process.getpgid(serverpid))
|
38
|
+
self.serverpid = nil
|
39
|
+
self.serverport = nil
|
40
|
+
rescue Errno::ESRCH, Errno::EPERM, Errno::ECHILD # rubocop:disable Lint/SuppressedException
|
41
|
+
end
|
42
|
+
|
43
|
+
def entry_key(entry)
|
44
|
+
entry.start_with?("./") ? File.stat(site.in_root_dir(entry)).mtime : entry
|
45
|
+
end
|
46
|
+
|
47
|
+
def reset
|
48
|
+
@esbuild_notice_printed = false
|
49
|
+
@render_notice_printed = false
|
50
|
+
end
|
51
|
+
|
52
|
+
def cache
|
53
|
+
@cache ||= Bridgetown::Cache.new("LitSSR")
|
54
|
+
end
|
55
|
+
|
56
|
+
def esbuild(code)
|
57
|
+
raise "You must first assign the `site' accessor" unless site
|
58
|
+
|
59
|
+
unless @esbuild_notice_printed
|
60
|
+
Bridgetown.logger.info "Lit SSR:", "Bundling with esbuild..."
|
61
|
+
@esbuild_notice_printed = true
|
62
|
+
end
|
63
|
+
|
64
|
+
IO.popen(["node", site.in_root_dir("./config/lit-ssr.config.js")], "r+") do |pipe|
|
65
|
+
pipe.puts({ code: code }.to_json)
|
66
|
+
pipe.close_write
|
67
|
+
pipe.read
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def render(code, data:, entry:, caching: true) # rubocop:todo Metrics/MethodLength, Metrics/AbcSize
|
72
|
+
raise "You must first assign the `site' accessor" unless site
|
73
|
+
|
74
|
+
cache_key = "esbuild-#{code}#{entry}#{entry_key(entry)}"
|
75
|
+
|
76
|
+
esbuild_fn = -> { esbuild(js_code_block(entry, code)) }
|
77
|
+
|
78
|
+
built_code = if caching
|
79
|
+
cache.getset(cache_key) { esbuild_fn.() }
|
80
|
+
else
|
81
|
+
esbuild_fn.()
|
82
|
+
end
|
83
|
+
|
84
|
+
unless @render_notice_printed
|
85
|
+
Bridgetown.logger.info "Lit SSR:", "Rendering components..."
|
86
|
+
@render_notice_printed = true
|
87
|
+
end
|
88
|
+
|
89
|
+
self.class.start_node_server
|
90
|
+
|
91
|
+
output = Faraday.post(
|
92
|
+
"http://127.0.0.1:#{self.class.serverport}",
|
93
|
+
"const data = #{data.to_json}; #{built_code}",
|
94
|
+
"Authorization" => "Bearer #{self.class.authtoken}"
|
95
|
+
).body
|
96
|
+
|
97
|
+
if output == "SCRIPT NOT VALID!"
|
98
|
+
output = <<~HTML
|
99
|
+
<ssr-error style="display:block; padding:0.3em 0.5em; color:white; background:maroon; font-weight:bold">
|
100
|
+
Lit SSR error in #{entry}, see logs
|
101
|
+
</ssr-error>
|
102
|
+
HTML
|
103
|
+
cache.delete(cache_key) if caching
|
104
|
+
end
|
105
|
+
|
106
|
+
output.html_safe
|
107
|
+
end
|
108
|
+
|
109
|
+
def js_code_block(entry, code)
|
110
|
+
entry_import = "import #{entry.to_json}"
|
111
|
+
<<~JS
|
112
|
+
import { Readable } from "stream"
|
113
|
+
import { render } from "@lit-labs/ssr/lib/render-with-global-dom-shim.js"
|
114
|
+
import { html } from "lit"
|
115
|
+
#{entry_import}
|
116
|
+
|
117
|
+
const ssrResult = render(html`
|
118
|
+
#{code}
|
119
|
+
`);
|
120
|
+
|
121
|
+
let ret = []
|
122
|
+
for (const chunk of ssrResult) {
|
123
|
+
ret.push(chunk)
|
124
|
+
}
|
125
|
+
|
126
|
+
ret.join("")
|
127
|
+
JS
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
data/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "bridgetown-lit-renderer",
|
3
|
-
"version": "1.
|
3
|
+
"version": "1.1.0",
|
4
4
|
"main": "frontend/javascript/index.js",
|
5
5
|
"exports": {
|
6
6
|
".": {
|
@@ -26,6 +26,7 @@
|
|
26
26
|
],
|
27
27
|
"dependencies": {
|
28
28
|
"@webcomponents/template-shadowroot": "^0.1.0",
|
29
|
+
"colors": "^1.4.0",
|
29
30
|
"esbuild": "^0.12"
|
30
31
|
}
|
31
32
|
}
|
data/src/serve.js
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
const http = require("http")
|
2
|
+
const litexec = require("./ssr_exec")
|
3
|
+
|
4
|
+
const server = http.createServer((req, res) => {
|
5
|
+
if (req.method === "POST" && req.headers.authorization?.endsWith(process.env.LIT_SSR_AUTH_TOKEN)) {
|
6
|
+
let body = ""
|
7
|
+
req.on("data", (chunk) => {
|
8
|
+
body += chunk.toString()
|
9
|
+
});
|
10
|
+
req.on("end", () => {
|
11
|
+
let ret = "";
|
12
|
+
try {
|
13
|
+
ret = litexec.execScript(body)
|
14
|
+
} catch (e) {
|
15
|
+
console.warn(e);
|
16
|
+
}
|
17
|
+
if (ret) {
|
18
|
+
res.end(ret.toString())
|
19
|
+
} else {
|
20
|
+
res.end("SCRIPT NOT VALID!")
|
21
|
+
}
|
22
|
+
})
|
23
|
+
} else {
|
24
|
+
res.statusCode = 400
|
25
|
+
res.end("Invalid Request!")
|
26
|
+
}
|
27
|
+
})
|
28
|
+
|
29
|
+
const port = process.env.LIT_SSR_SERVER_PORT
|
30
|
+
server.listen(port, "127.0.0.1")
|
data/src/ssr_exec.js
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
const colors = require("colors/safe")
|
2
|
+
|
3
|
+
const originalConsoleLog = console.log
|
4
|
+
|
5
|
+
console.log = function () {
|
6
|
+
args = []
|
7
|
+
args.push(colors.rainbow("[LitSSR]"))
|
8
|
+
// Note: arguments is part of the prototype
|
9
|
+
for (let i = 0; i < arguments.length; i++) {
|
10
|
+
args.push(arguments[i])
|
11
|
+
}
|
12
|
+
originalConsoleLog.apply(console, args)
|
13
|
+
}
|
14
|
+
|
15
|
+
module.exports = {
|
16
|
+
execScript(str) {
|
17
|
+
const vm = require("vm")
|
18
|
+
const contextObject = {
|
19
|
+
require: require,
|
20
|
+
console: console,
|
21
|
+
process: process,
|
22
|
+
global: global,
|
23
|
+
URL: URL,
|
24
|
+
Buffer: Buffer,
|
25
|
+
__filename: "__lit_eval.js",
|
26
|
+
}
|
27
|
+
|
28
|
+
return vm.runInNewContext(str, contextObject)
|
29
|
+
},
|
30
|
+
}
|
data/yarn.lock
CHANGED
@@ -7,6 +7,11 @@
|
|
7
7
|
resolved "https://registry.yarnpkg.com/@webcomponents/template-shadowroot/-/template-shadowroot-0.1.0.tgz#adb3438d0d9a18e8fced08abc253f56b7eadab00"
|
8
8
|
integrity sha512-ry84Vft6xtRBbd4M/ptRodbOLodV5AD15TYhyRghCRgIcJJKmYmJ2v2BaaWxygENwh6Uq3zTfGPmlckKT/GXsQ==
|
9
9
|
|
10
|
+
colors@^1.4.0:
|
11
|
+
version "1.4.0"
|
12
|
+
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
|
13
|
+
integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
|
14
|
+
|
10
15
|
esbuild@^0.12:
|
11
16
|
version "0.12.29"
|
12
17
|
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.12.29.tgz#be602db7c4dc78944a9dbde0d1ea19d36c1f882d"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bridgetown-lit-renderer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bridgetown Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bridgetown
|
@@ -30,6 +30,20 @@ dependencies:
|
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: '2.0'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: random-port
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0.5'
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0.5'
|
33
47
|
- !ruby/object:Gem::Dependency
|
34
48
|
name: bundler
|
35
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -50,28 +64,28 @@ dependencies:
|
|
50
64
|
requirements:
|
51
65
|
- - "~>"
|
52
66
|
- !ruby/object:Gem::Version
|
53
|
-
version: '
|
67
|
+
version: '13.0'
|
54
68
|
type: :development
|
55
69
|
prerelease: false
|
56
70
|
version_requirements: !ruby/object:Gem::Requirement
|
57
71
|
requirements:
|
58
72
|
- - "~>"
|
59
73
|
- !ruby/object:Gem::Version
|
60
|
-
version: '
|
74
|
+
version: '13.0'
|
61
75
|
- !ruby/object:Gem::Dependency
|
62
76
|
name: rubocop-bridgetown
|
63
77
|
requirement: !ruby/object:Gem::Requirement
|
64
78
|
requirements:
|
65
79
|
- - "~>"
|
66
80
|
- !ruby/object:Gem::Version
|
67
|
-
version: '0.
|
81
|
+
version: '0.3'
|
68
82
|
type: :development
|
69
83
|
prerelease: false
|
70
84
|
version_requirements: !ruby/object:Gem::Requirement
|
71
85
|
requirements:
|
72
86
|
- - "~>"
|
73
87
|
- !ruby/object:Gem::Version
|
74
|
-
version: '0.
|
88
|
+
version: '0.3'
|
75
89
|
description:
|
76
90
|
email: maintainers@bridgetownrb.com
|
77
91
|
executables: []
|
@@ -88,16 +102,20 @@ files:
|
|
88
102
|
- bridgetown-lit-renderer.gemspec
|
89
103
|
- lib/bridgetown-lit-renderer.rb
|
90
104
|
- lib/bridgetown-lit-renderer/builder.rb
|
105
|
+
- lib/bridgetown-lit-renderer/renderer.rb
|
91
106
|
- lib/bridgetown-lit-renderer/version.rb
|
92
107
|
- package.json
|
93
108
|
- src/build.js
|
94
109
|
- src/import-meta-url-shim.js
|
110
|
+
- src/serve.js
|
111
|
+
- src/ssr_exec.js
|
95
112
|
- yarn.lock
|
96
113
|
homepage: https://github.com/bridgetownrb/bridgetown-lit-renderer
|
97
114
|
licenses:
|
98
115
|
- MIT
|
99
116
|
metadata:
|
100
|
-
yarn-add: bridgetown-lit-renderer@1.
|
117
|
+
yarn-add: bridgetown-lit-renderer@1.1.0
|
118
|
+
rubygems_mfa_required: 'true'
|
101
119
|
post_install_message:
|
102
120
|
rdoc_options: []
|
103
121
|
require_paths:
|