@dr.pogodin/react-utils 1.41.4 → 1.41.5
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/build/development/client/index.js +7 -8
- package/build/development/client/index.js.map +1 -1
- package/build/development/server/renderer.js +34 -29
- package/build/development/server/renderer.js.map +1 -1
- package/build/development/shared/components/GenericLink/index.js +2 -1
- package/build/development/shared/components/GenericLink/index.js.map +1 -1
- package/build/development/shared/components/Link.js +2 -2
- package/build/development/shared/components/Link.js.map +1 -1
- package/build/development/shared/components/MetaTags.js +2 -2
- package/build/development/shared/components/MetaTags.js.map +1 -1
- package/build/development/shared/components/NavLink.js +2 -2
- package/build/development/shared/components/NavLink.js.map +1 -1
- package/build/development/shared/utils/jest/E2eSsrEnv.js +16 -0
- package/build/development/shared/utils/jest/E2eSsrEnv.js.map +1 -1
- package/build/development/web.bundle.js +140 -23
- package/build/production/client/index.js +2 -2
- package/build/production/client/index.js.map +1 -1
- package/build/production/server/renderer.js +4 -5
- package/build/production/server/renderer.js.map +1 -1
- package/build/production/shared/components/GenericLink/index.js +1 -1
- package/build/production/shared/components/GenericLink/index.js.map +1 -1
- package/build/production/shared/components/Link.js +2 -2
- package/build/production/shared/components/Link.js.map +1 -1
- package/build/production/shared/components/MetaTags.js +2 -2
- package/build/production/shared/components/MetaTags.js.map +1 -1
- package/build/production/shared/components/NavLink.js +1 -1
- package/build/production/shared/components/NavLink.js.map +1 -1
- package/build/production/shared/utils/jest/E2eSsrEnv.js +14 -2
- package/build/production/shared/utils/jest/E2eSsrEnv.js.map +1 -1
- package/build/production/web.bundle.js +1 -1
- package/build/production/web.bundle.js.map +1 -1
- package/build/types-code/shared/components/GenericLink/index.d.ts +1 -1
- package/build/types-code/shared/components/Link.d.ts +1 -1
- package/build/types-code/shared/components/NavLink.d.ts +1 -1
- package/config/jest/resolver.js +5 -3
- package/config/jest/setup.js +11 -1
- package/package.json +18 -19
- package/src/client/index.tsx +7 -10
- package/src/server/renderer.tsx +33 -38
- package/src/shared/components/GenericLink/index.tsx +2 -1
- package/src/shared/components/Link.tsx +1 -1
- package/src/shared/components/MetaTags.tsx +1 -1
- package/src/shared/components/NavLink.tsx +1 -1
- package/src/shared/utils/jest/E2eSsrEnv.ts +18 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
-
import type { Link, LinkProps, NavLink, NavLinkProps } from 'react-router
|
|
2
|
+
import type { Link, LinkProps, NavLink, NavLinkProps } from 'react-router';
|
|
3
3
|
import './style.scss';
|
|
4
4
|
type LinkT = typeof Link;
|
|
5
5
|
type NavLinkT = typeof NavLink;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* - User opts to open the reference in a new tab;
|
|
6
6
|
* - User explicitely opts to use <a>.
|
|
7
7
|
*/
|
|
8
|
-
import { type LinkProps } from 'react-router
|
|
8
|
+
import { type LinkProps } from 'react-router';
|
|
9
9
|
import { type PropsT as GenericLinkPropsT } from './GenericLink';
|
|
10
10
|
type PropsT = Omit<GenericLinkPropsT, 'routerLinkType'> & LinkProps;
|
|
11
11
|
declare const Link: React.FunctionComponent<PropsT>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type NavLinkProps } from 'react-router
|
|
1
|
+
import { type NavLinkProps } from 'react-router';
|
|
2
2
|
import { type PropsT as GenericLinkPropsT } from './GenericLink';
|
|
3
3
|
type PropsT = Omit<GenericLinkPropsT, 'routerLinkType'> & NavLinkProps;
|
|
4
4
|
declare const NavLink: React.FunctionComponent<PropsT>;
|
package/config/jest/resolver.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
module.exports = (path, options) => {
|
|
2
|
+
const ops = { ...options };
|
|
3
|
+
|
|
2
4
|
// Appending "development" option we ensure that Jest tests use development
|
|
3
5
|
// version of the library's build for browsers, which for example contains
|
|
4
6
|
// "data-testid" attributes (they are optimized-out of production builds).
|
|
5
|
-
if (
|
|
6
|
-
|
|
7
|
+
if (ops.conditions && !ops.conditions.includes('development')) {
|
|
8
|
+
ops.conditions = [...ops.conditions, 'development'];
|
|
7
9
|
}
|
|
8
10
|
|
|
9
|
-
return options.defaultResolver(path,
|
|
11
|
+
return options.defaultResolver(path, ops);
|
|
10
12
|
};
|
package/config/jest/setup.js
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
-
/* eslint-disable import/no-extraneous-dependencies */
|
|
1
|
+
/* eslint-disable global-require, import/no-extraneous-dependencies */
|
|
2
|
+
/* global globalThis */
|
|
2
3
|
|
|
3
4
|
import 'raf/polyfill';
|
|
5
|
+
|
|
6
|
+
// TODO: This is a temporary polyfill necessary for react-router,
|
|
7
|
+
// as JSDom does not provide TextEncoder, see:
|
|
8
|
+
// https://github.com/remix-run/react-router/issues/12363
|
|
9
|
+
if (!globalThis.TextEncoder || !globalThis.TextDecoder) {
|
|
10
|
+
const { TextDecoder, TextEncoder } = require('node:util');
|
|
11
|
+
globalThis.TextEncoder = TextEncoder;
|
|
12
|
+
globalThis.TextDecoder = TextDecoder;
|
|
13
|
+
}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.41.
|
|
2
|
+
"version": "1.41.5",
|
|
3
3
|
"bin": {
|
|
4
4
|
"react-utils-build": "bin/build.js",
|
|
5
5
|
"react-utils-setup": "bin/setup.js"
|
|
@@ -30,25 +30,25 @@
|
|
|
30
30
|
"lodash": "^4.17.21",
|
|
31
31
|
"morgan": "^1.10.0",
|
|
32
32
|
"node-forge": "^1.3.1",
|
|
33
|
-
"qs": "^6.
|
|
33
|
+
"qs": "^6.14.0",
|
|
34
34
|
"raf": "^3.4.1",
|
|
35
35
|
"react": "^19.0.0",
|
|
36
36
|
"react-dom": "^19.0.0",
|
|
37
|
-
"react-helmet": "^
|
|
38
|
-
"react-router
|
|
37
|
+
"react-helmet-async": "^2.0.5",
|
|
38
|
+
"react-router": "^7.1.1",
|
|
39
39
|
"request-ip": "^3.3.0",
|
|
40
40
|
"rimraf": "^6.0.0",
|
|
41
41
|
"serialize-javascript": "^6.0.2",
|
|
42
42
|
"serve-favicon": "^2.5.0",
|
|
43
43
|
"source-map-support": "^0.5.21",
|
|
44
|
-
"uuid": "^11.0.
|
|
44
|
+
"uuid": "^11.0.5",
|
|
45
45
|
"winston": "^3.17.0"
|
|
46
46
|
},
|
|
47
47
|
"description": "Collection of generic ReactJS components and utils",
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@babel/cli": "^7.26.4",
|
|
50
50
|
"@babel/core": "^7.26.0",
|
|
51
|
-
"@babel/eslint-parser": "^7.
|
|
51
|
+
"@babel/eslint-parser": "^7.26.5",
|
|
52
52
|
"@babel/eslint-plugin": "^7.25.9",
|
|
53
53
|
"@babel/node": "^7.26.0",
|
|
54
54
|
"@babel/plugin-transform-runtime": "^7.25.9",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.15",
|
|
62
62
|
"@testing-library/dom": "^10.4.0",
|
|
63
63
|
"@testing-library/react": "^16.1.0",
|
|
64
|
-
"@testing-library/user-event": "^14.
|
|
64
|
+
"@testing-library/user-event": "^14.6.0",
|
|
65
65
|
"@tsconfig/recommended": "^1.0.8",
|
|
66
66
|
"@types/compression": "^1.7.5",
|
|
67
67
|
"@types/config": "^3.3.5",
|
|
@@ -74,9 +74,8 @@
|
|
|
74
74
|
"@types/morgan": "^1.9.9",
|
|
75
75
|
"@types/node-forge": "^1.3.11",
|
|
76
76
|
"@types/pretty": "^2.0.3",
|
|
77
|
-
"@types/react": "^19.0.
|
|
78
|
-
"@types/react-dom": "^19.0.
|
|
79
|
-
"@types/react-helmet": "^6.1.11",
|
|
77
|
+
"@types/react": "^19.0.7",
|
|
78
|
+
"@types/react-dom": "^19.0.3",
|
|
80
79
|
"@types/request-ip": "^0.0.41",
|
|
81
80
|
"@types/serialize-javascript": "^5.0.4",
|
|
82
81
|
"@types/serve-favicon": "^2.5.7",
|
|
@@ -94,36 +93,36 @@
|
|
|
94
93
|
"eslint-config-airbnb-typescript": "^18.0.0",
|
|
95
94
|
"eslint-import-resolver-babel-module": "^5.3.2",
|
|
96
95
|
"eslint-plugin-import": "^2.31.0",
|
|
97
|
-
"eslint-plugin-jest": "^28.
|
|
96
|
+
"eslint-plugin-jest": "^28.11.0",
|
|
98
97
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
99
|
-
"eslint-plugin-react": "^7.37.
|
|
98
|
+
"eslint-plugin-react": "^7.37.4",
|
|
100
99
|
"eslint-plugin-react-hooks": "^4.6.2",
|
|
101
100
|
"identity-obj-proxy": "^3.0.0",
|
|
102
101
|
"jest": "^29.7.0",
|
|
103
102
|
"jest-environment-jsdom": "^29.7.0",
|
|
104
|
-
"memfs": "^4.
|
|
103
|
+
"memfs": "^4.17.0",
|
|
105
104
|
"mini-css-extract-plugin": "^2.9.2",
|
|
106
105
|
"mockdate": "^3.0.5",
|
|
107
106
|
"nodelist-foreach-polyfill": "^1.2.0",
|
|
108
|
-
"postcss": "^8.
|
|
107
|
+
"postcss": "^8.5.1",
|
|
109
108
|
"postcss-loader": "^8.1.1",
|
|
110
109
|
"postcss-scss": "^4.0.9",
|
|
111
110
|
"pretty": "^2.0.0",
|
|
112
111
|
"react-refresh": "^0.16.0",
|
|
113
112
|
"regenerator-runtime": "^0.14.1",
|
|
114
113
|
"resolve-url-loader": "^5.0.0",
|
|
115
|
-
"sass": "^1.83.
|
|
114
|
+
"sass": "^1.83.4",
|
|
116
115
|
"sass-loader": "^16.0.4",
|
|
117
116
|
"sitemap": "^8.0.0",
|
|
118
117
|
"source-map-loader": "^5.0.0",
|
|
119
|
-
"stylelint": "^16.
|
|
118
|
+
"stylelint": "^16.13.2",
|
|
120
119
|
"stylelint-config-standard-scss": "^14.0.0",
|
|
121
120
|
"supertest": "^7.0.0",
|
|
122
121
|
"tsc-alias": "^1.8.10",
|
|
123
|
-
"tstyche": "^3.
|
|
124
|
-
"typed-scss-modules": "^8.1.
|
|
122
|
+
"tstyche": "^3.5.0",
|
|
123
|
+
"typed-scss-modules": "^8.1.1",
|
|
125
124
|
"typescript": "^5.7.3",
|
|
126
|
-
"typescript-eslint": "^8.
|
|
125
|
+
"typescript-eslint": "^8.20.0",
|
|
127
126
|
"webpack": "^5.97.1",
|
|
128
127
|
"webpack-dev-middleware": "^7.4.2",
|
|
129
128
|
"webpack-hot-middleware": "^2.26.1",
|
package/src/client/index.tsx
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
/* global document */
|
|
3
3
|
|
|
4
4
|
import { type ComponentType } from 'react';
|
|
5
|
+
import { createRoot, hydrateRoot } from 'react-dom/client';
|
|
6
|
+
import { HelmetProvider } from 'react-helmet-async';
|
|
7
|
+
import { BrowserRouter } from 'react-router';
|
|
5
8
|
|
|
6
9
|
import { GlobalStateProvider } from '@dr.pogodin/react-global-state';
|
|
7
10
|
|
|
8
|
-
import { createRoot, hydrateRoot } from 'react-dom/client';
|
|
9
|
-
import { BrowserRouter } from 'react-router-dom';
|
|
10
|
-
|
|
11
11
|
import getInj from './getInj';
|
|
12
12
|
|
|
13
13
|
type OptionsT = {
|
|
@@ -28,13 +28,10 @@ export default function Launch(
|
|
|
28
28
|
if (!container) throw Error('Failed to find container for React app');
|
|
29
29
|
const scene = (
|
|
30
30
|
<GlobalStateProvider initialState={getInj().ISTATE || options.initialState}>
|
|
31
|
-
<BrowserRouter
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}}
|
|
36
|
-
>
|
|
37
|
-
<Application />
|
|
31
|
+
<BrowserRouter>
|
|
32
|
+
<HelmetProvider>
|
|
33
|
+
<Application />
|
|
34
|
+
</HelmetProvider>
|
|
38
35
|
</BrowserRouter>
|
|
39
36
|
</GlobalStateProvider>
|
|
40
37
|
);
|
package/src/server/renderer.tsx
CHANGED
|
@@ -27,9 +27,9 @@ import {
|
|
|
27
27
|
import config from 'config';
|
|
28
28
|
import forge from 'node-forge';
|
|
29
29
|
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import { StaticRouter } from 'react-router
|
|
30
|
+
import { prerenderToNodeStream } from 'react-dom/static';
|
|
31
|
+
import { HelmetProvider } from 'react-helmet-async';
|
|
32
|
+
import { StaticRouter } from 'react-router';
|
|
33
33
|
import serializeJs from 'serialize-javascript';
|
|
34
34
|
import { type BuildInfoT, setBuildInfo } from 'utils/isomorphy/buildInfo';
|
|
35
35
|
|
|
@@ -403,7 +403,7 @@ export default function factory(
|
|
|
403
403
|
prepareCipher(buildInfo.key) as Promise<any>,
|
|
404
404
|
]);
|
|
405
405
|
|
|
406
|
-
let helmet;
|
|
406
|
+
let helmet: any;
|
|
407
407
|
|
|
408
408
|
// Gets the mapping between code chunk names and their asset files.
|
|
409
409
|
// These data come from the Webpack compilation, either from the stats
|
|
@@ -426,7 +426,7 @@ export default function factory(
|
|
|
426
426
|
const App = ops.Application;
|
|
427
427
|
let appHtmlMarkup: string = '';
|
|
428
428
|
const ssrContext = new ServerSsrContext(req, chunkGroups, initialState);
|
|
429
|
-
let stream:
|
|
429
|
+
let stream: NodeJS.ReadableStream;
|
|
430
430
|
if (App) {
|
|
431
431
|
const ssrStart = Date.now();
|
|
432
432
|
|
|
@@ -436,30 +436,26 @@ export default function factory(
|
|
|
436
436
|
|
|
437
437
|
const renderPass = async () => {
|
|
438
438
|
ssrContext.chunks = [];
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
v7_startTransition: true,
|
|
451
|
-
}}
|
|
452
|
-
location={req.url}
|
|
453
|
-
>
|
|
439
|
+
|
|
440
|
+
// TODO: prerenderToNodeStream has (abort) "signal" option,
|
|
441
|
+
// and we should wire it up to the SSR timeout below.
|
|
442
|
+
const helmetContext = {};
|
|
443
|
+
const { prelude } = await prerenderToNodeStream(
|
|
444
|
+
<GlobalStateProvider
|
|
445
|
+
initialState={ssrContext.state}
|
|
446
|
+
ssrContext={ssrContext}
|
|
447
|
+
>
|
|
448
|
+
<StaticRouter location={req.url}>
|
|
449
|
+
<HelmetProvider context={helmetContext}>
|
|
454
450
|
<App2 />
|
|
455
|
-
</
|
|
456
|
-
</
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
451
|
+
</HelmetProvider>
|
|
452
|
+
</StaticRouter>
|
|
453
|
+
</GlobalStateProvider>,
|
|
454
|
+
{ onError: (error) => { throw error; } },
|
|
455
|
+
);
|
|
456
|
+
({ helmet } = helmetContext as any);
|
|
457
|
+
|
|
458
|
+
return prelude;
|
|
463
459
|
};
|
|
464
460
|
|
|
465
461
|
let ssrRound = 0;
|
|
@@ -492,16 +488,15 @@ export default function factory(
|
|
|
492
488
|
|
|
493
489
|
ops.logger!.log(ssrContext.dirty ? 'warn' : 'info', logMsg);
|
|
494
490
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
done
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
helmet = Helmet.renderStatic();
|
|
491
|
+
await new Promise((ready) => {
|
|
492
|
+
stream!.pipe(new Writable({
|
|
493
|
+
destroy: ready,
|
|
494
|
+
write: (chunk, _, done) => {
|
|
495
|
+
appHtmlMarkup += chunk.toString();
|
|
496
|
+
done();
|
|
497
|
+
},
|
|
498
|
+
}));
|
|
499
|
+
});
|
|
505
500
|
}
|
|
506
501
|
|
|
507
502
|
/* Encrypts data to be injected into HTML.
|
|
@@ -5,7 +5,7 @@ import type {
|
|
|
5
5
|
LinkProps,
|
|
6
6
|
NavLink,
|
|
7
7
|
NavLinkProps,
|
|
8
|
-
} from 'react-router
|
|
8
|
+
} from 'react-router';
|
|
9
9
|
|
|
10
10
|
import './style.scss';
|
|
11
11
|
|
|
@@ -112,6 +112,7 @@ const GenericLink = ({
|
|
|
112
112
|
return (
|
|
113
113
|
<L
|
|
114
114
|
className={className}
|
|
115
|
+
discover="none"
|
|
115
116
|
// disabled
|
|
116
117
|
onMouseDown={onMouseDown}
|
|
117
118
|
replace={replace}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* - User explicitely opts to use <a>.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import { type LinkProps, Link as RrLink } from 'react-router
|
|
9
|
+
import { type LinkProps, Link as RrLink } from 'react-router';
|
|
10
10
|
|
|
11
11
|
import GenericLink, { type PropsT as GenericLinkPropsT } from './GenericLink';
|
|
12
12
|
|
|
@@ -37,6 +37,8 @@ import type {
|
|
|
37
37
|
JestEnvironmentConfig,
|
|
38
38
|
} from '@jest/environment';
|
|
39
39
|
|
|
40
|
+
import { setBuildInfo } from '../isomorphy/buildInfo';
|
|
41
|
+
|
|
40
42
|
export default class E2eSsrEnv extends JsdomEnv {
|
|
41
43
|
pragmas: Record<string, string | string[]>;
|
|
42
44
|
|
|
@@ -232,6 +234,22 @@ export default class E2eSsrEnv extends JsdomEnv {
|
|
|
232
234
|
async setup() {
|
|
233
235
|
await super.setup();
|
|
234
236
|
await this.runWebpack();
|
|
237
|
+
|
|
238
|
+
// NOTE: It is possible that the Webpack run above, and the SSR run below
|
|
239
|
+
// load different versions of the same module (CommonJS, and ES), and it may
|
|
240
|
+
// cause very confusing problems (e.g. see:
|
|
241
|
+
// https://github.com/birdofpreyru/react-utils/issues/413).
|
|
242
|
+
// It seems we can't reset the cache of ES modules, and Jest's module reset
|
|
243
|
+
// does not reset modules loaded in this enviroment module, and also only
|
|
244
|
+
// replacing entire cache object by and empty {} seems to help (in contrast
|
|
245
|
+
// to deleting all entries by their keys, as it is done within .teardown()
|
|
246
|
+
// method below). Thus, for now we do this as a hotfix, and we also reset
|
|
247
|
+
// build info to undefined, because ES module version not beeing reset
|
|
248
|
+
// triggers an error on the subsequent test using the environment.
|
|
249
|
+
// TODO: Look for a cleaner solution.
|
|
250
|
+
require.cache = {};
|
|
251
|
+
setBuildInfo(undefined, true);
|
|
252
|
+
|
|
235
253
|
if (this.withSsr) await this.runSsr();
|
|
236
254
|
this.global.REACT_UTILS_FORCE_CLIENT_SIDE = true;
|
|
237
255
|
}
|