@tramvai/module-page-render-mode 2.27.0 → 2.29.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 CHANGED
@@ -9,9 +9,27 @@ Enable different rendering modes for specific pages:
9
9
  - `client`
10
10
 
11
11
  Client mode - render only fallback for page component, then render full page on browser, after hydration.
12
+
12
13
  This mode can significally improve server rendering performance, but not recommended for pages with high SEO impact.
14
+
13
15
  By default, Header and Footer will be rendered as usual.
14
16
 
17
+ - `static`
18
+
19
+ Static mode - in-memory cache for page HTML markup.
20
+
21
+ Response for first request for specific page, without `Cookie` header, will be cached directly, and sended as response to next requests for this page. Otherwise, unpersonalized request for the same page will be triggered at background, and result will be cached.
22
+
23
+ 5xx responses will not be cached by default, but this behaviour are configurable.
24
+
25
+ Any responses from cache will have `X-Tramvai-Static-Page-From-Cache` header.
26
+
27
+ Additional metric with name `static_pages_cache_hit` will be added with cache hits counter.
28
+
29
+ Response from cache will be sended from `customer_start` command line, and next lines execution will be aborted.
30
+
31
+ Cache will be segmented by page path and method, request hostname, device type and browser (modern or default group).
32
+
15
33
  ## Installation
16
34
 
17
35
  You need to install `@tramvai/module-page-render-mode`
@@ -28,7 +46,7 @@ import { PageRenderModeModule } from '@tramvai/module-page-render-mode';
28
46
 
29
47
  createApp({
30
48
  name: 'tincoin',
31
- modules: [ PageRenderModeModule ],
49
+ modules: [PageRenderModeModule],
32
50
  });
33
51
  ```
34
52
 
@@ -36,8 +54,7 @@ createApp({
36
54
 
37
55
  ### Rendering mode
38
56
 
39
- By default, this module connection has no changes, because default rendering mode is `ssr`.
40
- You can change this mode for all pages or for specific pages only.
57
+ By default, this module connection has no changes, because default rendering mode is `ssr`. You can change this mode for all pages or for specific pages only.
41
58
 
42
59
  #### Default mode
43
60
 
@@ -69,7 +86,7 @@ For specific pages available two options:
69
86
  pageRenderMode: 'client',
70
87
  },
71
88
  },
72
- ]
89
+ ];
73
90
  ```
74
91
 
75
92
  - setting mode in page component static property:
@@ -84,8 +101,7 @@ For specific pages available two options:
84
101
 
85
102
  ### Fallback
86
103
 
87
- Standard behaviour for SPA applications - render some fallback with spinner or page skeleton before application was rendered.
88
- You can set default fallback for all pages with `client` render mode, or only for specific pages.
104
+ Standard behaviour for SPA applications - render some fallback with spinner or page skeleton before application was rendered. You can set default fallback for all pages with `client` render mode, or only for specific pages.
89
105
 
90
106
  #### Default fallback
91
107
 
@@ -102,7 +118,6 @@ const provider = {
102
118
  };
103
119
  ```
104
120
 
105
-
106
121
  #### Fallback for specific pages
107
122
 
108
123
  For specific pages available few options:
@@ -117,7 +132,7 @@ For specific pages available few options:
117
132
  const PageFallback = () => <div>Loading...</div>;
118
133
 
119
134
  Page.components = {
120
- 'pageRenderFallbackDefault': PageFallback,
135
+ pageRenderFallbackDefault: PageFallback,
121
136
  };
122
137
 
123
138
  export default Page;
@@ -131,7 +146,7 @@ For specific pages available few options:
131
146
  const mainDefaultBundle = createBundle({
132
147
  name: 'mainDefault',
133
148
  components: {
134
- 'pageRenderFallbackDefault': DefaultFallback,
149
+ pageRenderFallbackDefault: DefaultFallback,
135
150
  },
136
151
  });
137
152
 
@@ -154,12 +169,28 @@ For specific pages available few options:
154
169
  ];
155
170
  ```
156
171
 
172
+ ### Static pages
173
+
174
+ #### Options
175
+
176
+ - `ttl` parameter spicified page response cache time. Default - `60000` ms.
177
+ - `maxSize` parameter spicified maximum cached urls count (can be up to 4 pages per url for different segments). Default - `1000`. For apps with heavy HTML and a lot of urls memory usage can be increased significantly.
178
+
179
+ ```ts
180
+ const provider = {
181
+ provide: STATIC_PAGES_OPTIONS_TOKEN,
182
+ useValue: {
183
+ ttl: 60 * 1000,
184
+ maxSize: 1000,
185
+ },
186
+ };
187
+ ```
188
+
157
189
  ## How-to
158
190
 
159
191
  ### How to prevent Header and Footer Rendering
160
192
 
161
- By default, Header and Footer will be rendered as usual, because this module provide Page component wrapper.
162
- If you want to make less work on server, use token `PAGE_RENDER_WRAPPER_TYPE` with `layout` or `content` value, e.g.:
193
+ By default, Header and Footer will be rendered as usual, because this module provide Page component wrapper. If you want to make less work on server, use token `PAGE_RENDER_WRAPPER_TYPE` with `layout` or `content` value, e.g.:
163
194
 
164
195
  ```ts
165
196
  const providers = [
@@ -174,12 +205,39 @@ With `client` rendering mode, all layout will be rendered in browser.
174
205
 
175
206
  `PAGE_RENDER_WRAPPER_TYPE` value will be passed to [default layout](references/modules/render.md#basic-layout), where the library [@tinkoff/layout-factory](references/libs/tinkoff-layout.md#wrappers) is used.
176
207
 
208
+ ### How to clear static page cache
209
+
210
+ If you want to clear all cache, make POST request to special papi endpoint without body - `/{appName}/private/papi/revalidate/`.
211
+
212
+ For specific page, just add `path` parameter to request body, e.g. for `/static/` - `{ path: 'static' }`.
213
+
214
+ ### How to disable background requests for static pages
215
+
216
+ For example, you want to cache only requests without cookies, without extra requests into the application:
217
+
218
+ ```ts
219
+ const provider = {
220
+ provide: STATIC_PAGES_BACKGROUND_FETCH_ENABLED,
221
+ useValue: () => false,
222
+ };
223
+ ```
224
+
225
+ ### How to enable 5xx requests caching for static pages
226
+
227
+ For example, 5xx responses are expected behaviour:
228
+
229
+ ```ts
230
+ const provider = {
231
+ provide: STATIC_PAGES_CACHE_5xx_RESPONSE,
232
+ useValue: () => true,
233
+ };
234
+ ```
235
+
177
236
  ## Troubleshooting
178
237
 
179
238
  ### Fallback name conflicts
180
239
 
181
- You might have a potential issue with conflict existing components and render fallback component names - `pageRenderFallbackComponent` and `pageRenderFallbackDefault`.
182
- For avoiding this issues, just change fallback name prefix using token `PAGE_RENDER_FALLBACK_COMPONENT_PREFIX`:
240
+ You might have a potential issue with conflict existing components and render fallback component names - `pageRenderFallbackComponent` and `pageRenderFallbackDefault`. For avoiding this issues, just change fallback name prefix using token `PAGE_RENDER_FALLBACK_COMPONENT_PREFIX`:
183
241
 
184
242
  ```ts
185
243
  import { PAGE_RENDER_FALLBACK_COMPONENT_PREFIX } from '@tramvai/module-page-render-mode';
@@ -0,0 +1,9 @@
1
+ import type { TramvaiRenderMode } from '@tramvai/tokens-render';
2
+ export * from './tokens';
3
+ declare module '@tramvai/react' {
4
+ interface PageComponentOptions {
5
+ renderMode?: TramvaiRenderMode;
6
+ }
7
+ }
8
+ export declare class PageRenderModeModule {
9
+ }
@@ -5,7 +5,6 @@ import { jsx, Fragment } from 'react/jsx-runtime';
5
5
  import { useState, useEffect } from 'react';
6
6
  import { useDi } from '@tramvai/react';
7
7
  import { PAGE_SERVICE_TOKEN } from '@tramvai/tokens-router';
8
- import { useRoute } from '@tramvai/module-router';
9
8
  import { createToken } from '@tinkoff/dippy';
10
9
 
11
10
  const PAGE_RENDER_FALLBACK_COMPONENT_PREFIX = createToken('pageRenderFallbackComponentName');
@@ -15,11 +14,25 @@ const PAGE_RENDER_FALLBACK_COMPONENT_PREFIX = createToken('pageRenderFallbackCom
15
14
  const PAGE_RENDER_DEFAULT_MODE = createToken('pageRenderDefaultMode');
16
15
  const PAGE_RENDER_WRAPPER_TYPE = createToken('pageRenderWrapperType');
17
16
  const PAGE_RENDER_DEFAULT_FALLBACK_COMPONENT = createToken('pageRenderDefaultFallbackComponent');
17
+ const STATIC_PAGES_CACHE_TOKEN = createToken('static pages cache');
18
+ const STATIC_PAGES_SHOULD_USE_CACHE = createToken('static pages should use cache');
19
+ const STATIC_PAGES_SHOULD_SET_TO_CACHE = createToken('static pages should set to cache');
20
+ const STATIC_PAGES_BACKGROUND_FETCH_ENABLED = createToken('static pages can fetch page');
21
+ const STATIC_PAGES_OPTIONS_TOKEN = createToken('static pages options');
22
+ const STATIC_PAGES_COMMAND_LINE = createToken('static pages command line');
23
+ const STATIC_PAGES_MODIFY_CACHE = createToken('static pages modify cache', { multi: true });
24
+ const STATIC_PAGES_CACHE_5xx_RESPONSE = createToken('static pages cache 5xx response');
18
25
 
19
- const PageRenderWrapper = ({ children }) => {
26
+ const getPageRenderMode = ({ pageService, defaultRenderMode, }) => {
20
27
  var _a;
28
+ const { pageComponent, pageRenderMode } = pageService.getConfig();
29
+ const { renderMode } = (_a = pageService.getComponent(pageComponent)) !== null && _a !== void 0 ? _a : {};
30
+ const mode = pageRenderMode || renderMode || defaultRenderMode;
31
+ return mode;
32
+ };
33
+
34
+ const PageRenderWrapper = ({ children }) => {
21
35
  const [mounted, setMounted] = useState(false);
22
- const { config } = useRoute();
23
36
  const pageService = useDi(PAGE_SERVICE_TOKEN);
24
37
  const fallbackKey = useDi(PAGE_RENDER_FALLBACK_COMPONENT_PREFIX);
25
38
  const defaultRenderMode = useDi(PAGE_RENDER_DEFAULT_MODE);
@@ -27,10 +40,8 @@ const PageRenderWrapper = ({ children }) => {
27
40
  token: PAGE_RENDER_DEFAULT_FALLBACK_COMPONENT,
28
41
  optional: true,
29
42
  });
30
- const { pageComponent, pageRenderMode } = config;
31
- const { renderMode } = (_a = pageService.getComponent(pageComponent)) !== null && _a !== void 0 ? _a : { renderMode: false };
32
43
  const FallbackComponent = pageService.resolveComponentFromConfig(fallbackKey) || DefaultFallbackComponent;
33
- const mode = renderMode || pageRenderMode || defaultRenderMode;
44
+ const mode = getPageRenderMode({ pageService, defaultRenderMode });
34
45
  useEffect(() => {
35
46
  if (mode === 'client') {
36
47
  setMounted(true);
@@ -49,44 +60,46 @@ const pageRenderHOC = (WrapperPage) => (props) => {
49
60
  return (jsx(PageRenderWrapper, { children: jsx(WrapperPage, { ...props }) }));
50
61
  };
51
62
 
63
+ const sharedProviders = [
64
+ {
65
+ provide: LAYOUT_OPTIONS,
66
+ multi: true,
67
+ useFactory: ({ wrapperType }) => {
68
+ return {
69
+ wrappers: {
70
+ [wrapperType]: pageRenderHOC,
71
+ },
72
+ };
73
+ },
74
+ deps: {
75
+ wrapperType: PAGE_RENDER_WRAPPER_TYPE,
76
+ },
77
+ },
78
+ {
79
+ provide: PAGE_RENDER_FALLBACK_COMPONENT_PREFIX,
80
+ useValue: 'pageRenderFallback',
81
+ },
82
+ {
83
+ provide: PAGE_RENDER_DEFAULT_MODE,
84
+ useFactory: ({ tramvaiRenderMode }) => {
85
+ return tramvaiRenderMode;
86
+ },
87
+ deps: {
88
+ tramvaiRenderMode: TRAMVAI_RENDER_MODE,
89
+ },
90
+ },
91
+ {
92
+ provide: PAGE_RENDER_WRAPPER_TYPE,
93
+ useValue: 'page',
94
+ },
95
+ ];
96
+
52
97
  let PageRenderModeModule = class PageRenderModeModule {
53
98
  };
54
99
  PageRenderModeModule = __decorate([
55
100
  Module({
56
- providers: [
57
- {
58
- provide: LAYOUT_OPTIONS,
59
- multi: true,
60
- useFactory: ({ wrapperType }) => {
61
- return {
62
- wrappers: {
63
- [wrapperType]: pageRenderHOC,
64
- },
65
- };
66
- },
67
- deps: {
68
- wrapperType: PAGE_RENDER_WRAPPER_TYPE,
69
- },
70
- },
71
- {
72
- provide: PAGE_RENDER_FALLBACK_COMPONENT_PREFIX,
73
- useValue: 'pageRenderFallback',
74
- },
75
- {
76
- provide: PAGE_RENDER_DEFAULT_MODE,
77
- useFactory: ({ tramvaiRenderMode }) => {
78
- return tramvaiRenderMode;
79
- },
80
- deps: {
81
- tramvaiRenderMode: TRAMVAI_RENDER_MODE,
82
- },
83
- },
84
- {
85
- provide: PAGE_RENDER_WRAPPER_TYPE,
86
- useValue: 'page',
87
- },
88
- ],
101
+ providers: [...sharedProviders],
89
102
  })
90
103
  ], PageRenderModeModule);
91
104
 
92
- export { PAGE_RENDER_DEFAULT_FALLBACK_COMPONENT, PAGE_RENDER_DEFAULT_MODE, PAGE_RENDER_FALLBACK_COMPONENT_PREFIX, PAGE_RENDER_WRAPPER_TYPE, PageRenderModeModule };
105
+ export { PAGE_RENDER_DEFAULT_FALLBACK_COMPONENT, PAGE_RENDER_DEFAULT_MODE, PAGE_RENDER_FALLBACK_COMPONENT_PREFIX, PAGE_RENDER_WRAPPER_TYPE, PageRenderModeModule, STATIC_PAGES_BACKGROUND_FETCH_ENABLED, STATIC_PAGES_CACHE_5xx_RESPONSE, STATIC_PAGES_CACHE_TOKEN, STATIC_PAGES_COMMAND_LINE, STATIC_PAGES_MODIFY_CACHE, STATIC_PAGES_OPTIONS_TOKEN, STATIC_PAGES_SHOULD_SET_TO_CACHE, STATIC_PAGES_SHOULD_USE_CACHE };
package/lib/error.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import { SilentError } from '@tinkoff/errors';
2
+ export declare class StopCommandLineRunnerError extends SilentError {
3
+ static errorName: string;
4
+ name: string;
5
+ constructor();
6
+ }
7
+ export declare const isStopCommandLineRunnerError: (error: Error) => error is StopCommandLineRunnerError;
@@ -0,0 +1,9 @@
1
+ import type { TramvaiRenderMode } from '@tramvai/tokens-render';
2
+ export * from './tokens';
3
+ declare module '@tramvai/react' {
4
+ interface PageComponentOptions {
5
+ renderMode?: TramvaiRenderMode;
6
+ }
7
+ }
8
+ export declare class PageRenderModeModule {
9
+ }