vike-react 0.4.17 → 0.4.18

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/dist/+config.d.ts CHANGED
@@ -5,6 +5,7 @@ declare const _default: {
5
5
  require: {
6
6
  vike: string;
7
7
  };
8
+ Loading: "import:vike-react/components/Loading:default";
8
9
  onRenderHtml: "import:vike-react/renderer/onRenderHtml:onRenderHtml";
9
10
  onRenderClient: "import:vike-react/renderer/onRenderClient:onRenderClient";
10
11
  passToClient: string[];
@@ -90,6 +91,12 @@ declare const _default: {
90
91
  server: true;
91
92
  };
92
93
  };
94
+ Loading: {
95
+ env: {
96
+ server: true;
97
+ client: true;
98
+ };
99
+ };
93
100
  };
94
101
  };
95
102
  export default _default;
package/dist/+config.js CHANGED
@@ -7,6 +7,7 @@ export default {
7
7
  require: {
8
8
  vike: '>=0.4.178'
9
9
  },
10
+ Loading: 'import:vike-react/components/Loading:default',
10
11
  // https://vike.dev/onRenderHtml
11
12
  onRenderHtml: 'import:vike-react/renderer/onRenderHtml:onRenderHtml',
12
13
  // https://vike.dev/onRenderClient
@@ -66,6 +67,9 @@ export default {
66
67
  },
67
68
  reactStrictMode: {
68
69
  env: { client: true, server: true }
70
+ },
71
+ Loading: {
72
+ env: { server: true, client: true }
69
73
  }
70
74
  }
71
75
  };
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ declare const _default: {
3
+ component: typeof LoadingComponent;
4
+ };
5
+ export default _default;
6
+ declare function LoadingComponent(): React.JSX.Element;
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ export default {
3
+ component: LoadingComponent
4
+ };
5
+ function LoadingComponent() {
6
+ return (React.createElement("div", { style: {
7
+ width: '100%',
8
+ height: '100%',
9
+ maxHeight: '100%',
10
+ background: 'linear-gradient(110deg, #ececec 8%, #f5f5f5 18%, #ececec 33%)',
11
+ borderRadius: '5px',
12
+ backgroundSize: '200% 100%',
13
+ animation: '1.3s vike-react-shine linear infinite',
14
+ aspectRatio: '2.5/1'
15
+ } }));
16
+ }
@@ -1,16 +1,24 @@
1
1
  export { getPageElement };
2
- import React from 'react';
2
+ import React, { Suspense } from 'react';
3
3
  import { PageContextProvider } from '../hooks/usePageContext.js';
4
4
  function getPageElement(pageContext) {
5
- const { Page } = pageContext;
5
+ const { Page, config: { Loading } } = pageContext;
6
6
  let page = Page ? React.createElement(Page, null) : null;
7
+ // Wrapping
8
+ const addSuspense = (el) => {
9
+ if (!Loading?.layout)
10
+ return el;
11
+ return React.createElement(Suspense, { fallback: React.createElement(Loading.layout, null) }, page);
12
+ };
13
+ page = addSuspense(page);
7
14
  [
8
15
  // Inner wrapping
9
16
  ...(pageContext.config.Layout || []),
10
17
  // Outer wrapping
11
18
  ...(pageContext.config.Wrapper || [])
12
- ].forEach((Wrapper) => {
13
- page = React.createElement(Wrapper, null, page);
19
+ ].forEach((Wrap) => {
20
+ page = React.createElement(Wrap, null, page);
21
+ page = addSuspense(page);
14
22
  });
15
23
  page = React.createElement(PageContextProvider, { pageContext: pageContext }, page);
16
24
  if (pageContext.config.reactStrictMode !== false) {
@@ -1,3 +1,4 @@
1
1
  export { onRenderClient };
2
2
  import type { OnRenderClientSync } from 'vike/types';
3
+ import './styles.css';
3
4
  declare const onRenderClient: OnRenderClientSync;
@@ -3,6 +3,7 @@ export { onRenderClient };
3
3
  import ReactDOM from 'react-dom/client';
4
4
  import { getHeadSetting } from './getHeadSetting.js';
5
5
  import { getPageElement } from './getPageElement.js';
6
+ import './styles.css';
6
7
  let root;
7
8
  const onRenderClient = (pageContext) => {
8
9
  // Use case:
@@ -10,53 +10,62 @@ import { getPageElement } from './getPageElement.js';
10
10
  checkVikeVersion();
11
11
  addEcosystemStamp();
12
12
  const onRenderHtml = async (pageContext) => {
13
- const title = getHeadSetting('title', pageContext);
14
- const favicon = getHeadSetting('favicon', pageContext);
15
- const lang = getHeadSetting('lang', pageContext) || 'en';
16
- const titleTag = !title ? '' : escapeInject `<title>${title}</title>`;
17
- const faviconTag = !favicon ? '' : escapeInject `<link rel="icon" href="${favicon}" />`;
18
- const Head = pageContext.config.Head || (() => React.createElement(React.Fragment, null));
19
- let head = (React.createElement(PageContextProvider, { pageContext: pageContext },
20
- React.createElement(Head, null)));
21
- if (pageContext.config.reactStrictMode !== false) {
22
- head = React.createElement(React.StrictMode, null, head);
23
- }
24
- const headHtml = dangerouslySkipEscape(renderToString(head));
25
- let pageView;
13
+ const pageHtml = await getPageHtml(pageContext);
14
+ const { headHtml, lang } = getHeadHtml(pageContext);
15
+ return escapeInject `<!DOCTYPE html>
16
+ <html lang='${lang}'>
17
+ <head>${headHtml}</head>
18
+ <body>
19
+ <div id="root">${pageHtml}</div>
20
+ </body>
21
+ </html>`;
22
+ };
23
+ async function getPageHtml(pageContext) {
24
+ let pageHtml;
26
25
  if (!pageContext.Page) {
27
- pageView = '';
26
+ pageHtml = '';
28
27
  }
29
28
  else {
30
29
  const page = getPageElement(pageContext);
31
30
  const { stream, streamIsRequired } = pageContext.config;
32
31
  if (!stream && !streamIsRequired) {
33
- pageView = dangerouslySkipEscape(renderToString(page));
32
+ pageHtml = dangerouslySkipEscape(renderToString(page));
34
33
  }
35
34
  else {
36
35
  const disable = stream === false ? true : undefined;
37
- pageView = await renderToStream(page, {
36
+ pageHtml = await renderToStream(page, {
38
37
  webStream: typeof stream === 'string' ? stream === 'web' : undefined,
39
38
  userAgent: pageContext.headers?.['user-agent'] ||
40
- // Deprecated way of acccessing User Agent header. Eventually remove it.
39
+ // TODO/eventually: remove old way of acccessing the User Agent header.
40
+ // @ts-ignore
41
41
  pageContext.userAgent,
42
42
  disable
43
43
  });
44
44
  }
45
45
  }
46
- const documentHtml = escapeInject `<!DOCTYPE html>
47
- <html lang='${lang}'>
48
- <head>
49
- <meta charset="UTF-8" />
50
- ${titleTag}
51
- ${headHtml}
52
- ${faviconTag}
53
- </head>
54
- <body>
55
- <div id="root">${pageView}</div>
56
- </body>
57
- </html>`;
58
- return documentHtml;
59
- };
46
+ return pageHtml;
47
+ }
48
+ function getHeadHtml(pageContext) {
49
+ const title = getHeadSetting('title', pageContext);
50
+ const favicon = getHeadSetting('favicon', pageContext);
51
+ const lang = getHeadSetting('lang', pageContext) || 'en';
52
+ const titleTags = !title ? '' : escapeInject `<title>${title}</title><meta property="og:title" content="${title}" />`;
53
+ const faviconTag = !favicon ? '' : escapeInject `<link rel="icon" href="${favicon}" />`;
54
+ const Head = pageContext.config.Head || (() => React.createElement(React.Fragment, null));
55
+ let headElement = (React.createElement(PageContextProvider, { pageContext: pageContext },
56
+ React.createElement(Head, null)));
57
+ if (pageContext.config.reactStrictMode !== false) {
58
+ headElement = React.createElement(React.StrictMode, null, headElement);
59
+ }
60
+ const headElementHtml = dangerouslySkipEscape(renderToString(headElement));
61
+ const headHtml = escapeInject `
62
+ <meta charset="UTF-8" />
63
+ ${titleTags}
64
+ ${headElementHtml}
65
+ ${faviconTag}
66
+ `;
67
+ return { headHtml, lang };
68
+ }
60
69
  // We don't need this anymore starting from vike@0.4.173 which added the `require` setting.
61
70
  // TODO/eventually: remove this once <=0.4.172 versions become rare.
62
71
  function checkVikeVersion() {
@@ -2,18 +2,21 @@ export { ssrEffect };
2
2
  function ssrEffect({ configDefinedAt, configValue }) {
3
3
  if (typeof configValue !== 'boolean')
4
4
  throw new Error(`${configDefinedAt} should be a boolean`);
5
+ const env = {
6
+ // Always load on the client-side.
7
+ client: true,
8
+ // When the SSR flag is false, we want to render the page only on the client-side.
9
+ // We achieve this by loading `Page` only on the client-side: when onRenderHtml()
10
+ // gets a `Page` value that is undefined it skip server-side rendering.
11
+ server: configValue !== false
12
+ };
5
13
  return {
6
14
  meta: {
7
- Page: {
8
- env: {
9
- // Always load `Page` on the client-side.
10
- client: true,
11
- // When the SSR flag is false, we want to render the page only on the client-side.
12
- // We achieve this by loading `Page` only on the client-side: when onRenderHtml()
13
- // gets a `Page` value that is undefined it skip server-side rendering.
14
- server: configValue !== false
15
- }
16
- }
15
+ Page: { env },
16
+ /* We don't do this to enable wraping <Head> with <Wrapper>
17
+ Wrapper: { env }, */
18
+ Layout: { env },
19
+ Loading: { env }
17
20
  }
18
21
  };
19
22
  }
@@ -0,0 +1,6 @@
1
+ /* For components/Loading.tsx */
2
+ @keyframes vike-react-shine {
3
+ to {
4
+ background-position-x: -200%;
5
+ }
6
+ }
@@ -1,4 +1,4 @@
1
- import type { ImportString, PageContextClient } from 'vike/types';
1
+ import type { ImportString, PageContextClient, PageContext } from 'vike/types';
2
2
  declare global {
3
3
  namespace Vike {
4
4
  interface Config {
@@ -20,16 +20,26 @@ declare global {
20
20
  * https://vike.dev/Wrapper
21
21
  */
22
22
  Wrapper?: Wrapper | ImportString;
23
- /** &lt;title>${title}&lt;/title> */
24
- title?: string;
25
- /** &lt;link rel="icon" href="${favicon}" /> */
26
- favicon?: string;
27
- /** &lt;html lang="${lang}">
28
- *
29
- * @default 'en'
30
- *
23
+ /**
24
+ * ```js
25
+ * <title>${title}</title>
26
+ * <meta property="og:title" content="${title}" />
27
+ * ```
28
+ */
29
+ title?: PlainOrGetter<string>;
30
+ /**
31
+ * ```js
32
+ * <link rel="icon" href="${favicon}" />
33
+ * ```
34
+ */
35
+ favicon?: PlainOrGetter<string>;
36
+ /**
37
+ * ```js
38
+ * <html lang="${lang}">
39
+ * ```
40
+ * @default 'en'
31
41
  */
32
- lang?: string;
42
+ lang?: PlainOrGetter<string>;
33
43
  /**
34
44
  * If `true`, the page is rendered twice: on the server-side (to HTML) and on the client-side (hydration).
35
45
  *
@@ -82,6 +92,7 @@ declare global {
82
92
  * https://vike.dev/onAfterRenderClient
83
93
  */
84
94
  onAfterRenderClient?: (pageContext: PageContextClient) => void;
95
+ Loading?: Loading | ImportString;
85
96
  }
86
97
  interface ConfigResolved {
87
98
  Wrapper?: Wrapper[];
@@ -89,8 +100,13 @@ declare global {
89
100
  }
90
101
  }
91
102
  }
103
+ type PlainOrGetter<T> = T | ((pageContext: PageContext) => T);
92
104
  type Wrapper = (props: {
93
105
  children: React.ReactNode;
94
106
  }) => React.ReactNode;
95
107
  type Layout = Wrapper;
108
+ type Loading = {
109
+ component?: () => React.ReactNode;
110
+ layout?: () => React.ReactNode;
111
+ };
96
112
  export {};
@@ -6,8 +6,6 @@ declare global {
6
6
  interface PageContext {
7
7
  /** The root React component of the page */
8
8
  Page?: () => React.ReactNode;
9
- /** The user agent string of the user's browser */
10
- userAgent?: string;
11
9
  /** The root React element of the page */
12
10
  page?: JSX.Element;
13
11
  /** The React root DOM container */
@@ -0,0 +1 @@
1
+ export declare function assert(condition: unknown): asserts condition;
@@ -0,0 +1,5 @@
1
+ export function assert(condition) {
2
+ if (condition)
3
+ return;
4
+ throw new Error('You stumbled upon a vike-react bug, reach out on GitHub.');
5
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vike-react",
3
- "version": "0.4.17",
3
+ "version": "0.4.18",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -12,11 +12,13 @@
12
12
  ".": "./dist/index.js",
13
13
  "./config": "./dist/+config.js",
14
14
  "./renderer/onRenderHtml": "./dist/renderer/onRenderHtml.js",
15
- "./renderer/onRenderClient": "./dist/renderer/onRenderClient.js"
15
+ "./renderer/onRenderClient": "./dist/renderer/onRenderClient.js",
16
+ "./components/Loading": "./dist/components/Loading.js"
16
17
  },
17
18
  "scripts": {
18
19
  "dev": "tsc --watch",
19
- "build": "rimraf dist/ && tsc",
20
+ "build": "rimraf dist/ && tsc && pnpm run build:css",
21
+ "build:css": "cp src/renderer/styles.css dist/renderer/styles.css",
20
22
  "release": "release-me patch",
21
23
  "release:minor": "release-me minor",
22
24
  "release:commit": "release-me commit"
@@ -36,11 +38,11 @@
36
38
  "react": "^18.2.0",
37
39
  "react-dom": "^18.2.0",
38
40
  "rimraf": "^5.0.5",
39
- "typescript": "^5.3.3",
41
+ "typescript": "^5.5.3",
40
42
  "vike": "^0.4.178"
41
43
  },
42
44
  "dependencies": {
43
- "react-streaming": "^0.3.41"
45
+ "react-streaming": "^0.3.42"
44
46
  },
45
47
  "typesVersions": {
46
48
  "*": {