bridgetown-lit-renderer 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Demo Site](https://img.shields.io/badge/Demo%20Site-teal?style=for-the-badge&logo=safari)](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:
|