@lwrjs/lwc-ssr 0.7.2 → 0.8.0-alpha.2

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
@@ -63,7 +63,7 @@ Because of this, the [`@lwrjs/router`](https://github.com/salesforce/lwr-recipes
63
63
 
64
64
  ### Preloading data during SSR
65
65
 
66
- Many components depend on external data. LWR provides a `getProps()` hook for developers to fetch that data on the server. LWR passes the data to the component during SSR as [properties](<(https://developer.salesforce.com/docs/component-library/documentation/en/lwc/reactivity_public)>).
66
+ Many components depend on external data. LWR provides a `getProps()` hook for developers to fetch that data on the server. SSR Sandbox supports `fetch` with its `globalThis` so developers could use `fetch` as if the module is executed by the browser. LWR passes the data to the component during SSR as [properties](<(https://developer.salesforce.com/docs/component-library/documentation/en/lwc/reactivity_public)>).
67
67
 
68
68
  > **Important**: This hook is **only** run for root components.
69
69
 
@@ -83,7 +83,7 @@ export async function getProps(context: PropsRequestContext): Promise<PropsRespo
83
83
  const category = context.params.category;
84
84
  // page.html template => context.props = { limit: '10' }
85
85
  const num = context.props.limit || '25';
86
- const res = await context.fetch(`https://www.some-api.com/${category}?lang=${context.locale}&num=${num}`);
86
+ const res = await fetch(`https://www.some-api.com/${category}?lang=${context.locale}&num=${num}`);
87
87
  const data = await res.json();
88
88
  return {
89
89
  props: {
@@ -107,8 +107,6 @@ interface PropsRequestContext {
107
107
  query: { [key: string]: string };
108
108
  // locale string for the request, eg: 'en-US'
109
109
  locale: string;
110
- // server-friendly fetch() function for accessing data
111
- fetch: Function;
112
110
  }
113
111
 
114
112
  interface PropsResponse {
@@ -36,18 +36,18 @@ import Ctor, * as rootComponent from '${rootSpecifier}';
36
36
 
37
37
  (async () => {
38
38
  try {
39
- let props = globalThis.context.props;
39
+ // 1. setup props
40
+ const context = globalThis.getContext();
41
+ let props = context.props;
40
42
  if (rootComponent.getProps) {
41
- const data = await rootComponent.getProps({
42
- props,
43
- params: globalThis.context.params,
44
- query: globalThis.context.query,
45
- locale: globalThis.context.locale,
46
- fetch: globalThis.fetch,
47
- });
43
+ const data = await rootComponent.getProps(context);
48
44
  props = data.props; // overwrite public props
49
45
  }
46
+
47
+ // 2. render component
50
48
  const result = renderComponent('${(0, import_shared_utils.moduleSpecifierToKebabCase)(rootSpecifier)}', Ctor, props || {});
49
+
50
+ // 3. relay results
51
51
  globalThis.postMessage({ result, props });
52
52
  } catch(e) {
53
53
  globalThis.postMessage({ error: e });
@@ -60,7 +60,9 @@ function lwcSsrViewTranformer(options, {moduleBundler}) {
60
60
  const [, remain] = html.split(`<${tagName}`);
61
61
  html = [`<${tagName}`, ` ${import_identity.SSR_PROPS_ATTR}="${propsId}"`, remain].join("");
62
62
  }
63
- stringBuilder.overwrite(startOffset, endOffset, html);
63
+ if (html.length > 0) {
64
+ stringBuilder.overwrite(startOffset, endOffset, html);
65
+ }
64
66
  });
65
67
  }));
66
68
  if (Object.keys(ssrProps).length) {
@@ -30,7 +30,7 @@ var import_worker_threads = __toModule(require("worker_threads"));
30
30
  var HEADER = "/* This module is generated and meant to be used in a Server context */";
31
31
  var WORKER_CODE_SANDBOX_APIS = [
32
32
  `const { parentPort, workerData } = require('worker_threads');`,
33
- `globalThis.context = workerData;`,
33
+ `globalThis.getContext = () => workerData;`,
34
34
  `globalThis.fetch = require('node-fetch');`,
35
35
  `globalThis.postMessage = (...args) => parentPort.postMessage(...args);`
36
36
  ];
@@ -52,7 +52,8 @@ async function ssrElement({specifier, props: templateProps}, moduleBundler, {run
52
52
  code
53
53
  ], context) : await (0, import_sandbox.default)([code], context);
54
54
  if (error) {
55
- throw new Error(error);
55
+ console.error(`Server-side rendering for "${specifier}" failed. Falling back to client-side rendering. Reason: `, error);
56
+ return {html: "", props: void 0};
56
57
  } else {
57
58
  return {html: result, props};
58
59
  }
@@ -20,18 +20,18 @@ import Ctor, * as rootComponent from '${rootSpecifier}';
20
20
 
21
21
  (async () => {
22
22
  try {
23
- let props = globalThis.context.props;
23
+ // 1. setup props
24
+ const context = globalThis.getContext();
25
+ let props = context.props;
24
26
  if (rootComponent.getProps) {
25
- const data = await rootComponent.getProps({
26
- props,
27
- params: globalThis.context.params,
28
- query: globalThis.context.query,
29
- locale: globalThis.context.locale,
30
- fetch: globalThis.fetch,
31
- });
27
+ const data = await rootComponent.getProps(context);
32
28
  props = data.props; // overwrite public props
33
29
  }
30
+
31
+ // 2. render component
34
32
  const result = renderComponent('${moduleSpecifierToKebabCase(rootSpecifier)}', Ctor, props || {});
33
+
34
+ // 3. relay results
35
35
  globalThis.postMessage({ result, props });
36
36
  } catch(e) {
37
37
  globalThis.postMessage({ error: e });
@@ -56,8 +56,10 @@ export default function lwcSsrViewTranformer(options, { moduleBundler }) {
56
56
  const [, remain] = html.split(`<${tagName}`);
57
57
  html = [`<${tagName}`, ` ${SSR_PROPS_ATTR}="${propsId}"`, remain].join('');
58
58
  }
59
- // Overwrite the custom element with the SSRed component string
60
- stringBuilder.overwrite(startOffset, endOffset, html);
59
+ if (html.length > 0) {
60
+ // Overwrite the custom element with the SSRed component string
61
+ stringBuilder.overwrite(startOffset, endOffset, html);
62
+ }
61
63
  });
62
64
  }));
63
65
  if (Object.keys(ssrProps).length) {
@@ -4,6 +4,6 @@ interface SandboxResults {
4
4
  error?: string;
5
5
  props?: Json;
6
6
  }
7
- export default function runCode(codes: string[], context: Partial<PropsRequestContext>): Promise<SandboxResults>;
7
+ export default function runCode(codes: string[], context: PropsRequestContext): Promise<SandboxResults>;
8
8
  export {};
9
9
  //# sourceMappingURL=sandbox.d.ts.map
@@ -2,8 +2,8 @@ import { Worker } from 'worker_threads';
2
2
  const HEADER = '/* This module is generated and meant to be used in a Server context */';
3
3
  /**
4
4
  * Sandbox APIs
5
- * @param globalThis.context
6
- * context such as props, params, and locale for executing SSR
5
+ * @param globalThis.getContext
6
+ * function to provide prop request context object with properties such as props, params, and locale
7
7
  *
8
8
  * @param globalThis.fetch
9
9
  * fetch function for external data fetching
@@ -13,7 +13,7 @@ const HEADER = '/* This module is generated and meant to be used in a Server con
13
13
  */
14
14
  const WORKER_CODE_SANDBOX_APIS = [
15
15
  `const { parentPort, workerData } = require('worker_threads');`,
16
- `globalThis.context = workerData;`,
16
+ `globalThis.getContext = () => workerData;`,
17
17
  `globalThis.fetch = require('node-fetch');`,
18
18
  `globalThis.postMessage = (...args) => parentPort.postMessage(...args);`,
19
19
  ];
@@ -35,7 +35,8 @@ export async function ssrElement({ specifier, props: templateProps }, moduleBund
35
35
  ], context)
36
36
  : await runCode([code], context);
37
37
  if (error) {
38
- throw new Error(error);
38
+ console.error(`Server-side rendering for "${specifier}" failed. Falling back to client-side rendering. Reason: `, error);
39
+ return { html: '', props: undefined };
39
40
  }
40
41
  else {
41
42
  return { html: result, props };
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
- "version": "0.7.2",
7
+ "version": "0.8.0-alpha.2",
8
8
  "homepage": "https://developer.salesforce.com/docs/platform/lwr/overview",
9
9
  "repository": {
10
10
  "type": "git",
@@ -33,14 +33,14 @@
33
33
  "build/**/*.d.ts"
34
34
  ],
35
35
  "dependencies": {
36
- "@lwrjs/diagnostics": "0.7.2",
37
- "@lwrjs/shared-utils": "0.7.2"
36
+ "@lwrjs/diagnostics": "0.8.0-alpha.2",
37
+ "@lwrjs/shared-utils": "0.8.0-alpha.2"
38
38
  },
39
39
  "devDependencies": {
40
- "@lwrjs/types": "0.7.2"
40
+ "@lwrjs/types": "0.8.0-alpha.2"
41
41
  },
42
42
  "engines": {
43
43
  "node": ">=14.15.4 <19"
44
44
  },
45
- "gitHead": "1467a95aa5dcf6901e1122f6025ffd4f22237a3f"
45
+ "gitHead": "44bee038acb30418870678d886e3ded4a6afecf0"
46
46
  }