quilt_rails 3.2.1 → 3.4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +11 -11
- data/Rakefile +2 -0
- data/app/controllers/quilt/performance_report_controller.rb +2 -2
- data/app/controllers/quilt/ui_controller.rb +10 -0
- data/lib/generators/quilt/rails_setup/rails_setup_generator.rb +4 -4
- data/lib/generators/quilt/react_setup/react_setup_generator.rb +1 -1
- data/lib/quilt_rails.rb +2 -1
- data/lib/quilt_rails/configuration.rb +21 -12
- data/lib/quilt_rails/engine.rb +14 -0
- data/lib/quilt_rails/header_csrf_strategy.rb +4 -3
- data/lib/quilt_rails/logger.rb +8 -5
- data/lib/quilt_rails/performance/report.rb +25 -11
- data/lib/quilt_rails/react_renderable.rb +14 -10
- data/lib/quilt_rails/version.rb +1 -1
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4740cbe3dcb527f279be3289d9d71097f92bb5a943378690234617dace12fe0e
|
4
|
+
data.tar.gz: c0560de0c9e8504d5ccc645be4fb57205560aeace2ba5e9fe4437f71374d394c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1ef599968c2e5a615e2a747555694284482ff99c5e0ee4dd323173b9ff2660857fad0582592990544e81fcc40af73bbd1f3a5525ba4943152955b604881f7922
|
7
|
+
data.tar.gz: 13c3210ed0ab6a7c70b477a33b6208497b8412f6ad2316441b5418da0ba0db8e6141de86f8e1853be75040b5bbe079231e70b0962efcbda250d26844d68a391c
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# quilt_rails
|
2
2
|
|
3
|
-
A turn-key solution for integrating Quilt client-side libraries into your Rails app, with support for server-side-rendering using [`@shopify/react-server`](https://www.npmjs.com/package/@shopify/react-server), integration with [`@shopify/sewing-kit`](https://github.com/Shopify/sewing-kit) for building, testing and linting, and front-end performance tracking through [`@shopify/performance`](https://www.npmjs.com/package/@shopify/performance).
|
3
|
+
A turn-key solution for integrating [Quilt](https://github.com/Shopify/quilt) client-side libraries into your Rails app, with support for server-side-rendering using [`@shopify/react-server`](https://www.npmjs.com/package/@shopify/react-server), integration with [`@shopify/sewing-kit`](https://github.com/Shopify/sewing-kit) for building, testing and linting, and front-end performance tracking through [`@shopify/performance`](https://www.npmjs.com/package/@shopify/performance).
|
4
4
|
|
5
5
|
## Table of Contents
|
6
6
|
|
@@ -67,9 +67,9 @@ Follow [this guide](./docs/manual-installation.md) on how to do manual setup wit
|
|
67
67
|
|
68
68
|
For fast tests with consistent results, test front-end components using the tools provided by sewing-kit instead of Rails integration tests.
|
69
69
|
|
70
|
-
Use [`sewing-kit test`](https://github.com/Shopify/sewing-kit/blob/
|
70
|
+
Use [`sewing-kit test`](https://github.com/Shopify/sewing-kit/blob/main/docs/commands/test.md#L3) to run all `.test.{js|ts}x` files in the `app/ui` directory. [Jest](https://jestjs.io/) is used as a test runner, with customization available via [its sewing-kit plugin](https://github.com/Shopify/sewing-kit/blob/main/docs/plugins/jest.md).
|
71
71
|
|
72
|
-
For testing React applications we provide and support [`@shopify/react-testing`](https://github.com/Shopify/quilt/tree/
|
72
|
+
For testing React applications we provide and support [`@shopify/react-testing`](https://github.com/Shopify/quilt/tree/main/packages/react-testing).
|
73
73
|
|
74
74
|
##### Example
|
75
75
|
|
@@ -102,11 +102,11 @@ describe('MyComponent', () => {
|
|
102
102
|
|
103
103
|
Often you will want to hook up custom polyfills, global mocks, or other logic that needs to run either before the initialization of the test environment, or once for each test suite.
|
104
104
|
|
105
|
-
By default, sewing-kit will look for such test setup files under `/app/ui/tests`. Check out the [documentation](https://github.com/Shopify/sewing-kit/blob/
|
105
|
+
By default, sewing-kit will look for such test setup files under `/app/ui/tests`. Check out the [documentation](https://github.com/Shopify/sewing-kit/blob/main/docs/plugins/jest.md#smart-defaults) for more details.
|
106
106
|
|
107
107
|
##### Interacting with the request and response in React code
|
108
108
|
|
109
|
-
React-server sets up [@shopify/react-network](https://github.com/Shopify/quilt/blob/
|
109
|
+
React-server sets up [@shopify/react-network](https://github.com/Shopify/quilt/blob/main/packages/react-network) automatically, so most interactions with the request or response can be done from inside the React app.
|
110
110
|
|
111
111
|
##### Example: getting headers
|
112
112
|
|
@@ -131,7 +131,7 @@ function App() {
|
|
131
131
|
export default App;
|
132
132
|
```
|
133
133
|
|
134
|
-
**Note:** This solution works out of the box for initial server-side renders. If you wish to have consistent access to request headers on subsequent client-side renders, take a look at [`NetworkUniversalProvider`](https://github.com/Shopify/quilt/tree/
|
134
|
+
**Note:** This solution works out of the box for initial server-side renders. If you wish to have consistent access to request headers on subsequent client-side renders, take a look at [`NetworkUniversalProvider`](https://github.com/Shopify/quilt/tree/main/packages/react-network#networkuniversalprovider).
|
135
135
|
|
136
136
|
##### Example: sending custom headers from Rails controller
|
137
137
|
|
@@ -147,7 +147,7 @@ class ReactController < ApplicationController
|
|
147
147
|
end
|
148
148
|
```
|
149
149
|
|
150
|
-
🗒️ if you don't have a controller. Follow the [instruction](./docs/manual-installation#add-a-react-controller-and-routes) to setup `quilt_rails` in a controller instead of using the engine.
|
150
|
+
🗒️ if you don't have a controller. Follow the [instruction](./docs/manual-installation.md#option-2-add-a-react-controller-and-routes) to setup `quilt_rails` in a controller instead of using the engine.
|
151
151
|
|
152
152
|
Headers can be accessed during server-side-rendering with the `useRequestHeader` hook from `@shopify/react-network`.
|
153
153
|
|
@@ -183,7 +183,7 @@ class ReactController < ApplicationController
|
|
183
183
|
end
|
184
184
|
```
|
185
185
|
|
186
|
-
🗒️ if you don't have a controller. Follow the [instruction](./docs/manual-installation#add-a-react-controller-and-routes) to setup `quilt_rails` in a controller instead of using the engine.
|
186
|
+
🗒️ if you don't have a controller. Follow the [instruction](./docs/manual-installation.md#option-2-add-a-react-controller-and-routes) to setup `quilt_rails` in a controller instead of using the engine.
|
187
187
|
|
188
188
|
If using `react-server` without a customized server & client file, this will be automatically passed into your application as the `data` prop. If `react-server` is not being used or a customized server / client file was provided, check out [`react-server/webpack-plugin`](../../packages/react-server/src/webpack-plugin/webpack-plugin.ts) on how to pass the data to React.
|
189
189
|
|
@@ -222,9 +222,9 @@ export default App;
|
|
222
222
|
|
223
223
|
#### Isomorphic state
|
224
224
|
|
225
|
-
With SSR enabled React apps, state must be serialized on the server and deserialized on the client to keep it consistent. When using `@shopify/react-server`, the best tool for this job is [`@shopify/react-html`](https://github.com/Shopify/quilt/tree/
|
225
|
+
With SSR enabled React apps, state must be serialized on the server and deserialized on the client to keep it consistent. When using `@shopify/react-server`, the best tool for this job is [`@shopify/react-html`](https://github.com/Shopify/quilt/tree/main/packages/react-html)'s [`useSerialized`](https://github.com/Shopify/quilt/tree/main/packages/react-html#in-your-application-code) hook.
|
226
226
|
|
227
|
-
`useSerialized` can be used to implement [universal-providers](https://github.com/Shopify/quilt/tree/
|
227
|
+
`useSerialized` can be used to implement [universal-providers](https://github.com/Shopify/quilt/tree/main/packages/react-universal-provider#what-is-a-universal-provider-), allowing application code to manage what is persisted between the server and client without adding any custom code to client or server entrypoints. We offer some for common use cases such as [GraphQL](https://github.com/Shopify/quilt/tree/main/packages/react-graphql-universal-provider), and [I18n](https://github.com/Shopify/quilt/tree/main/packages/react-i18n-universal-provider).
|
228
228
|
|
229
229
|
#### Customizing the Node server
|
230
230
|
|
@@ -289,7 +289,7 @@ end
|
|
289
289
|
|
290
290
|
#### Exception monitoring with Bugsnag
|
291
291
|
|
292
|
-
For an opinionated universal Bugsnag+React setup we provide and support [`@shopify/react-bugsnag`](https://github.com/Shopify/quilt/tree/
|
292
|
+
For an opinionated universal Bugsnag+React setup we provide and support [`@shopify/react-bugsnag`](https://github.com/Shopify/quilt/tree/main/packages/react-bugsnag).
|
293
293
|
|
294
294
|
##### Example
|
295
295
|
|
data/Rakefile
CHANGED
@@ -8,9 +8,9 @@ module Quilt
|
|
8
8
|
def create
|
9
9
|
process_report
|
10
10
|
|
11
|
-
render
|
11
|
+
render(json: { result: 'success' }, status: 200)
|
12
12
|
rescue ActionController::ParameterMissing => error
|
13
|
-
render
|
13
|
+
render(json: { error: error.message, status: 422 })
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
@@ -3,9 +3,19 @@
|
|
3
3
|
module Quilt
|
4
4
|
class UiController < ApplicationController
|
5
5
|
include Quilt::ReactRenderable
|
6
|
+
layout(false)
|
6
7
|
|
7
8
|
def index
|
8
9
|
render_react
|
10
|
+
rescue Quilt::ReactRenderable::ReactServerNoResponseError
|
11
|
+
sleep(1)
|
12
|
+
retry if execution_count < 10
|
13
|
+
raise
|
14
|
+
end
|
15
|
+
|
16
|
+
def execution_count
|
17
|
+
@times ||= 0
|
18
|
+
@times = @times.next
|
9
19
|
end
|
10
20
|
end
|
11
21
|
end
|
@@ -12,7 +12,7 @@ module Quilt
|
|
12
12
|
if File.exist?(procfile_path)
|
13
13
|
append_file(procfile_path, File.read(File.expand_path(find_in_source_paths(procfile_path))))
|
14
14
|
else
|
15
|
-
copy_file
|
15
|
+
copy_file(procfile_path)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
@@ -20,12 +20,12 @@ module Quilt
|
|
20
20
|
routes_path = "config/routes.rb"
|
21
21
|
|
22
22
|
if File.exist?(routes_path)
|
23
|
-
route
|
23
|
+
route("mount Quilt::Engine, at: '/'")
|
24
24
|
else
|
25
|
-
copy_file
|
25
|
+
copy_file("routes.rb", routes_path)
|
26
26
|
end
|
27
27
|
|
28
|
-
say
|
28
|
+
say("Added Quilt engine mount")
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
data/lib/quilt_rails.rb
CHANGED
@@ -3,11 +3,12 @@ module Quilt
|
|
3
3
|
end
|
4
4
|
|
5
5
|
require "quilt_rails/version"
|
6
|
-
require "quilt_rails/engine"
|
7
6
|
require "quilt_rails/logger"
|
8
7
|
require "quilt_rails/configuration"
|
9
8
|
require "quilt_rails/react_renderable"
|
10
9
|
require "quilt_rails/performance"
|
11
10
|
require "quilt_rails/trusted_ui_server_csrf_strategy"
|
12
11
|
require "quilt_rails/header_csrf_strategy"
|
12
|
+
|
13
|
+
require "quilt_rails/engine"
|
13
14
|
require "quilt_rails/monkey_patches/active_support_reloader" if Rails.env.development?
|
@@ -1,23 +1,32 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
class Configuration
|
5
|
-
attr_accessor :react_server_host, :react_server_protocol
|
3
|
+
require "active_support/ordered_options"
|
6
4
|
|
5
|
+
module Quilt
|
6
|
+
class Configuration < ActiveSupport::OrderedOptions
|
7
7
|
def initialize
|
8
|
-
|
9
|
-
|
8
|
+
super
|
9
|
+
react_server_ip = ENV['REACT_SERVER_IP'] || "localhost"
|
10
|
+
react_server_port = ENV['REACT_SERVER_PORT'] || 8081
|
10
11
|
|
11
|
-
|
12
|
-
|
12
|
+
self.react_server_host = "#{react_server_ip}:#{react_server_port}"
|
13
|
+
self.react_server_protocol = ENV['REACT_SERVER_PROTOCOL'] || "http"
|
14
|
+
self.logger = ::Logger.new($stdout)
|
15
|
+
self.mount = true
|
13
16
|
end
|
14
|
-
end
|
15
17
|
|
16
|
-
|
17
|
-
|
18
|
+
def mount?
|
19
|
+
mount
|
20
|
+
end
|
18
21
|
end
|
19
22
|
|
20
|
-
|
21
|
-
|
23
|
+
class << self
|
24
|
+
def configuration
|
25
|
+
@configuration ||= Configuration.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def configure
|
29
|
+
yield(configuration)
|
30
|
+
end
|
22
31
|
end
|
23
32
|
end
|
data/lib/quilt_rails/engine.rb
CHANGED
@@ -3,5 +3,19 @@
|
|
3
3
|
module Quilt
|
4
4
|
class Engine < ::Rails::Engine
|
5
5
|
isolate_namespace Quilt
|
6
|
+
|
7
|
+
config.quilt = Quilt.configuration
|
8
|
+
|
9
|
+
initializer(:initialize_quilt_logger, after: :initialize_logger) do
|
10
|
+
config.quilt.logger = ::Rails.logger
|
11
|
+
end
|
12
|
+
|
13
|
+
initializer(:mount_quilt, before: :add_builtin_route) do |app|
|
14
|
+
if config.quilt.mount?
|
15
|
+
app.routes.append do
|
16
|
+
mount(Quilt::Engine, at: '/') unless has_named_route?(:quilt)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
6
20
|
end
|
7
21
|
end
|
@@ -25,9 +25,10 @@ module Quilt
|
|
25
25
|
|
26
26
|
class NoSameSiteHeaderError < StandardError
|
27
27
|
def initialize
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
super(<<~MSG.squish)
|
29
|
+
CSRF verification failed. This request is missing the
|
30
|
+
`x-shopify-react-xhr` header, or it does not have the expected value.
|
31
|
+
MSG
|
31
32
|
end
|
32
33
|
end
|
33
34
|
end
|
data/lib/quilt_rails/logger.rb
CHANGED
@@ -3,11 +3,14 @@
|
|
3
3
|
module Quilt
|
4
4
|
module Logger
|
5
5
|
def self.log(string)
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
6
|
+
ActiveSupport::Deprecation.warn(<<~MSG.squish)
|
7
|
+
Quilt::Logger.log is deprecated. Please use Quilt.logger instead.
|
8
|
+
MSG
|
9
|
+
Quilt.configuration.logger.info(string)
|
11
10
|
end
|
12
11
|
end
|
12
|
+
|
13
|
+
class << self
|
14
|
+
delegate(:logger, to: :configuration)
|
15
|
+
end
|
13
16
|
end
|
@@ -7,25 +7,39 @@ module Quilt
|
|
7
7
|
attr_accessor :navigations
|
8
8
|
attr_accessor :connection
|
9
9
|
|
10
|
-
|
11
|
-
params
|
12
|
-
|
10
|
+
class << self
|
11
|
+
def from_params(params)
|
12
|
+
params.transform_keys! { |key| key.underscore.to_sym }
|
13
|
+
params[:connection] = { effectiveType: 'unknown' } if params[:connection].blank?
|
13
14
|
|
14
|
-
|
15
|
+
connection = Connection.from_params(params[:connection])
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
Report.new(
|
18
|
+
connection: connection,
|
19
|
+
navigations: build_navigations(params[:navigations], connection: connection),
|
20
|
+
events: build_events(params[:events], connection: connection),
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def build_navigations(navigations_params, connection:)
|
27
|
+
navigations_params ||= []
|
28
|
+
navigations_params.map do |navigation|
|
19
29
|
navigation = Navigation.from_params(navigation)
|
20
30
|
navigation.connection = connection
|
21
31
|
navigation
|
22
|
-
end
|
23
|
-
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def build_events(events_params, connection:)
|
36
|
+
events_params ||= []
|
37
|
+
events_params.map do |event|
|
24
38
|
event = Event.from_params(event)
|
25
39
|
event.connection = connection
|
26
40
|
event
|
27
|
-
end
|
28
|
-
|
41
|
+
end
|
42
|
+
end
|
29
43
|
end
|
30
44
|
|
31
45
|
def initialize(events:, navigations:, connection:)
|
@@ -30,19 +30,19 @@ module Quilt
|
|
30
30
|
|
31
31
|
def proxy(headers, data)
|
32
32
|
url = "#{Quilt.configuration.react_server_protocol}://#{Quilt.configuration.react_server_host}"
|
33
|
-
Quilt
|
33
|
+
Quilt.logger.info("[ReactRenderable] proxying to React server at #{url}")
|
34
34
|
|
35
35
|
unless headers.blank?
|
36
|
-
Quilt
|
36
|
+
Quilt.logger.info("[ReactRenderable] applying custom headers #{headers.inspect}")
|
37
37
|
end
|
38
38
|
|
39
39
|
begin
|
40
40
|
reverse_proxy(
|
41
41
|
url,
|
42
|
-
headers: headers.merge('X-Quilt-Data': data.to_json)
|
42
|
+
headers: headers.merge('X-Request-ID': request.request_id, 'X-Quilt-Data': data.to_json)
|
43
43
|
) do |callbacks|
|
44
44
|
callbacks.on_response do |status_code, _response|
|
45
|
-
Quilt
|
45
|
+
Quilt.logger.info("[ReactRenderable] #{url} returned #{status_code}")
|
46
46
|
end
|
47
47
|
end
|
48
48
|
rescue Errno::ECONNREFUSED
|
@@ -52,17 +52,21 @@ module Quilt
|
|
52
52
|
|
53
53
|
class ReactServerNoResponseError < StandardError
|
54
54
|
def initialize(url)
|
55
|
-
|
56
|
-
|
57
|
-
|
55
|
+
super(<<~MSG.squish)
|
56
|
+
Connection refused while waiting for React server to boot up.
|
57
|
+
If this error persists, verify that @shopify/react-server is configured on #{url}.
|
58
|
+
MSG
|
58
59
|
end
|
59
60
|
end
|
60
61
|
|
61
62
|
class DoNotIntegrationTestError < StandardError
|
62
63
|
def initialize
|
63
|
-
|
64
|
-
|
65
|
-
|
64
|
+
super(<<~MSG.squish)
|
65
|
+
Please don't test React views with Ruby.
|
66
|
+
Jest and @shopify/react-testing should be used to test React components.
|
67
|
+
|
68
|
+
If you meant to query your Rails application, please check your integration test for errors.
|
69
|
+
MSG
|
66
70
|
end
|
67
71
|
end
|
68
72
|
end
|
data/lib/quilt_rails/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: quilt_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.2
|
4
|
+
version: 3.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mathew Allen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-02-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 3.2.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.2.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 3.2.0
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: rails-reverse-proxy
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -123,7 +137,7 @@ files:
|
|
123
137
|
- lib/quilt_rails/react_renderable.rb
|
124
138
|
- lib/quilt_rails/trusted_ui_server_csrf_strategy.rb
|
125
139
|
- lib/quilt_rails/version.rb
|
126
|
-
homepage: https://github.com/Shopify/quilt/tree/
|
140
|
+
homepage: https://github.com/Shopify/quilt/tree/main/gems/quilt_rails
|
127
141
|
licenses:
|
128
142
|
- MIT
|
129
143
|
metadata:
|