@tramvai/module-render 1.50.0 → 1.50.4
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.
- package/README.md +102 -116
- package/package.json +14 -14
package/README.md
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
# RenderModule
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Module for rendering React application on the server and in the browser
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Overview
|
|
6
6
|
|
|
7
|
-

|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Module contains the logic for generating HTML pages, starting from getting current page component, and finishing with the rendering result HTML using the `@tinkoff/htmlpagebuilder` library.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
This module includes code for creating top-level React component with all necessary providers composition, and page and layout components from the current route.
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## Installation
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
You need to install `@tramvai/module-render`
|
|
16
16
|
|
|
17
|
-
```bash
|
|
18
|
-
npm
|
|
17
|
+
```bash npm2yarn
|
|
18
|
+
npm install @tramvai/module-render
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
And connect to the project
|
|
22
22
|
|
|
23
23
|
```tsx
|
|
24
24
|
import { createApp } from '@tramvai/core';
|
|
@@ -32,25 +32,25 @@ createApp({
|
|
|
32
32
|
|
|
33
33
|
## Explanation
|
|
34
34
|
|
|
35
|
-
###
|
|
35
|
+
### Different React rendering modes
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
More information about rendering modes can be found in the [official documentation](https://reactjs.org/docs/concurrent-mode-adoption.html), `RenderModule` has support for all rendering types and you can choose the right one for your application.
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
To set the mode, you must pass the `mode` parameter when initializing the `RenderModule`.
|
|
40
40
|
|
|
41
41
|
```typescript
|
|
42
42
|
RenderModule.forRoot({ mode: 'concurrent' });
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
Available modes: `'legacy' | 'strict' | 'blocking' | 'concurrent'`
|
|
46
46
|
|
|
47
|
-
[
|
|
47
|
+
[Gradual concurrent mode adoption](#gradual-concurrent-mode-adoption)
|
|
48
48
|
|
|
49
|
-
###
|
|
49
|
+
### Application static assets
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
For static assets (JS, CSS, fonts, etc.) we create special resources registry module, which allow to provide in DI list of resources, and then render them to specifics slots in final HTML.
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
Example:
|
|
54
54
|
|
|
55
55
|
```typescript
|
|
56
56
|
createApp({
|
|
@@ -59,12 +59,12 @@ createApp({
|
|
|
59
59
|
multi: true,
|
|
60
60
|
useValue: [
|
|
61
61
|
{
|
|
62
|
-
type: ResourceType.inlineScript, // inlineScript
|
|
63
|
-
slot: ResourceSlot.HEAD_CORE_SCRIPTS, //
|
|
62
|
+
type: ResourceType.inlineScript, // inlineScript wrap payload in tag <script>
|
|
63
|
+
slot: ResourceSlot.HEAD_CORE_SCRIPTS, // define position where in HTML will be included resource
|
|
64
64
|
payload: 'alert("render")',
|
|
65
65
|
},
|
|
66
66
|
{
|
|
67
|
-
type: ResourceType.asIs, // asIs
|
|
67
|
+
type: ResourceType.asIs, // asIs just add payload as a string, without special processing
|
|
68
68
|
slot: ResourceSlot.BODY_TAIL,
|
|
69
69
|
payload: '<div>hello from render slots</div>',
|
|
70
70
|
},
|
|
@@ -74,13 +74,13 @@ createApp({
|
|
|
74
74
|
});
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
- **type** -
|
|
78
|
-
- **slot** -
|
|
79
|
-
- **payload** -
|
|
77
|
+
- **type** - presets for different resources types
|
|
78
|
+
- **slot** - slot in HTML where resource will be included
|
|
79
|
+
- **payload** - information that will be rendered
|
|
80
80
|
|
|
81
81
|
<p>
|
|
82
82
|
<details>
|
|
83
|
-
<summary
|
|
83
|
+
<summary>Available slots</summary>
|
|
84
84
|
|
|
85
85
|
@inline src/server/constants/slots.ts
|
|
86
86
|
|
|
@@ -89,29 +89,30 @@ createApp({
|
|
|
89
89
|
|
|
90
90
|
<p>
|
|
91
91
|
<details>
|
|
92
|
-
<summary
|
|
92
|
+
<summary>Layout of slots in the HTML page</summary>
|
|
93
93
|
|
|
94
94
|
@inline src/server/htmlPageSchema.ts
|
|
95
95
|
|
|
96
96
|
</details>
|
|
97
97
|
</p>
|
|
98
98
|
|
|
99
|
-
[
|
|
99
|
+
[How to add assets loading to a page](#How-to-add-assets-loading-to-a-page)
|
|
100
100
|
|
|
101
|
-
###
|
|
101
|
+
### Automatic resource inlining
|
|
102
102
|
|
|
103
|
-
####
|
|
103
|
+
#### Concept
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
A large number of resource files creates problems when loading the page, because the browser has to create a lot of connections to small files
|
|
106
106
|
|
|
107
|
-
####
|
|
107
|
+
#### Solution
|
|
108
108
|
|
|
109
|
-
|
|
109
|
+
To optimize page loading, we've added the ability to include some resources directly in the incoming HTML from the server.
|
|
110
|
+
To avoid inlining everything at all, we've added the ability to set an upper limit for file size.
|
|
110
111
|
|
|
111
|
-
####
|
|
112
|
+
#### Connection and configuration
|
|
112
113
|
|
|
113
|
-
|
|
114
|
-
|
|
114
|
+
Since version `0.60.7` inlining for styles is enabled by default, CSS files smaller than 40kb before gzip (+-10kb after gzip) are inlined.
|
|
115
|
+
To override these settings, add a provider specifying types of resources to be inlined (styles and/or scripts) and an upper limit for file size (in bytes, before gzip):
|
|
115
116
|
|
|
116
117
|
```js
|
|
117
118
|
import { RESOURCE_INLINE_OPTIONS } from '@tramvai/tokens-render';
|
|
@@ -121,61 +122,43 @@ import { provide } from '@tramvai/core';
|
|
|
121
122
|
provide({
|
|
122
123
|
provide: RESOURCE_INLINE_OPTIONS,
|
|
123
124
|
useValue: {
|
|
124
|
-
types: [ResourceType.script, ResourceType.style], //
|
|
125
|
+
types: [ResourceType.script, ResourceType.style], // Turn on for a CSS and JS files
|
|
125
126
|
threshold: 1024, // 1kb unzipped
|
|
126
127
|
},
|
|
127
128
|
}),
|
|
128
129
|
```
|
|
129
130
|
|
|
130
|
-
####
|
|
131
|
+
#### Peculiarities
|
|
131
132
|
|
|
132
|
-
|
|
133
|
+
All scripts and styles (depending on the settings) registered through the `ResourcesRegistry` are inlined.
|
|
133
134
|
|
|
134
|
-
|
|
135
|
+
File uploading to the server occurs in lazy mode, asynchronously.
|
|
136
|
+
This means that there will be no inlining when the page first loads.
|
|
137
|
+
It also means that there is no extra waiting for resources to load on the server side.
|
|
138
|
+
Once the file is in the cache it will be inline.
|
|
139
|
+
The cache has a TTL of 30 minutes and there is no resetting of the cache.
|
|
135
140
|
|
|
136
|
-
###
|
|
141
|
+
### Automatic resource preloading
|
|
137
142
|
|
|
138
|
-
|
|
143
|
+
To speed up data loading, we've added a preloading system for resources and asynchronous chunks, which works according to the following scenario:
|
|
139
144
|
|
|
140
|
-
-
|
|
141
|
-
-
|
|
142
|
-
-
|
|
145
|
+
- After rendering the application, we get information about all the CSS, JS bundles and asynchronous chunks used in the application
|
|
146
|
+
- Next we add all the CSS to the **preload** tag and add onload event on them. We need to load the blocking resources as quickly as possible.
|
|
147
|
+
- When loading any CSS file, onload event will be fired (only once time) and add all **preload** tags to the necessary JS files
|
|
143
148
|
|
|
144
|
-
|
|
149
|
+
### Basic layout
|
|
145
150
|
|
|
146
|
-
|
|
151
|
+
The `RenderModule` has a default basic layout that supports different ways of extending and adding functionality
|
|
147
152
|
|
|
148
|
-
|
|
149
|
-
const dashboard = () => require.ensure([], (require) => require('./bundles/dashboard'), 'dashboard');
|
|
150
|
-
bundles: {
|
|
151
|
-
'platform/mvno/dashboard': dashboard,
|
|
152
|
-
}
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
или если используете import
|
|
156
|
-
|
|
157
|
-
```
|
|
158
|
-
const dashboard = () => import(/* webpackChunkName: "dashboard" */ './bundles/dashboard');
|
|
159
|
-
bundles: {
|
|
160
|
-
'platform/mvno/dashboard': dashboard,
|
|
161
|
-
}
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
В примере выше, 'dashboard' и last('platform/mvno/dashboard'.split('/')) имеют одинаковое значение. Иначе мы не сможем на стороне сервера узнать, какой из списка чанков подходит в бандлу и подзагрузка произойдет только на стороне клиента.
|
|
165
|
-
|
|
166
|
-
### Базовый layout
|
|
153
|
+
[Read more about layout on the library page](references/libs/layout-factory.md)
|
|
167
154
|
|
|
168
|
-
|
|
155
|
+
#### Adding a basic header and footer
|
|
169
156
|
|
|
170
|
-
|
|
157
|
+
The module allows you to add header and footer components, which will be rendered by default for all pages
|
|
171
158
|
|
|
172
|
-
|
|
159
|
+
##### Via provider
|
|
173
160
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
##### Через провайдер
|
|
177
|
-
|
|
178
|
-
Зарегистрировать компоненты header и footer через провайдеры
|
|
161
|
+
Register header and footer components through providers:
|
|
179
162
|
|
|
180
163
|
```tsx
|
|
181
164
|
import { DEFAULT_HEADER_COMPONENT, DEFAULT_FOOTER_COMPONENT } from '@tramvai/tokens-render';
|
|
@@ -195,9 +178,9 @@ createApp({
|
|
|
195
178
|
});
|
|
196
179
|
```
|
|
197
180
|
|
|
198
|
-
#####
|
|
181
|
+
##### Via bundle
|
|
199
182
|
|
|
200
|
-
|
|
183
|
+
You can register a `headerDefault` and `footerDefault` component in the bundle, which will be rendered for all routes that do not have `headerComponent` and `footerComponent` redefined in configuration:
|
|
201
184
|
|
|
202
185
|
```tsx
|
|
203
186
|
createBundle({
|
|
@@ -209,9 +192,9 @@ createBundle({
|
|
|
209
192
|
});
|
|
210
193
|
```
|
|
211
194
|
|
|
212
|
-
####
|
|
195
|
+
#### Adding components and wrappers
|
|
213
196
|
|
|
214
|
-
|
|
197
|
+
You can add custom components and wrappers for layout via the token `LAYOUT_OPTIONS`
|
|
215
198
|
|
|
216
199
|
```tsx
|
|
217
200
|
import { provide } from '@tramvai/core';
|
|
@@ -221,17 +204,18 @@ import { provide } from '@tramvai/core';
|
|
|
221
204
|
provide: 'LAYOUT_OPTIONS',
|
|
222
205
|
multi: true,
|
|
223
206
|
useValue: {
|
|
224
|
-
//
|
|
207
|
+
// React components
|
|
225
208
|
components: {
|
|
226
|
-
//
|
|
209
|
+
// content component, this component wraps the header, page and footer
|
|
227
210
|
content: Content,
|
|
211
|
+
// page component
|
|
228
212
|
page: Page,
|
|
229
213
|
|
|
230
|
-
//
|
|
214
|
+
// any global components
|
|
231
215
|
alerts: Alerts,
|
|
232
216
|
feedback: Feedback,
|
|
233
217
|
},
|
|
234
|
-
// HOC
|
|
218
|
+
// HOC's for components
|
|
235
219
|
wrappers: {
|
|
236
220
|
layout: layoutWrapper,
|
|
237
221
|
alerts: [alertWrapper1, alertWrapper2],
|
|
@@ -243,17 +227,19 @@ import { provide } from '@tramvai/core';
|
|
|
243
227
|
export class MyLayoutModule {}
|
|
244
228
|
```
|
|
245
229
|
|
|
246
|
-
|
|
230
|
+
More details about the `components` and `wrappers` options can be found in [@tinkoff/layout-factory](references/libs/layout-factory.md)
|
|
247
231
|
|
|
248
|
-
####
|
|
232
|
+
#### Replacing the basic layout
|
|
249
233
|
|
|
250
|
-
|
|
234
|
+
If the basic layout doesn't work for you, you can replace it with any other React component.
|
|
235
|
+
In doing so, you need to implement all the wrappers yourself and plug in global components if you need them.
|
|
251
236
|
|
|
252
|
-
|
|
237
|
+
You can replace it in two ways:
|
|
253
238
|
|
|
254
|
-
#####
|
|
239
|
+
##### Add layoutComponent to route
|
|
255
240
|
|
|
256
|
-
|
|
241
|
+
You can add a `layoutComponent` property to route `config` and register component in `bundle`.
|
|
242
|
+
This layout will be rendered when you go to the corresponding route.
|
|
257
243
|
|
|
258
244
|
```tsx
|
|
259
245
|
createBundle({
|
|
@@ -264,9 +250,9 @@ createBundle({
|
|
|
264
250
|
});
|
|
265
251
|
```
|
|
266
252
|
|
|
267
|
-
#####
|
|
253
|
+
##### Replace layoutDefault
|
|
268
254
|
|
|
269
|
-
|
|
255
|
+
You can register a `layoutDefault` component in `bundle`, which will be automatically rendered for all routes that do not have an `layoutComponent` in `config` property.
|
|
270
256
|
|
|
271
257
|
```tsx
|
|
272
258
|
createBundle({
|
|
@@ -279,79 +265,79 @@ createBundle({
|
|
|
279
265
|
|
|
280
266
|
## How to
|
|
281
267
|
|
|
282
|
-
###
|
|
268
|
+
### How to add assets loading to a page
|
|
283
269
|
|
|
284
|
-
|
|
270
|
+
There are 2 main ways how you can add resources to your application
|
|
285
271
|
|
|
286
|
-
-
|
|
287
|
-
-
|
|
272
|
+
- The `RENDER_SLOTS` token, where you can pass a list of resources, such as HTML markup, inline scripts, script tag
|
|
273
|
+
- Token `RESOURCES_REGISTRY` to get the resource manager, and register the desired resources manually
|
|
288
274
|
|
|
289
|
-
|
|
275
|
+
Example:
|
|
290
276
|
|
|
291
277
|
<p>
|
|
292
278
|
<details>
|
|
293
|
-
<summary
|
|
279
|
+
<summary>Application example</summary>
|
|
294
280
|
|
|
295
281
|
@inline ../../../examples/how-to/render-add-resources/index.tsx
|
|
296
282
|
|
|
297
283
|
</details>
|
|
298
284
|
</p>
|
|
299
285
|
|
|
300
|
-
###
|
|
286
|
+
### Gradual concurrent mode adoption
|
|
301
287
|
|
|
302
|
-
React
|
|
288
|
+
React allows a gradual migration of an application
|
|
303
289
|
|
|
304
|
-
|
|
290
|
+
**Stages of migration:**
|
|
305
291
|
|
|
306
|
-
1. [Strict Mode](https://reactjs.org/docs/strict-mode.html) -
|
|
292
|
+
1. [Strict Mode](https://reactjs.org/docs/strict-mode.html) - strict mode, in which React warns about using the legacy API
|
|
307
293
|
|
|
308
|
-
|
|
294
|
+
To connect, you must configure the `RenderModule`
|
|
309
295
|
|
|
310
|
-
```
|
|
296
|
+
```js
|
|
311
297
|
modules: [
|
|
312
298
|
RenderModule.forRoot({ mode: 'strict' })
|
|
313
299
|
]
|
|
314
300
|
```
|
|
315
301
|
|
|
316
|
-
|
|
302
|
+
Then you need to fix any new warnings, such as using legacy lifecycle methods and string refs.
|
|
317
303
|
|
|
318
|
-
2. [Blocking Mode](https://reactjs.org/docs/concurrent-mode-adoption.html#migration-step-blocking-mode) -
|
|
304
|
+
2. [Blocking Mode](https://reactjs.org/docs/concurrent-mode-adoption.html#migration-step-blocking-mode) - adds some Concurrent Mode features, such as Suspense on the server. Suitable for gradual migration to Concurrent Mode.
|
|
319
305
|
|
|
320
|
-
|
|
306
|
+
To connect, install an experimental version of React and configure the `RenderModule`
|
|
321
307
|
|
|
322
|
-
```bash
|
|
308
|
+
```bash npm2yarn
|
|
323
309
|
npm install react@experimental react-dom@experimental
|
|
324
310
|
```
|
|
325
311
|
|
|
326
|
-
```
|
|
312
|
+
```js
|
|
327
313
|
modules: [
|
|
328
314
|
RenderModule.forRoot({ mode: 'blocking' })
|
|
329
315
|
]
|
|
330
316
|
```
|
|
331
317
|
|
|
332
|
-
|
|
318
|
+
At this stage, you need to check the performance of the application, and you can try new APIs, for example [SuspenseList](https://reactjs.org/docs/concurrent-mode-patterns.html#suspenselist)
|
|
333
319
|
|
|
334
320
|
3. Concurrent Mode
|
|
335
321
|
|
|
336
|
-
|
|
322
|
+
To connect, install an experimental version of React and configure the `RenderModule`
|
|
337
323
|
|
|
338
|
-
```bash
|
|
324
|
+
```bash npm2yarn
|
|
339
325
|
npm install react@experimental react-dom@experimental
|
|
340
326
|
```
|
|
341
327
|
|
|
342
|
-
```
|
|
328
|
+
```js
|
|
343
329
|
modules: [
|
|
344
330
|
RenderModule.forRoot({ mode: 'concurrent' })
|
|
345
331
|
]
|
|
346
332
|
```
|
|
347
333
|
|
|
348
|
-
|
|
334
|
+
At this stage, you need to check the performance of the application, and you can try new APIs, for example [useTransition](https://reactjs.org/docs/concurrent-mode-patterns.html#transitions)
|
|
349
335
|
|
|
350
|
-
###
|
|
336
|
+
### Testing
|
|
351
337
|
|
|
352
|
-
####
|
|
338
|
+
#### Testing render extensions via RENDER_SLOTS or RESOURCES_REGISTRY tokens
|
|
353
339
|
|
|
354
|
-
|
|
340
|
+
If you have a module or providers that define `RENDER_SLOTS` or use `RESOURCES_REGISTRY`, it is convenient to use special utilities to test them separately
|
|
355
341
|
|
|
356
342
|
```ts
|
|
357
343
|
import {
|
|
@@ -401,6 +387,6 @@ describe('testPageResources', () => {
|
|
|
401
387
|
});
|
|
402
388
|
```
|
|
403
389
|
|
|
404
|
-
##
|
|
390
|
+
## Exported tokens
|
|
405
391
|
|
|
406
|
-
[
|
|
392
|
+
[link](references/tokens/render-tokens.md)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tramvai/module-render",
|
|
3
|
-
"version": "1.50.
|
|
3
|
+
"version": "1.50.4",
|
|
4
4
|
"description": "",
|
|
5
5
|
"browser": "lib/browser.js",
|
|
6
6
|
"main": "lib/server.js",
|
|
@@ -24,26 +24,26 @@
|
|
|
24
24
|
"@tinkoff/htmlpagebuilder": "0.4.22",
|
|
25
25
|
"@tinkoff/layout-factory": "0.2.28",
|
|
26
26
|
"@tinkoff/url": "0.7.37",
|
|
27
|
-
"@tinkoff/user-agent": "0.3.
|
|
28
|
-
"@tramvai/module-client-hints": "1.50.
|
|
29
|
-
"@tramvai/module-router": "1.50.
|
|
30
|
-
"@tramvai/react": "1.50.
|
|
27
|
+
"@tinkoff/user-agent": "0.3.216",
|
|
28
|
+
"@tramvai/module-client-hints": "1.50.4",
|
|
29
|
+
"@tramvai/module-router": "1.50.4",
|
|
30
|
+
"@tramvai/react": "1.50.4",
|
|
31
31
|
"@tramvai/safe-strings": "0.4.3",
|
|
32
|
-
"@tramvai/tokens-render": "1.50.
|
|
33
|
-
"@tramvai/experiments": "1.50.
|
|
32
|
+
"@tramvai/tokens-render": "1.50.4",
|
|
33
|
+
"@tramvai/experiments": "1.50.4",
|
|
34
34
|
"@types/loadable__server": "^5.12.6",
|
|
35
35
|
"node-fetch": "^2.6.1"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"@tinkoff/dippy": "0.7.36",
|
|
39
39
|
"@tinkoff/utils": "^2.1.2",
|
|
40
|
-
"@tramvai/cli": "1.50.
|
|
41
|
-
"@tramvai/core": "1.50.
|
|
42
|
-
"@tramvai/module-common": "1.50.
|
|
43
|
-
"@tramvai/state": "1.50.
|
|
44
|
-
"@tramvai/test-helpers": "1.50.
|
|
45
|
-
"@tramvai/tokens-common": "1.50.
|
|
46
|
-
"@tramvai/tokens-router": "1.50.
|
|
40
|
+
"@tramvai/cli": "1.50.4",
|
|
41
|
+
"@tramvai/core": "1.50.4",
|
|
42
|
+
"@tramvai/module-common": "1.50.4",
|
|
43
|
+
"@tramvai/state": "1.50.4",
|
|
44
|
+
"@tramvai/test-helpers": "1.50.4",
|
|
45
|
+
"@tramvai/tokens-common": "1.50.4",
|
|
46
|
+
"@tramvai/tokens-router": "1.50.4",
|
|
47
47
|
"prop-types": "^15.6.2",
|
|
48
48
|
"react": ">=16.8.0",
|
|
49
49
|
"react-dom": ">=16.8.0",
|