@tramvai/module-render 1.79.0 → 1.81.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.
- package/README.md +10 -50
- package/lib/browser.d.ts +1 -1
- package/lib/browser.js +65 -67
- package/lib/client/index.d.ts +4 -4
- package/lib/client/renderer.d.ts +3 -0
- package/lib/shared/types.d.ts +5 -0
- package/package.json +16 -15
- package/lib/client/concurrent.d.ts +0 -4
- package/lib/client/legacy.d.ts +0 -3
- package/lib/client/strict.d.ts +0 -3
package/README.md
CHANGED
|
@@ -32,20 +32,16 @@ createApp({
|
|
|
32
32
|
|
|
33
33
|
## Explanation
|
|
34
34
|
|
|
35
|
-
###
|
|
35
|
+
### React Strict Mode
|
|
36
36
|
|
|
37
|
-
More information about
|
|
37
|
+
More information about Strict Mode can be found in the [official documentation](https://reactjs.org/docs/strict-mode.html).
|
|
38
38
|
|
|
39
|
-
To set the mode, you must pass the `
|
|
39
|
+
To set the mode, you must pass the `useStrictMode` parameter when initializing the `RenderModule`.
|
|
40
40
|
|
|
41
41
|
```typescript
|
|
42
|
-
RenderModule.forRoot({
|
|
42
|
+
RenderModule.forRoot({ useStrictMode: true });
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
Available modes: `'legacy' | 'strict' | 'blocking' | 'concurrent'`
|
|
46
|
-
|
|
47
|
-
[Gradual concurrent mode adoption](#gradual-concurrent-mode-adoption)
|
|
48
|
-
|
|
49
45
|
### Application static assets
|
|
50
46
|
|
|
51
47
|
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.
|
|
@@ -283,56 +279,20 @@ Example:
|
|
|
283
279
|
</details>
|
|
284
280
|
</p>
|
|
285
281
|
|
|
286
|
-
###
|
|
287
|
-
|
|
288
|
-
React allows a gradual migration of an application
|
|
289
|
-
|
|
290
|
-
**Stages of migration:**
|
|
291
|
-
|
|
292
|
-
1. [Strict Mode](https://reactjs.org/docs/strict-mode.html) - strict mode, in which React warns about using the legacy API
|
|
293
|
-
|
|
294
|
-
To connect, you must configure the `RenderModule`
|
|
295
|
-
|
|
296
|
-
```js
|
|
297
|
-
modules: [
|
|
298
|
-
RenderModule.forRoot({ mode: 'strict' })
|
|
299
|
-
]
|
|
300
|
-
```
|
|
282
|
+
### React 18 concurrent features
|
|
301
283
|
|
|
302
|
-
|
|
284
|
+
`tramvai` will automatically detect React version, and use hydrateRoot API on the client for 18+ version.
|
|
303
285
|
|
|
304
|
-
|
|
286
|
+
Before switch to React 18, we recommended to activate [Strict Mode](https://reactjs.org/docs/strict-mode.html) in your application.
|
|
287
|
+
In Strict Mode which React warns about using the legacy API.
|
|
305
288
|
|
|
306
|
-
To connect,
|
|
307
|
-
|
|
308
|
-
```bash npm2yarn
|
|
309
|
-
npm install react@experimental react-dom@experimental
|
|
310
|
-
```
|
|
289
|
+
To connect, you must configure the `RenderModule`:
|
|
311
290
|
|
|
312
291
|
```js
|
|
313
292
|
modules: [
|
|
314
|
-
RenderModule.forRoot({
|
|
293
|
+
RenderModule.forRoot({ useStrictMode: true })
|
|
315
294
|
]
|
|
316
295
|
```
|
|
317
|
-
|
|
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)
|
|
319
|
-
|
|
320
|
-
3. Concurrent Mode
|
|
321
|
-
|
|
322
|
-
To connect, install an experimental version of React and configure the `RenderModule`
|
|
323
|
-
|
|
324
|
-
```bash npm2yarn
|
|
325
|
-
npm install react@experimental react-dom@experimental
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
```js
|
|
329
|
-
modules: [
|
|
330
|
-
RenderModule.forRoot({ mode: 'concurrent' })
|
|
331
|
-
]
|
|
332
|
-
```
|
|
333
|
-
|
|
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)
|
|
335
|
-
|
|
336
296
|
### Testing
|
|
337
297
|
|
|
338
298
|
#### Testing render extensions via RENDER_SLOTS or RESOURCES_REGISTRY tokens
|
package/lib/browser.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export * from './shared/pageErrorStore';
|
|
|
3
3
|
export * from '@tramvai/tokens-render';
|
|
4
4
|
export declare const DEFAULT_POLYFILL_CONDITION = "";
|
|
5
5
|
export declare class RenderModule {
|
|
6
|
-
static forRoot({ mode }: RenderModuleConfig): {
|
|
6
|
+
static forRoot({ mode, useStrictMode }: RenderModuleConfig): {
|
|
7
7
|
mainModule: typeof RenderModule;
|
|
8
8
|
providers: any[];
|
|
9
9
|
};
|
package/lib/browser.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { __decorate } from 'tslib';
|
|
2
2
|
import { Module, provide, commandLineListTokens, DI_TOKEN } from '@tramvai/core';
|
|
3
3
|
import { STORE_TOKEN, LOGGER_TOKEN, CONTEXT_TOKEN } from '@tramvai/module-common';
|
|
4
|
-
import { DEFAULT_LAYOUT_COMPONENT, LAYOUT_OPTIONS, DEFAULT_FOOTER_COMPONENT, DEFAULT_HEADER_COMPONENT, TRAMVAI_RENDER_MODE, RESOURCES_REGISTRY, CUSTOM_RENDER, EXTEND_RENDER, RENDERER_CALLBACK, RENDER_MODE } from '@tramvai/tokens-render';
|
|
4
|
+
import { DEFAULT_LAYOUT_COMPONENT, LAYOUT_OPTIONS, DEFAULT_FOOTER_COMPONENT, DEFAULT_HEADER_COMPONENT, TRAMVAI_RENDER_MODE, RESOURCES_REGISTRY, CUSTOM_RENDER, EXTEND_RENDER, RENDERER_CALLBACK, USE_REACT_STRICT_MODE, RENDER_MODE } from '@tramvai/tokens-render';
|
|
5
5
|
export * from '@tramvai/tokens-render';
|
|
6
6
|
import { ROUTER_TOKEN, PAGE_SERVICE_TOKEN } from '@tramvai/tokens-router';
|
|
7
7
|
import each from '@tinkoff/utils/array/each';
|
|
8
|
-
import React, { PureComponent, useMemo, createElement, StrictMode
|
|
8
|
+
import React, { PureComponent, useMemo, createElement, StrictMode } from 'react';
|
|
9
9
|
import { createEvent, createReducer, useStore, Provider } from '@tramvai/state';
|
|
10
10
|
import { useDi, ERROR_BOUNDARY_TOKEN, ERROR_BOUNDARY_FALLBACK_COMPONENT_TOKEN, UniversalErrorBoundary, DIContext } from '@tramvai/react';
|
|
11
11
|
import { useRoute, useUrl } from '@tramvai/module-router';
|
|
12
|
-
import
|
|
12
|
+
import { useIsomorphicLayoutEffect } from '@tinkoff/react-hooks';
|
|
13
13
|
import { composeLayoutOptions, createLayout } from '@tinkoff/layout-factory';
|
|
14
14
|
import { COMBINE_REDUCERS } from '@tramvai/tokens-common';
|
|
15
15
|
|
|
@@ -72,76 +72,62 @@ function renderReact({ pageService, di }, context) {
|
|
|
72
72
|
React.createElement(Root, { pageService: pageService }))));
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
const legacyRenderer = ({ element, container, callback }) => hydrate(element, container, callback);
|
|
76
|
-
|
|
77
|
-
const strictRenderer = (params) => {
|
|
78
|
-
const element = createElement(StrictMode, null, params.element);
|
|
79
|
-
return legacyRenderer({ ...params, element });
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
const WARNING_TEXT = '\n--->\n-->\n->\nInstall experemental version of React and ReactDOM for blocking and concurrent modes!\n->\n-->\n--->';
|
|
83
75
|
const ExecuteRenderCallback = ({ children, callback }) => {
|
|
84
76
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
85
|
-
|
|
77
|
+
useIsomorphicLayoutEffect(callback, []);
|
|
86
78
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
87
79
|
return children;
|
|
88
80
|
};
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
81
|
+
const renderer = ({ element, container, callback }) => {
|
|
82
|
+
if (process.env.__TRAMVAI_CONCURRENT_FEATURES) {
|
|
83
|
+
const wrappedElement = createElement(ExecuteRenderCallback, { callback }, element);
|
|
84
|
+
// eslint-disable-next-line import/no-unresolved, import/extensions
|
|
85
|
+
const { hydrateRoot } = require('react-dom/client');
|
|
86
|
+
return hydrateRoot(container, wrappedElement);
|
|
93
87
|
}
|
|
94
|
-
const
|
|
95
|
-
return
|
|
88
|
+
const { hydrate } = require('react-dom');
|
|
89
|
+
return hydrate(element, container, callback);
|
|
96
90
|
};
|
|
97
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
98
|
-
const blockingRenderer = rendererFactory(ReactDOM.createBlockingRoot);
|
|
99
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
100
|
-
const concurrentRenderer = rendererFactory(ReactDOM.createRoot);
|
|
101
91
|
|
|
102
|
-
function rendering({ pageService, log, consumerContext, customRender, extendRender, di,
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
92
|
+
function rendering({ pageService, log, consumerContext, customRender, extendRender, di, useStrictMode, rendererCallback, }) {
|
|
93
|
+
return new Promise((resolve, reject) => {
|
|
94
|
+
let renderResult = renderReact({ pageService, di }, consumerContext);
|
|
95
|
+
if (extendRender) {
|
|
96
|
+
each((render) => {
|
|
97
|
+
renderResult = render(renderResult);
|
|
98
|
+
}, extendRender);
|
|
99
|
+
}
|
|
100
|
+
if (customRender) {
|
|
101
|
+
return customRender(renderResult);
|
|
102
|
+
}
|
|
103
|
+
if (useStrictMode) {
|
|
104
|
+
renderResult = createElement(StrictMode, null, renderResult);
|
|
105
|
+
}
|
|
106
|
+
const container = document.querySelector('.application');
|
|
107
|
+
const executeRendererCallbacks = (renderErr) => rendererCallback === null || rendererCallback === void 0 ? void 0 : rendererCallback.forEach((cb) => {
|
|
108
|
+
try {
|
|
109
|
+
cb(renderErr);
|
|
110
|
+
}
|
|
111
|
+
catch (cbError) {
|
|
112
|
+
// eslint-disable-next-line no-console
|
|
113
|
+
console.error(cbError);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
const callback = () => {
|
|
117
|
+
log.debug('App rendering');
|
|
118
|
+
document.querySelector('html').classList.remove('no-js');
|
|
119
|
+
executeRendererCallbacks();
|
|
120
|
+
resolve();
|
|
121
|
+
};
|
|
122
|
+
const params = { element: renderResult, container, callback, log };
|
|
114
123
|
try {
|
|
115
|
-
|
|
124
|
+
renderer(params);
|
|
116
125
|
}
|
|
117
|
-
catch (
|
|
118
|
-
|
|
119
|
-
|
|
126
|
+
catch (e) {
|
|
127
|
+
executeRendererCallbacks(e);
|
|
128
|
+
reject(e);
|
|
120
129
|
}
|
|
121
130
|
});
|
|
122
|
-
const callback = () => {
|
|
123
|
-
log.debug('App rendering');
|
|
124
|
-
document.querySelector('html').classList.remove('no-js');
|
|
125
|
-
executeRendererCallbacks();
|
|
126
|
-
};
|
|
127
|
-
const params = { element: renderResult, container, callback, log };
|
|
128
|
-
try {
|
|
129
|
-
switch (mode) {
|
|
130
|
-
case 'strict':
|
|
131
|
-
return strictRenderer(params);
|
|
132
|
-
case 'blocking':
|
|
133
|
-
return blockingRenderer(params);
|
|
134
|
-
case 'concurrent':
|
|
135
|
-
return concurrentRenderer(params);
|
|
136
|
-
case 'legacy':
|
|
137
|
-
default:
|
|
138
|
-
return legacyRenderer(params);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
catch (e) {
|
|
142
|
-
executeRendererCallbacks(e);
|
|
143
|
-
throw e;
|
|
144
|
-
}
|
|
145
131
|
}
|
|
146
132
|
|
|
147
133
|
let LayoutModule = class LayoutModule {
|
|
@@ -193,12 +179,12 @@ const throwErrorInDev = (logger) => {
|
|
|
193
179
|
}
|
|
194
180
|
};
|
|
195
181
|
let RenderModule = RenderModule_1 = class RenderModule {
|
|
196
|
-
static forRoot({ mode }) {
|
|
182
|
+
static forRoot({ mode, useStrictMode }) {
|
|
197
183
|
const providers = [];
|
|
198
|
-
if (typeof mode === 'string') {
|
|
184
|
+
if (typeof mode === 'string' || typeof useStrictMode === 'boolean') {
|
|
199
185
|
providers.push({
|
|
200
|
-
provide:
|
|
201
|
-
useValue: mode,
|
|
186
|
+
provide: USE_REACT_STRICT_MODE,
|
|
187
|
+
useValue: useStrictMode !== null && useStrictMode !== void 0 ? useStrictMode : mode === 'strict',
|
|
202
188
|
});
|
|
203
189
|
}
|
|
204
190
|
return {
|
|
@@ -247,7 +233,7 @@ RenderModule = RenderModule_1 = __decorate([
|
|
|
247
233
|
useFactory: (deps) => {
|
|
248
234
|
return function renderClientCommand() {
|
|
249
235
|
window.contextExternal = deps.consumerContext;
|
|
250
|
-
return
|
|
236
|
+
return rendering(deps);
|
|
251
237
|
};
|
|
252
238
|
},
|
|
253
239
|
deps: {
|
|
@@ -258,10 +244,22 @@ RenderModule = RenderModule_1 = __decorate([
|
|
|
258
244
|
rendererCallback: { token: RENDERER_CALLBACK, optional: true },
|
|
259
245
|
consumerContext: CONTEXT_TOKEN,
|
|
260
246
|
di: DI_TOKEN,
|
|
261
|
-
|
|
247
|
+
useStrictMode: USE_REACT_STRICT_MODE,
|
|
262
248
|
},
|
|
263
249
|
multi: true,
|
|
264
250
|
}),
|
|
251
|
+
provide({
|
|
252
|
+
provide: USE_REACT_STRICT_MODE,
|
|
253
|
+
useFactory: ({ deprecatedMode }) => {
|
|
254
|
+
if (deprecatedMode === 'strict') {
|
|
255
|
+
return true;
|
|
256
|
+
}
|
|
257
|
+
return false;
|
|
258
|
+
},
|
|
259
|
+
deps: {
|
|
260
|
+
deprecatedMode: RENDER_MODE,
|
|
261
|
+
},
|
|
262
|
+
}),
|
|
265
263
|
provide({
|
|
266
264
|
provide: RENDER_MODE,
|
|
267
265
|
useValue: 'legacy',
|
package/lib/client/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import type { EXTEND_RENDER,
|
|
1
|
+
import type { EXTEND_RENDER, RENDERER_CALLBACK, USE_REACT_STRICT_MODE } from '@tramvai/tokens-render';
|
|
2
2
|
import type { PAGE_SERVICE_TOKEN } from '@tramvai/tokens-router';
|
|
3
|
-
export declare function rendering({ pageService, log, consumerContext, customRender, extendRender, di,
|
|
3
|
+
export declare function rendering({ pageService, log, consumerContext, customRender, extendRender, di, useStrictMode, rendererCallback, }: {
|
|
4
4
|
pageService: typeof PAGE_SERVICE_TOKEN;
|
|
5
5
|
log: any;
|
|
6
6
|
consumerContext: any;
|
|
7
7
|
extendRender?: typeof EXTEND_RENDER;
|
|
8
8
|
customRender?: any;
|
|
9
9
|
di: any;
|
|
10
|
-
|
|
10
|
+
useStrictMode: typeof USE_REACT_STRICT_MODE;
|
|
11
11
|
rendererCallback?: typeof RENDERER_CALLBACK;
|
|
12
|
-
}):
|
|
12
|
+
}): Promise<void>;
|
package/lib/shared/types.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
declare type RenderModuleConfig = {
|
|
2
2
|
polyfillCondition?: string;
|
|
3
|
+
/**
|
|
4
|
+
* @deprecated tramvai will automatically detect React version, and use hydrateRoot API for 18+ version
|
|
5
|
+
* For Strict Mode, use options `useStrictMode`
|
|
6
|
+
*/
|
|
3
7
|
mode?: 'legacy' | 'strict' | 'blocking' | 'concurrent';
|
|
8
|
+
useStrictMode?: boolean;
|
|
4
9
|
};
|
|
5
10
|
export { RenderModuleConfig };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tramvai/module-render",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.81.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"browser": "lib/browser.js",
|
|
6
6
|
"main": "lib/server.js",
|
|
@@ -24,27 +24,28 @@
|
|
|
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.
|
|
29
|
-
"@tramvai/module-router": "1.
|
|
30
|
-
"@tramvai/react": "1.
|
|
27
|
+
"@tinkoff/user-agent": "0.3.281",
|
|
28
|
+
"@tramvai/module-client-hints": "1.81.0",
|
|
29
|
+
"@tramvai/module-router": "1.81.0",
|
|
30
|
+
"@tramvai/react": "1.81.0",
|
|
31
31
|
"@tramvai/safe-strings": "0.4.3",
|
|
32
|
-
"@tramvai/tokens-render": "1.
|
|
33
|
-
"@tramvai/experiments": "1.
|
|
32
|
+
"@tramvai/tokens-render": "1.81.0",
|
|
33
|
+
"@tramvai/experiments": "1.81.0",
|
|
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.39",
|
|
39
39
|
"@tinkoff/utils": "^2.1.2",
|
|
40
|
-
"@
|
|
41
|
-
"@tramvai/
|
|
42
|
-
"@tramvai/
|
|
43
|
-
"@tramvai/
|
|
44
|
-
"@tramvai/
|
|
45
|
-
"@tramvai/
|
|
46
|
-
"@tramvai/tokens-
|
|
47
|
-
"@tramvai/tokens-
|
|
40
|
+
"@tinkoff/react-hooks": "0.0.24",
|
|
41
|
+
"@tramvai/cli": "1.81.0",
|
|
42
|
+
"@tramvai/core": "1.81.0",
|
|
43
|
+
"@tramvai/module-common": "1.81.0",
|
|
44
|
+
"@tramvai/state": "1.81.0",
|
|
45
|
+
"@tramvai/test-helpers": "1.81.0",
|
|
46
|
+
"@tramvai/tokens-common": "1.81.0",
|
|
47
|
+
"@tramvai/tokens-router": "1.81.0",
|
|
48
|
+
"@tramvai/tokens-server": "1.81.0",
|
|
48
49
|
"express": "^4.17.1",
|
|
49
50
|
"prop-types": "^15.6.2",
|
|
50
51
|
"react": ">=16.8.0",
|
package/lib/client/legacy.d.ts
DELETED
package/lib/client/strict.d.ts
DELETED