@lynx-js/web-core-server 0.13.2 → 0.13.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # @lynx-js/web-core-server
2
2
 
3
+ ## 0.13.4
4
+
5
+ ### Patch Changes
6
+
7
+ - feat: support to dump ssrID ([#919](https://github.com/lynx-family/lynx-stack/pull/919))
8
+
9
+ ## 0.13.3
10
+
11
+ ### Patch Changes
12
+
13
+ - refactor: code clean ([#897](https://github.com/lynx-family/lynx-stack/pull/897))
14
+
15
+ rename many internal apis to make logic be clear:
16
+
17
+ multi-thread: startMainWorker -> prepareMainThreadAPIs -> startMainThread -> createMainThreadContext(new MainThreadRuntime)
18
+ all-on-ui: prepareMainThreadAPIs -> startMainThread -> createMainThreadContext(new MainThreadRuntime)
19
+
20
+ - feat: support to dump ssrEncode string ([#876](https://github.com/lynx-family/lynx-stack/pull/876))
21
+
22
+ - perf: improve dom operation performance ([#881](https://github.com/lynx-family/lynx-stack/pull/881))
23
+
24
+ - code clean for offscreen-document, cut down inheritance levels
25
+ - add `appendChild` method for OffscreenElement, improve performance for append one node
26
+ - bypass some JS getter for dumping SSR string
27
+
28
+ - feat: dump dehydrate string with shadow root template ([#838](https://github.com/lynx-family/lynx-stack/pull/838))
29
+
3
30
  ## 0.13.2
4
31
 
5
32
  ### Patch Changes
@@ -1,6 +1,11 @@
1
- import { type MainThreadStartConfigs } from '@lynx-js/web-constants';
2
- interface LynxViewConfig extends Pick<MainThreadStartConfigs, 'browserConfig' | 'tagMap' | 'initData' | 'globalProps' | 'template'> {
1
+ import { type StartMainThreadContextConfig } from '@lynx-js/web-constants';
2
+ interface LynxViewConfig extends Pick<StartMainThreadContextConfig, 'browserConfig' | 'tagMap' | 'initData' | 'globalProps' | 'template'> {
3
3
  templateName?: string;
4
+ hydrateUrl: string;
5
+ injectStyles: string;
6
+ overrideElementTemplates?: Record<string, ((attributes: Record<string, string>) => string) | string>;
7
+ autoSize?: boolean;
8
+ lynxViewStyle?: string;
4
9
  }
5
10
  export declare function createLynxView(config: LynxViewConfig): Promise<{
6
11
  renderToString: () => Promise<string>;
@@ -1,33 +1,92 @@
1
- import { flushElementTreeEndpoint, mainThreadStartEndpoint, } from '@lynx-js/web-constants';
1
+ import { inShadowRootStyles, lynxUniqueIdAttribute, } from '@lynx-js/web-constants';
2
2
  import { Rpc } from '@lynx-js/web-worker-rpc';
3
- import { startMainThread } from '@lynx-js/web-worker-runtime';
3
+ import { prepareMainThreadAPIs } from '@lynx-js/web-mainthread-apis';
4
4
  import { loadTemplate } from './utils/loadTemplate.js';
5
+ import { _attributes, OffscreenDocument, OffscreenElement, } from '@lynx-js/offscreen-document/webworker';
6
+ import { templateScrollView, templateXAudioTT, templateXImage, templateFilterImage, templateXInput, templateXList, templateXOverlayNg, templateXRefreshView, templateXSwiper, templateXText, templateInlineImage, templateXTextarea, templateXViewpageNg, } from '@lynx-js/web-elements-template';
7
+ import { dumpHTMLString } from './dumpHTMLString.js';
8
+ const builtinElementTemplates = {
9
+ 'scroll-view': templateScrollView,
10
+ 'x-audio-tt': templateXAudioTT,
11
+ 'x-image': templateXImage,
12
+ 'filter-image': templateFilterImage,
13
+ 'x-input': templateXInput,
14
+ 'x-list': templateXList,
15
+ 'x-overlay-ng': templateXOverlayNg,
16
+ 'x-refresh-view': templateXRefreshView,
17
+ 'x-swiper': templateXSwiper,
18
+ 'x-text': templateXText,
19
+ 'inline-image': templateInlineImage,
20
+ 'x-textarea': templateXTextarea,
21
+ 'x-viewpage-ng': templateXViewpageNg,
22
+ };
23
+ const builtinTagTransformMap = {
24
+ 'page': 'div',
25
+ 'view': 'x-view',
26
+ 'text': 'x-text',
27
+ 'image': 'x-image',
28
+ 'list': 'x-list',
29
+ 'svg': 'x-svg',
30
+ };
31
+ // @ts-expect-error
32
+ OffscreenElement.prototype.toJSON = function toJSON() {
33
+ return {
34
+ ssrID: this[_attributes].get(lynxUniqueIdAttribute),
35
+ };
36
+ };
5
37
  export async function createLynxView(config) {
6
- const { template: rawTemplate, browserConfig, tagMap, initData, globalProps, } = config;
7
- const mainToUIChannel = new MessageChannel();
8
- const mainWithBackgroundChannel = new MessageChannel();
9
- const mainToUIMessagePort = mainToUIChannel.port2;
10
- const uiToMainRpc = new Rpc(mainToUIChannel.port1, 'main-to-ui');
11
- const { docu: offscreenDocument } = startMainThread(mainToUIMessagePort, mainWithBackgroundChannel.port2);
38
+ const { template: rawTemplate, browserConfig, tagMap, initData, globalProps, overrideElementTemplates = {}, hydrateUrl, autoSize, injectStyles, lynxViewStyle, } = config;
39
+ const template = await loadTemplate(rawTemplate, config.templateName);
12
40
  const { promise: firstPaintReadyPromise, resolve: firstPaintReady } = Promise
13
41
  .withResolvers();
14
- const template = await loadTemplate(rawTemplate, config.templateName);
15
- const mainThreadStart = uiToMainRpc.createCall(mainThreadStartEndpoint);
16
- mainThreadStart({
42
+ const mainWithBackgroundChannel = new MessageChannel();
43
+ const backgroundThreadRpc = new Rpc(mainWithBackgroundChannel.port1, 'background-thread');
44
+ const offscreenDocument = new OffscreenDocument({
45
+ onCommit: () => {
46
+ },
47
+ });
48
+ const { startMainThread } = prepareMainThreadAPIs(backgroundThreadRpc, offscreenDocument, offscreenDocument.createElement.bind(offscreenDocument), () => {
49
+ firstPaintReady();
50
+ }, () => {
51
+ // mark timing
52
+ }, () => {
53
+ // report error
54
+ });
55
+ const runtime = await startMainThread({
17
56
  template,
18
57
  initData,
19
58
  globalProps,
20
59
  browserConfig,
21
60
  nativeModulesMap: {}, // the bts won't start
22
61
  napiModulesMap: {}, // the bts won't start
23
- tagMap,
24
- });
25
- uiToMainRpc.registerHandler(flushElementTreeEndpoint, () => {
26
- firstPaintReady();
62
+ tagMap: {
63
+ ...builtinTagTransformMap,
64
+ ...tagMap,
65
+ },
27
66
  });
67
+ const elementTemplates = {
68
+ ...builtinElementTemplates,
69
+ ...overrideElementTemplates,
70
+ };
28
71
  async function renderToString() {
29
72
  await firstPaintReadyPromise;
30
- return offscreenDocument.innerHTML;
73
+ const ssrEncodeData = runtime?.ssrEncode?.();
74
+ const buffer = [];
75
+ buffer.push('<lynx-view url="', hydrateUrl, '" ssr');
76
+ if (autoSize) {
77
+ buffer.push(' height="auto" width="auto"');
78
+ }
79
+ if (lynxViewStyle) {
80
+ buffer.push(' style="', lynxViewStyle, '"');
81
+ }
82
+ if (ssrEncodeData) {
83
+ const encodeDataEncoded = ssrEncodeData ? encodeURI(ssrEncodeData) : ''; // to avoid XSS
84
+ buffer.push(' ssr-encode-data="', encodeDataEncoded, '"');
85
+ }
86
+ buffer.push('><template shadowrootmode="open">', '<style>', injectStyles, '\n', inShadowRootStyles.join('\n'), '</style>');
87
+ dumpHTMLString(buffer, offscreenDocument, elementTemplates);
88
+ buffer.push('</template>', '</lynx-view>');
89
+ return buffer.join('');
31
90
  }
32
91
  return {
33
92
  renderToString,
@@ -0,0 +1,4 @@
1
+ import { type OffscreenDocument } from '@lynx-js/offscreen-document/webworker';
2
+ type ShadowrootTemplates = ((attributes: Record<string, string>) => string) | string;
3
+ export declare function dumpHTMLString(buffer: string[], element: OffscreenDocument, shadowrootTemplates: Record<string, ShadowrootTemplates>): void;
4
+ export {};
@@ -0,0 +1,38 @@
1
+ import { _attributes, _children, innerHTML, } from '@lynx-js/offscreen-document/webworker';
2
+ function getInnerHTMLImpl(buffer, element, shadowrootTemplates) {
3
+ const localName = element.localName;
4
+ buffer.push('<');
5
+ buffer.push(localName);
6
+ for (const [key, value] of element[_attributes]) {
7
+ buffer.push(' ');
8
+ buffer.push(key);
9
+ buffer.push('="');
10
+ buffer.push(value);
11
+ buffer.push('"');
12
+ }
13
+ buffer.push('>');
14
+ const templateImpl = shadowrootTemplates[localName];
15
+ if (templateImpl) {
16
+ const template = typeof templateImpl === 'function'
17
+ ? templateImpl(Object.fromEntries(element[_attributes].entries()))
18
+ : templateImpl;
19
+ buffer.push('<template shadowrootmode="open">', template, '</template>');
20
+ }
21
+ if (element[innerHTML]) {
22
+ buffer.push(element[innerHTML]);
23
+ }
24
+ else {
25
+ for (const child of element[_children]) {
26
+ getInnerHTMLImpl(buffer, child, shadowrootTemplates);
27
+ }
28
+ }
29
+ buffer.push('</');
30
+ buffer.push(localName);
31
+ buffer.push('>');
32
+ }
33
+ export function dumpHTMLString(buffer, element, shadowrootTemplates) {
34
+ for (const child of element[_children]) {
35
+ getInnerHTMLImpl(buffer, child, shadowrootTemplates);
36
+ }
37
+ }
38
+ //# sourceMappingURL=dumpHTMLString.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lynx-js/web-core-server",
3
- "version": "0.13.2",
3
+ "version": "0.13.4",
4
4
  "private": false,
5
5
  "description": "",
6
6
  "keywords": [],
@@ -22,8 +22,10 @@
22
22
  "README.md"
23
23
  ],
24
24
  "devDependencies": {
25
- "@lynx-js/web-constants": "0.13.2",
26
- "@lynx-js/web-worker-rpc": "0.13.2",
27
- "@lynx-js/web-worker-runtime": "0.13.2"
25
+ "@lynx-js/offscreen-document": "0.1.0",
26
+ "@lynx-js/web-constants": "0.13.4",
27
+ "@lynx-js/web-elements-template": "0.7.4",
28
+ "@lynx-js/web-mainthread-apis": "0.13.4",
29
+ "@lynx-js/web-worker-rpc": "0.13.4"
28
30
  }
29
31
  }