@teambit/ui 0.0.802 → 0.0.805

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.
Files changed (50) hide show
  1. package/dist/create-root.js +1 -1
  2. package/dist/create-root.js.map +1 -1
  3. package/dist/index.d.ts +12 -5
  4. package/dist/index.js.map +1 -1
  5. package/dist/ssr-middleware/ssr-middleware.d.ts +2 -2
  6. package/dist/ssr-middleware/ssr-middleware.js +20 -18
  7. package/dist/ssr-middleware/ssr-middleware.js.map +1 -1
  8. package/dist/ui-root.d.ts +3 -3
  9. package/dist/ui-root.js.map +1 -1
  10. package/dist/ui.main.runtime.d.ts +1 -1
  11. package/dist/ui.main.runtime.js +2 -2
  12. package/dist/ui.main.runtime.js.map +1 -1
  13. package/dist/ui.ui.runtime.d.ts +4 -5
  14. package/dist/ui.ui.runtime.js +27 -17
  15. package/dist/ui.ui.runtime.js.map +1 -1
  16. package/package-tar/teambit-ui-0.0.805.tgz +0 -0
  17. package/package.json +19 -22
  18. package/{preview-1659151732866.js → preview-1659456045857.js} +2 -2
  19. package/ssr-middleware/ssr-middleware.ts +15 -16
  20. package/ui-root.tsx +7 -3
  21. package/ui.ui.runtime.tsx +21 -18
  22. package/dist/react-ssr/index.d.ts +0 -5
  23. package/dist/react-ssr/index.js +0 -23
  24. package/dist/react-ssr/index.js.map +0 -1
  25. package/dist/react-ssr/react-ssr.d.ts +0 -21
  26. package/dist/react-ssr/react-ssr.js +0 -285
  27. package/dist/react-ssr/react-ssr.js.map +0 -1
  28. package/dist/react-ssr/render-lifecycle.d.ts +0 -56
  29. package/dist/react-ssr/render-lifecycle.js +0 -3
  30. package/dist/react-ssr/render-lifecycle.js.map +0 -1
  31. package/dist/react-ssr/request-browser.d.ts +0 -56
  32. package/dist/react-ssr/request-browser.js +0 -3
  33. package/dist/react-ssr/request-browser.js.map +0 -1
  34. package/dist/react-ssr/request-server.d.ts +0 -9
  35. package/dist/react-ssr/request-server.js +0 -3
  36. package/dist/react-ssr/request-server.js.map +0 -1
  37. package/dist/react-ssr/ssr-content.d.ts +0 -8
  38. package/dist/react-ssr/ssr-content.js +0 -3
  39. package/dist/react-ssr/ssr-content.js.map +0 -1
  40. package/dist/ssr-middleware/extract-browser-data.d.ts +0 -6
  41. package/dist/ssr-middleware/extract-browser-data.js +0 -35
  42. package/dist/ssr-middleware/extract-browser-data.js.map +0 -1
  43. package/package-tar/teambit-ui-0.0.802.tgz +0 -0
  44. package/react-ssr/index.ts +0 -6
  45. package/react-ssr/react-ssr.tsx +0 -183
  46. package/react-ssr/render-lifecycle.tsx +0 -58
  47. package/react-ssr/request-browser.ts +0 -55
  48. package/react-ssr/request-server.ts +0 -10
  49. package/react-ssr/ssr-content.ts +0 -9
  50. package/ssr-middleware/extract-browser-data.ts +0 -31
@@ -1,183 +0,0 @@
1
- import React, { ReactNode } from 'react';
2
- import { merge } from 'webpack-merge';
3
- import compact from 'lodash.compact';
4
- import ReactDOM from 'react-dom';
5
- import ReactDOMServer from 'react-dom/server';
6
-
7
- import { Html, MountPoint, mountPointId, ssrCleanup, Assets } from '@teambit/ui-foundation.ui.rendering.html';
8
- import { Composer, Wrapper } from '@teambit/base-ui.utils.composer';
9
-
10
- import type { RenderPlugins } from './render-lifecycle';
11
- import type { SsrContent } from './ssr-content';
12
- import type { RequestServer } from './request-server';
13
- import type { BrowserData } from './request-browser';
14
-
15
- type RenderPluginsWithId = [key: string, hooks: RenderPlugins];
16
-
17
- export class ReactSSR {
18
- constructor(
19
- // create array once to keep consistent indexes
20
- private lifecycleHooks: RenderPluginsWithId[]
21
- ) {}
22
-
23
- /** render and rehydrate client-side */
24
- async renderBrowser(children: ReactNode) {
25
- // (*) load state from the dom
26
- const deserializedState = await this.deserialize();
27
-
28
- // (1) init setup client plugins
29
- let renderContexts = await this.triggerBrowserInit(deserializedState);
30
-
31
- // (2) make react dom
32
- const reactContexts = this.getReactContexts(renderContexts);
33
- const app = <Composer components={reactContexts}>{children}</Composer>;
34
-
35
- renderContexts = await this.triggerBeforeHydrateHook(renderContexts, app);
36
-
37
- // (3) render / rehydrate
38
- const mountPoint = document.getElementById(mountPointId);
39
- // .render() already runs `.hydrate()` behind the scenes.
40
- // in the future, we may want to replace it with .hydrate()
41
- ReactDOM.render(app, mountPoint);
42
-
43
- await this.triggerHydrateHook(renderContexts, mountPoint);
44
-
45
- // (3.1) remove ssr only styles
46
- ssrCleanup();
47
- }
48
-
49
- /** render dehydrated server-side */
50
- async renderServer(children: ReactNode, { assets, browser, server }: SsrContent = {}): Promise<string> {
51
- // (1) init
52
- let renderContexts = await this.triggerServerInit(browser, server);
53
-
54
- // (2) make React dom
55
- const reactContexts = this.getReactContexts(renderContexts);
56
- const app = (
57
- <MountPoint>
58
- <Composer components={reactContexts}>{children}</Composer>
59
- </MountPoint>
60
- );
61
-
62
- renderContexts = await this.triggerBeforeRender(renderContexts, app);
63
-
64
- // (3) render (to string)
65
- const renderedApp = ReactDOMServer.renderToString(app);
66
-
67
- // (*) serialize state
68
- const realtimeAssets = await this.serialize(renderContexts, app);
69
- // @ts-ignore // TODO upgrade 'webpack-merge'
70
- const totalAssets = merge(assets, realtimeAssets) as Assets;
71
-
72
- // (4) render html-template (to string)
73
- const html = <Html assets={totalAssets} withDevTools fullHeight ssr />;
74
- const renderedHtml = `<!DOCTYPE html>${ReactDOMServer.renderToStaticMarkup(html)}`;
75
- const fullHtml = Html.fillContent(renderedHtml, renderedApp);
76
-
77
- // (5) serve
78
- return fullHtml;
79
- }
80
-
81
- private triggerBrowserInit(deserializedState: any[]) {
82
- const { lifecycleHooks } = this;
83
-
84
- const initPromises = lifecycleHooks.map(([, hooks], idx) => {
85
- const state = deserializedState[idx];
86
- return hooks.browserInit?.(state);
87
- });
88
- return Promise.all(initPromises);
89
- }
90
-
91
- private triggerServerInit(browser?: BrowserData, server?: RequestServer) {
92
- const { lifecycleHooks } = this;
93
- const promises = lifecycleHooks.map(([, hooks]) => hooks.serverInit?.({ browser, server }));
94
- return Promise.all(promises);
95
- }
96
-
97
- private triggerBeforeHydrateHook(renderContexts: any[], app: JSX.Element) {
98
- const { lifecycleHooks } = this;
99
-
100
- const promises = lifecycleHooks.map(async ([, hooks], idx) => {
101
- const ctx = renderContexts[idx];
102
- const nextCtx = await hooks.onBeforeHydrate?.(ctx, app);
103
- return nextCtx || ctx;
104
- });
105
-
106
- return Promise.all(promises);
107
- }
108
-
109
- private async triggerHydrateHook(renderContexts: any[], mountPoint: HTMLElement | null) {
110
- const { lifecycleHooks } = this;
111
-
112
- const promises = lifecycleHooks.map(([, hooks], idx) => {
113
- const renderCtx = renderContexts[idx];
114
- return hooks.onHydrate?.(renderCtx, mountPoint);
115
- });
116
-
117
- await Promise.all(promises);
118
- }
119
-
120
- private async triggerBeforeRender(renderContexts: any[], app: JSX.Element) {
121
- const { lifecycleHooks } = this;
122
-
123
- const promises = lifecycleHooks.map(async ([, hooks], idx) => {
124
- const ctx = renderContexts[idx];
125
- const nextCtx = await hooks.onBeforeRender?.(ctx, app);
126
- return nextCtx || ctx;
127
- });
128
-
129
- await Promise.all(promises);
130
-
131
- return renderContexts;
132
- }
133
-
134
- private getReactContexts(renderContexts: any[]): Wrapper[] {
135
- const { lifecycleHooks } = this;
136
-
137
- return compact(
138
- lifecycleHooks.map(([, hooks], idx) => {
139
- const renderCtx = renderContexts[idx];
140
- const props = { renderCtx };
141
- return hooks.reactContext ? [hooks.reactContext, props] : undefined;
142
- })
143
- );
144
- }
145
-
146
- private async deserialize() {
147
- const { lifecycleHooks } = this;
148
- const rawAssets = Html.popAssets();
149
-
150
- const deserialized = await Promise.all(
151
- lifecycleHooks.map(async ([key, hooks]) => {
152
- try {
153
- const raw = rawAssets.get(key);
154
- return hooks.deserialize?.(raw);
155
- } catch (e) {
156
- // eslint-disable-next-line no-console
157
- console.error(`failed deserializing server state for aspect ${key}`, e);
158
- return undefined;
159
- }
160
- })
161
- );
162
-
163
- return deserialized;
164
- }
165
-
166
- private async serialize(renderContexts: any[], app: ReactNode): Promise<Assets> {
167
- const { lifecycleHooks } = this;
168
- const json = {};
169
-
170
- const promises = lifecycleHooks.map(async ([key, hooks], idx) => {
171
- const renderCtx = renderContexts[idx];
172
- const result = await hooks.serialize?.(renderCtx, app);
173
-
174
- if (!result) return;
175
- if (result.json) json[key] = result.json;
176
- });
177
-
178
- await Promise.all(promises);
179
-
180
- // more assets will be available in the future
181
- return { json };
182
- }
183
- }
@@ -1,58 +0,0 @@
1
- import { ReactNode, ComponentType } from 'react';
2
- import { BrowserData } from './request-browser';
3
- import { RequestServer } from './request-server';
4
-
5
- export type ContextProps<T = any> = { renderCtx?: T; children: ReactNode };
6
-
7
- /** Plugins for each step of the SSR and regular rendering lifecycle */
8
- export type RenderPlugins<RenderCtx = any, Serialized = any> = {
9
- /**
10
- * Initialize a context state for this specific rendering.
11
- * Context state will only be available to the current Aspect, in the other hooks, as well as a prop to the react context component.
12
- */
13
- serverInit?: (state: {
14
- browser?: BrowserData;
15
- server?: RequestServer;
16
- }) => RenderCtx | void | undefined | Promise<RenderCtx | void | undefined>;
17
- /**
18
- * Executes before running ReactDOM.renderToString(). Return value will replace the existing context state.
19
- */
20
- onBeforeRender?: (
21
- ctx: RenderCtx,
22
- app: ReactNode
23
- ) => RenderCtx | void | undefined | Promise<RenderCtx | void | undefined>;
24
- /**
25
- * Produce html assets. Runs after the body is rendered, and before rendering the final html.
26
- * @returns
27
- * json: will be rendered to the dom as a `<script type="json"/>`.
28
- * More assets will be available in the future.
29
- */
30
- serialize?: (ctx: RenderCtx, app: ReactNode) => { json: string } | Promise<{ json: string }> | undefined;
31
- /**
32
- * Converts serialized data from raw string back to structured data.
33
- * @example deserialize: (data) => { const parsed = JSON.parse(data); return { analytics: new AnalyticsService(parsed); } }
34
- */
35
- deserialize?: (data?: string) => Serialized;
36
- /**
37
- * Initialize the context state for client side rendering.
38
- * Context state will only be available to the current Aspect, in the other hooks, as well as a prop to the react context component.
39
- */
40
- browserInit?: (deserializedData: Serialized) => RenderCtx | void | undefined | Promise<RenderCtx | void | undefined>;
41
- /**
42
- * Executes before running ReactDOM.hydrate() (or .render() in case server side rendering is skipped). Receives the context produced by `deserialize()`
43
- */
44
- onBeforeHydrate?: (
45
- context: RenderCtx,
46
- app: ReactNode
47
- ) => RenderCtx | void | undefined | Promise<RenderCtx | void | undefined>;
48
- /**
49
- * Executes after browser rendering is complete. Receives context from the previous steps.
50
- * @example onHydrate: (ref, { analytics }) => { analytics.reportPageView() }
51
- */
52
- onHydrate?: (context: RenderCtx, ref: HTMLElement | null) => void;
53
-
54
- /**
55
- * Wraps dom with a context. Will receive render context, produced by `onBeforeRender()` (at server-side) or `deserialize()` (at the browser)
56
- */
57
- reactContext?: ComponentType<ContextProps<RenderCtx>>;
58
- };
@@ -1,55 +0,0 @@
1
- import type { IncomingHttpHeaders } from 'http';
2
-
3
- export type ParsedQuery = { [key: string]: undefined | string | string[] | ParsedQuery | ParsedQuery[] };
4
-
5
- export type BrowserData = {
6
- connection: {
7
- secure: boolean;
8
- headers: IncomingHttpHeaders;
9
- body: any;
10
- };
11
- /**
12
- * isomorphic location object, resembling the browser's window.location
13
- */
14
- location: {
15
- /** hostname + port
16
- * @example localhost:3000
17
- */
18
- host: string;
19
- /**
20
- * @example localhost
21
- */
22
- hostname: string;
23
- /** full url
24
- * @example http://localhost:3000/components?q=button
25
- */
26
- href: string;
27
- /** full url without query
28
- * @example http://localhost:3000/components
29
- */
30
- origin: string;
31
- /**
32
- * @example /component
33
- */
34
- pathname: string;
35
- /**
36
- * @example 3000
37
- */
38
- port: number;
39
- /**
40
- * @example http
41
- */
42
- protocol: string;
43
- /**
44
- * parsed search params
45
- * @example { one: 1, two: [2,3]}
46
- */
47
- query: ParsedQuery;
48
- /**
49
- * full resource path, including query, without hostname
50
- * @example /components?q=button
51
- */
52
- url: string;
53
- };
54
- cookie?: string;
55
- };
@@ -1,10 +0,0 @@
1
- import type { Request, Response } from 'express';
2
-
3
- /**
4
- * Represents the server configuration for the current request
5
- */
6
- export type RequestServer = {
7
- port: number;
8
- request: Request;
9
- response: Response;
10
- };
@@ -1,9 +0,0 @@
1
- import type { Assets } from '@teambit/ui-foundation.ui.rendering.html';
2
- import { BrowserData } from './request-browser';
3
- import { RequestServer } from './request-server';
4
-
5
- export type SsrContent = {
6
- assets?: Assets;
7
- browser?: BrowserData;
8
- server?: RequestServer;
9
- };
@@ -1,31 +0,0 @@
1
- import { Request } from 'express';
2
- import { BrowserData } from '../react-ssr';
3
-
4
- /**
5
- * extract relevant information from Express request.
6
- */
7
-
8
- export function extractBrowserData(req: Request, port: number) {
9
- const browser: BrowserData = {
10
- connection: {
11
- secure: req.secure,
12
- headers: req.headers,
13
- body: req.body,
14
- },
15
- // rebuild browser location from request, +port
16
- location: {
17
- host: `${req.hostname}:${port}`,
18
- hostname: req.hostname,
19
- href: `${req.protocol}://${req.hostname}:${port}${req.url}`,
20
- origin: `${req.protocol}://${req.hostname}:${port}`,
21
- pathname: req.path,
22
- port,
23
- protocol: `${req.protocol}:`,
24
- query: req.query,
25
- url: req.url,
26
- },
27
- cookie: req.header('Cookie'),
28
- };
29
-
30
- return browser;
31
- }