@teambit/ui 0.0.557 → 0.0.561
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/package.json +35 -28
- package/ui/client-context.module.scss +4 -0
- package/ui.docs.md +118 -0
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teambit/ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.561",
|
|
4
4
|
"homepage": "https://bit.dev/teambit/ui-foundation/ui",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"componentId": {
|
|
7
7
|
"scope": "teambit.ui-foundation",
|
|
8
8
|
"name": "ui",
|
|
9
|
-
"version": "0.0.
|
|
9
|
+
"version": "0.0.561"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"lodash": "4.17.21",
|
|
@@ -53,28 +53,28 @@
|
|
|
53
53
|
"@teambit/base-ui.loaders.loader-ribbon": "1.0.0",
|
|
54
54
|
"@teambit/base-ui.theme.fonts.roboto": "1.0.0",
|
|
55
55
|
"@teambit/base-ui.theme.theme-provider": "1.0.1",
|
|
56
|
-
"@teambit/aspect-loader": "0.0.
|
|
57
|
-
"@teambit/toolbox.path.to-windows-compatible-path": "0.0.
|
|
58
|
-
"@teambit/ui-foundation.ui.hooks.use-data-query": "0.0.
|
|
59
|
-
"@teambit/logger": "0.0.
|
|
60
|
-
"@teambit/cli": "0.0.
|
|
61
|
-
"@teambit/ui-foundation.cli.ui-server-console": "0.0.
|
|
62
|
-
"@teambit/bundler": "0.0.
|
|
63
|
-
"@teambit/component": "0.0.
|
|
64
|
-
"@teambit/express": "0.0.
|
|
65
|
-
"@teambit/graphql": "0.0.
|
|
66
|
-
"@teambit/toolbox.network.get-port": "0.0.
|
|
67
|
-
"@teambit/aspect": "0.0.
|
|
68
|
-
"@teambit/cache": "0.0.
|
|
69
|
-
"@teambit/pubsub": "0.0.
|
|
70
|
-
"@teambit/react-router": "0.0.
|
|
71
|
-
"@teambit/ui-foundation.ui.rendering.html": "0.0.
|
|
56
|
+
"@teambit/aspect-loader": "0.0.561",
|
|
57
|
+
"@teambit/toolbox.path.to-windows-compatible-path": "0.0.464",
|
|
58
|
+
"@teambit/ui-foundation.ui.hooks.use-data-query": "0.0.468",
|
|
59
|
+
"@teambit/logger": "0.0.475",
|
|
60
|
+
"@teambit/cli": "0.0.390",
|
|
61
|
+
"@teambit/ui-foundation.cli.ui-server-console": "0.0.469",
|
|
62
|
+
"@teambit/bundler": "0.0.561",
|
|
63
|
+
"@teambit/component": "0.0.561",
|
|
64
|
+
"@teambit/express": "0.0.479",
|
|
65
|
+
"@teambit/graphql": "0.0.561",
|
|
66
|
+
"@teambit/toolbox.network.get-port": "0.0.94",
|
|
67
|
+
"@teambit/aspect": "0.0.561",
|
|
68
|
+
"@teambit/cache": "0.0.475",
|
|
69
|
+
"@teambit/pubsub": "0.0.561",
|
|
70
|
+
"@teambit/react-router": "0.0.561",
|
|
71
|
+
"@teambit/ui-foundation.ui.rendering.html": "0.0.50",
|
|
72
72
|
"@teambit/design.theme.icons-font": "1.0.2",
|
|
73
73
|
"@teambit/design.ui.tooltip": "0.0.352",
|
|
74
|
-
"@teambit/ui-foundation.ui.global-loader": "0.0.
|
|
75
|
-
"@teambit/webpack.modules.generate-style-loaders": "0.0.
|
|
76
|
-
"@teambit/webpack.modules.style-regexps": "0.0.
|
|
77
|
-
"@teambit/webpack": "0.0.
|
|
74
|
+
"@teambit/ui-foundation.ui.global-loader": "0.0.467",
|
|
75
|
+
"@teambit/webpack.modules.generate-style-loaders": "0.0.84",
|
|
76
|
+
"@teambit/webpack.modules.style-regexps": "0.0.113",
|
|
77
|
+
"@teambit/webpack": "0.0.561"
|
|
78
78
|
},
|
|
79
79
|
"devDependencies": {
|
|
80
80
|
"@types/react": "^17.0.8",
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
},
|
|
97
97
|
"peerDependencies": {
|
|
98
98
|
"@apollo/client": "^3.0.0",
|
|
99
|
-
"@teambit/legacy": "1.0.
|
|
99
|
+
"@teambit/legacy": "1.0.176",
|
|
100
100
|
"react-dom": "^16.8.0 || ^17.0.0",
|
|
101
101
|
"react": "^16.8.0 || ^17.0.0"
|
|
102
102
|
},
|
|
@@ -141,7 +141,7 @@
|
|
|
141
141
|
"react": "-"
|
|
142
142
|
},
|
|
143
143
|
"peerDependencies": {
|
|
144
|
-
"@teambit/legacy": "1.0.
|
|
144
|
+
"@teambit/legacy": "1.0.176",
|
|
145
145
|
"react-dom": "^16.8.0 || ^17.0.0",
|
|
146
146
|
"react": "^16.8.0 || ^17.0.0"
|
|
147
147
|
}
|
|
@@ -150,10 +150,17 @@
|
|
|
150
150
|
"files": [
|
|
151
151
|
"dist",
|
|
152
152
|
"!dist/tsconfig.tsbuildinfo",
|
|
153
|
-
"
|
|
154
|
-
"
|
|
155
|
-
"
|
|
156
|
-
"
|
|
153
|
+
"**/*.md",
|
|
154
|
+
"**/*.mdx",
|
|
155
|
+
"**/*.js",
|
|
156
|
+
"**/*.json",
|
|
157
|
+
"**/*.sass",
|
|
158
|
+
"**/*.scss",
|
|
159
|
+
"**/*.less",
|
|
160
|
+
"**/*.css",
|
|
161
|
+
"**/*.css",
|
|
162
|
+
"**/*.jpeg",
|
|
163
|
+
"**/*.gif"
|
|
157
164
|
],
|
|
158
165
|
"private": false
|
|
159
166
|
}
|
package/ui.docs.md
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
## Server-side rendering
|
|
2
|
+
|
|
3
|
+
Server side rendering (or SSR) is done in the following form:
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
/** at server: */
|
|
7
|
+
const dom = ReactDom.renderToString(<MountPoint>{app}</MountPoint>);
|
|
8
|
+
const assets = { headers, scripts, ... };
|
|
9
|
+
const html = ReactDom.renderStaticMarkup(<Html assets={assets}/>);
|
|
10
|
+
Html.fillContent(html, dom);
|
|
11
|
+
send(html);
|
|
12
|
+
|
|
13
|
+
/** at client: */
|
|
14
|
+
ReactDom.render(app, mountPoint);
|
|
15
|
+
// or .hydrate()
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
We can then enrich the page with hooks:
|
|
19
|
+
|
|
20
|
+
```tsx
|
|
21
|
+
/** at server: */
|
|
22
|
+
let context = hooks.serverInit();
|
|
23
|
+
const app = (
|
|
24
|
+
<hooks.reactContext value={context}>
|
|
25
|
+
<App />
|
|
26
|
+
</hooks.reactContext>
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
context = hooks.onBeforeRender(app, context);
|
|
30
|
+
const dom = ...
|
|
31
|
+
|
|
32
|
+
const assets = hooks.serialize(context);
|
|
33
|
+
const html = ...
|
|
34
|
+
send(html);
|
|
35
|
+
|
|
36
|
+
/** at client: */
|
|
37
|
+
const parsed = hooks.deserialize();
|
|
38
|
+
const context = hooks.browserInit(parsed);
|
|
39
|
+
const app = (
|
|
40
|
+
<hooks.reactContext value={context}>
|
|
41
|
+
<App />
|
|
42
|
+
</hooks.reactContext>
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
hooks.onBeforeHydrate(app, context);
|
|
46
|
+
|
|
47
|
+
const ref = ReactDom.render(app, mountPoint);
|
|
48
|
+
|
|
49
|
+
hooks.onHydrate(ref, context);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The rendering flow will ensure that the rendering Context will be unique per request, and separate between aspects.
|
|
53
|
+
|
|
54
|
+
### Hiding elements before JS execution
|
|
55
|
+
|
|
56
|
+
Certain items look bad in the static HTML, and only get decent after JS executes. Tooltips are a notable example. They take up space in the DOM and only hide once their react code runs.
|
|
57
|
+
For these cases, use the convenience class `--ssr-hidden`. Add this to any misbehaving elements, and it will hide them using `display: none` until reactDom.render() is complete.
|
|
58
|
+
|
|
59
|
+
### .rehydrate vs .render()
|
|
60
|
+
|
|
61
|
+
.rehydrate() attach a React virtual dom to a mount point, without asserting the virtual-dom matches the actual dom.
|
|
62
|
+
.render() updates the mount point to match the react virtual dom.
|
|
63
|
+
|
|
64
|
+
On paper, `.rehydrate()` should be the preferred option, with better performance.
|
|
65
|
+
In practice, `.render()` is backward compatible to React 15, and will know to "hydrate" according to the `data-reactroot` attribute on the mount point, with similar performance, and without revalidating the DOM.
|
|
66
|
+
ReactDOM will also show warnings in dev mode about mismatch between ssr dom and the client side dom.
|
|
67
|
+
|
|
68
|
+
### Best practices
|
|
69
|
+
|
|
70
|
+
- Use ReactContext instead of trying to mutate `App`.
|
|
71
|
+
- Use existing context object.
|
|
72
|
+
- Do not use other Aspects' context object.
|
|
73
|
+
- Try to keep process symmetrical between server and client;
|
|
74
|
+
|
|
75
|
+
#### Example: Server side GraphQL
|
|
76
|
+
|
|
77
|
+
Graphql adds extra instructions to pre-fetch queries on the server:
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
// .registerRenderHooks() ?
|
|
81
|
+
.registerRenderLifecycle({
|
|
82
|
+
serverInit: ({ browser }) => {
|
|
83
|
+
const { cookie } = browser;
|
|
84
|
+
return { client: new Client(GQL_INTERNAL, { cookie }) };
|
|
85
|
+
},
|
|
86
|
+
beforeRender: ({ client }, app) => {
|
|
87
|
+
await getDataFromTree(app);
|
|
88
|
+
},
|
|
89
|
+
serialize: ({ client }, app) => {
|
|
90
|
+
return { json: JSON.stringify(client.extract()) };
|
|
91
|
+
},
|
|
92
|
+
deserialize: (raw) => {
|
|
93
|
+
return { state: JSON.parse(raw) };
|
|
94
|
+
},
|
|
95
|
+
browserInit: ({ state }) => {
|
|
96
|
+
return { client: new GraphqlClient(GQL_EXTERNAL, { cache: state })}
|
|
97
|
+
},
|
|
98
|
+
ReactContext: ({state, children}) =>
|
|
99
|
+
<GqlContext client={state.client}>{children}</GqlContext>
|
|
100
|
+
});
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
#### Example: Server side Styled-components
|
|
104
|
+
|
|
105
|
+
StyledComponents extracts css from page, and adds it to the `<head/>`:
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
.registerRenderLifecycle({
|
|
109
|
+
init: () => {
|
|
110
|
+
return { sheet: new ServerStyleSheet() };
|
|
111
|
+
},
|
|
112
|
+
serialize: (app, { sheet }) => {
|
|
113
|
+
return { styles: sheet.getStyleTags() };
|
|
114
|
+
};
|
|
115
|
+
ReactContext: ({state, children}) =>
|
|
116
|
+
<StyleSheetManager sheet={state.sheet}>{children}</StyleSheetManager>
|
|
117
|
+
});
|
|
118
|
+
```
|