@dooboostore/simple-boot-http-server-ssr 1.0.14 → 1.0.16
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 +98 -0
- package/dist/cjs/SimpleBootHttpSSRFactory.js.map +1 -1
- package/dist/cjs/SimpleBootHttpSSRServer.js +1 -0
- package/dist/cjs/SimpleBootHttpSSRServer.js.map +2 -2
- package/dist/cjs/bundle-entry.js +0 -4
- package/dist/cjs/bundle-entry.js.map +2 -2
- package/dist/cjs/filters/SSRDomParserFilter.js +54 -89
- package/dist/cjs/filters/SSRDomParserFilter.js.map +2 -2
- package/dist/cjs/filters/SSRFilter.js +10 -14
- package/dist/cjs/filters/SSRFilter.js.map +2 -2
- package/dist/cjs/filters/{SSRLinkDomDomFilter.js → SSRLinkDomFilter.js} +17 -21
- package/dist/cjs/filters/SSRLinkDomFilter.js.map +7 -0
- package/dist/cjs/filters/SSRSimpleWebComponentDomParserFilter.js +81 -0
- package/dist/cjs/filters/SSRSimpleWebComponentDomParserFilter.js.map +7 -0
- package/dist/cjs/filters/SSRSimpleWebComponentFilter.js +223 -0
- package/dist/cjs/filters/SSRSimpleWebComponentFilter.js.map +7 -0
- package/dist/cjs/filters/SSRWorker.js +2 -2
- package/dist/cjs/filters/SSRWorker.js.map +2 -2
- package/dist/cjs/filters/index.js +9 -3
- package/dist/cjs/filters/index.js.map +2 -2
- package/dist/cjs/index.js +16 -8
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/initializers/DomParserInitializer.js +5 -2
- package/dist/cjs/initializers/DomParserInitializer.js.map +2 -2
- package/dist/cjs/proxy/SSRDomParserFilterDataHydrationProxy.js +92 -0
- package/dist/cjs/proxy/SSRDomParserFilterDataHydrationProxy.js.map +7 -0
- package/dist/cjs/proxy/index.js +2 -8
- package/dist/cjs/proxy/index.js.map +2 -2
- package/dist/esm/SimpleBootHttpSSRFactory.js.map +1 -1
- package/dist/esm/SimpleBootHttpSSRServer.js +1 -0
- package/dist/esm/SimpleBootHttpSSRServer.js.map +2 -2
- package/dist/esm/bundle-entry.js +0 -2
- package/dist/esm/bundle-entry.js.map +2 -2
- package/dist/esm/filters/SSRDomParserFilter.js +52 -87
- package/dist/esm/filters/SSRDomParserFilter.js.map +2 -2
- package/dist/esm/filters/SSRFilter.js +7 -11
- package/dist/esm/filters/SSRFilter.js.map +2 -2
- package/dist/esm/filters/{SSRLinkDomDomFilter.js → SSRLinkDomFilter.js} +10 -14
- package/dist/esm/filters/SSRLinkDomFilter.js.map +7 -0
- package/dist/esm/filters/SSRSimpleWebComponentDomParserFilter.js +58 -0
- package/dist/esm/filters/SSRSimpleWebComponentDomParserFilter.js.map +7 -0
- package/dist/esm/filters/SSRSimpleWebComponentFilter.js +190 -0
- package/dist/esm/filters/SSRSimpleWebComponentFilter.js.map +7 -0
- package/dist/esm/filters/SSRWorker.js +1 -1
- package/dist/esm/filters/SSRWorker.js.map +2 -2
- package/dist/esm/filters/index.js +4 -1
- package/dist/esm/filters/index.js.map +2 -2
- package/dist/esm/index.js +6 -4
- package/dist/esm/index.js.map +2 -2
- package/dist/esm/initializers/DomParserInitializer.js +6 -3
- package/dist/esm/initializers/DomParserInitializer.js.map +2 -2
- package/dist/esm/proxy/SSRDomParserFilterDataHydrationProxy.js +69 -0
- package/dist/esm/proxy/SSRDomParserFilterDataHydrationProxy.js.map +7 -0
- package/dist/esm/proxy/index.js +1 -4
- package/dist/esm/proxy/index.js.map +2 -2
- package/dist/esm-bundle/dooboostore-simple-boot-http-server-ssr.esm.js +56266 -10404
- package/dist/esm-bundle/dooboostore-simple-boot-http-server-ssr.esm.js.map +4 -4
- package/dist/types/SimpleBootHttpSSRFactory.d.ts +1 -1
- package/dist/types/SimpleBootHttpSSRFactory.d.ts.map +1 -1
- package/dist/types/SimpleBootHttpSSRServer.d.ts +3 -2
- package/dist/types/SimpleBootHttpSSRServer.d.ts.map +1 -1
- package/dist/types/bundle-entry.d.ts +0 -2
- package/dist/types/bundle-entry.d.ts.map +1 -1
- package/dist/types/filters/SSRDomParserFilter.d.ts +12 -18
- package/dist/types/filters/SSRDomParserFilter.d.ts.map +1 -1
- package/dist/types/filters/SSRFilter.d.ts +1 -1
- package/dist/types/filters/SSRFilter.d.ts.map +1 -1
- package/dist/types/filters/{SSRLinkDomDomFilter.d.ts → SSRLinkDomFilter.d.ts} +6 -6
- package/dist/types/filters/SSRLinkDomFilter.d.ts.map +1 -0
- package/dist/types/filters/SSRSimpleWebComponentDomParserFilter.d.ts +37 -0
- package/dist/types/filters/SSRSimpleWebComponentDomParserFilter.d.ts.map +1 -0
- package/dist/types/filters/SSRSimpleWebComponentFilter.d.ts +57 -0
- package/dist/types/filters/SSRSimpleWebComponentFilter.d.ts.map +1 -0
- package/dist/types/filters/SSRWorker.d.ts +1 -1
- package/dist/types/filters/SSRWorker.d.ts.map +1 -1
- package/dist/types/filters/index.d.ts +4 -1
- package/dist/types/filters/index.d.ts.map +1 -1
- package/dist/types/index.d.ts +6 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/initializers/DomParserInitializer.d.ts +2 -0
- package/dist/types/initializers/DomParserInitializer.d.ts.map +1 -1
- package/dist/types/proxy/SSRDomParserFilterDataHydrationProxy.d.ts +7 -0
- package/dist/types/proxy/SSRDomParserFilterDataHydrationProxy.d.ts.map +1 -0
- package/dist/types/proxy/index.d.ts +1 -4
- package/dist/types/proxy/index.d.ts.map +1 -1
- package/dist/umd-bundle/dooboostore-simple-boot-http-server-ssr.umd.js +56265 -10408
- package/dist/umd-bundle/dooboostore-simple-boot-http-server-ssr.umd.js.map +4 -4
- package/package.json +22 -15
- package/src/SimpleBootHttpSSRFactory.ts +1 -1
- package/src/SimpleBootHttpSSRServer.ts +5 -4
- package/src/bundle-entry.ts +0 -2
- package/src/filters/SSRDomParserFilter.ts +113 -126
- package/src/filters/SSRFilter.ts +7 -12
- package/src/filters/{SSRLinkDomDomFilter.ts → SSRLinkDomFilter.ts} +10 -15
- package/src/filters/SSRSimpleWebComponentDomParserFilter.ts +106 -0
- package/src/filters/SSRSimpleWebComponentFilter.ts +306 -0
- package/src/filters/SSRWorker.ts +1 -2
- package/src/filters/index.ts +5 -2
- package/src/index.ts +6 -9
- package/src/initializers/DomParserInitializer.ts +9 -2
- package/src/proxy/SSRDomParserFilterDataHydrationProxy.ts +63 -0
- package/src/proxy/index.ts +1 -4
- package/tsconfig.json +1 -0
- package/README.MD +0 -36
- package/dist/cjs/codes/HttpHeaders.js +0 -41
- package/dist/cjs/codes/HttpHeaders.js.map +0 -7
- package/dist/cjs/codes/Mimes.js +0 -33
- package/dist/cjs/codes/Mimes.js.map +0 -7
- package/dist/cjs/codes/index.js +0 -24
- package/dist/cjs/codes/index.js.map +0 -7
- package/dist/cjs/decorators/LoadAroundBefore.js +0 -54
- package/dist/cjs/decorators/LoadAroundBefore.js.map +0 -7
- package/dist/cjs/decorators/SaveAroundAfter.js +0 -53
- package/dist/cjs/decorators/SaveAroundAfter.js.map +0 -7
- package/dist/cjs/decorators/index.js +0 -24
- package/dist/cjs/decorators/index.js.map +0 -7
- package/dist/cjs/filters/IntentSchemeFilter.js +0 -92
- package/dist/cjs/filters/IntentSchemeFilter.js.map +0 -7
- package/dist/cjs/filters/SSRLinkDomDomFilter.js.map +0 -7
- package/dist/cjs/proxy/IntentSchemeFrontProxy.js +0 -87
- package/dist/cjs/proxy/IntentSchemeFrontProxy.js.map +0 -7
- package/dist/cjs/proxy/IntentSchemeServerProxy.js +0 -67
- package/dist/cjs/proxy/IntentSchemeServerProxy.js.map +0 -7
- package/dist/cjs/proxy/SymbolIntentApiServiceProxy.js +0 -138
- package/dist/cjs/proxy/SymbolIntentApiServiceProxy.js.map +0 -7
- package/dist/cjs/proxy/SymbolIntentApiServiceProxyBase.js +0 -35
- package/dist/cjs/proxy/SymbolIntentApiServiceProxyBase.js.map +0 -7
- package/dist/esm/codes/HttpHeaders.js +0 -17
- package/dist/esm/codes/HttpHeaders.js.map +0 -7
- package/dist/esm/codes/Mimes.js +0 -10
- package/dist/esm/codes/Mimes.js.map +0 -7
- package/dist/esm/codes/index.js +0 -3
- package/dist/esm/codes/index.js.map +0 -7
- package/dist/esm/decorators/LoadAroundBefore.js +0 -31
- package/dist/esm/decorators/LoadAroundBefore.js.map +0 -7
- package/dist/esm/decorators/SaveAroundAfter.js +0 -29
- package/dist/esm/decorators/SaveAroundAfter.js.map +0 -7
- package/dist/esm/decorators/index.js +0 -3
- package/dist/esm/decorators/index.js.map +0 -7
- package/dist/esm/filters/IntentSchemeFilter.js +0 -69
- package/dist/esm/filters/IntentSchemeFilter.js.map +0 -7
- package/dist/esm/filters/SSRLinkDomDomFilter.js.map +0 -7
- package/dist/esm/proxy/IntentSchemeFrontProxy.js +0 -64
- package/dist/esm/proxy/IntentSchemeFrontProxy.js.map +0 -7
- package/dist/esm/proxy/IntentSchemeServerProxy.js +0 -44
- package/dist/esm/proxy/IntentSchemeServerProxy.js.map +0 -7
- package/dist/esm/proxy/SymbolIntentApiServiceProxy.js +0 -115
- package/dist/esm/proxy/SymbolIntentApiServiceProxy.js.map +0 -7
- package/dist/esm/proxy/SymbolIntentApiServiceProxyBase.js +0 -12
- package/dist/esm/proxy/SymbolIntentApiServiceProxyBase.js.map +0 -7
- package/dist/types/codes/HttpHeaders.d.ts +0 -45
- package/dist/types/codes/HttpHeaders.d.ts.map +0 -1
- package/dist/types/codes/Mimes.d.ts +0 -31
- package/dist/types/codes/Mimes.d.ts.map +0 -1
- package/dist/types/codes/index.d.ts +0 -3
- package/dist/types/codes/index.d.ts.map +0 -1
- package/dist/types/decorators/LoadAroundBefore.d.ts +0 -2
- package/dist/types/decorators/LoadAroundBefore.d.ts.map +0 -1
- package/dist/types/decorators/SaveAroundAfter.d.ts +0 -3
- package/dist/types/decorators/SaveAroundAfter.d.ts.map +0 -1
- package/dist/types/decorators/index.d.ts +0 -3
- package/dist/types/decorators/index.d.ts.map +0 -1
- package/dist/types/filters/IntentSchemeFilter.d.ts +0 -20
- package/dist/types/filters/IntentSchemeFilter.d.ts.map +0 -1
- package/dist/types/filters/SSRLinkDomDomFilter.d.ts.map +0 -1
- package/dist/types/proxy/IntentSchemeFrontProxy.d.ts +0 -4
- package/dist/types/proxy/IntentSchemeFrontProxy.d.ts.map +0 -1
- package/dist/types/proxy/IntentSchemeServerProxy.d.ts +0 -4
- package/dist/types/proxy/IntentSchemeServerProxy.d.ts.map +0 -1
- package/dist/types/proxy/SymbolIntentApiServiceProxy.d.ts +0 -18
- package/dist/types/proxy/SymbolIntentApiServiceProxy.d.ts.map +0 -1
- package/dist/types/proxy/SymbolIntentApiServiceProxyBase.d.ts +0 -5
- package/dist/types/proxy/SymbolIntentApiServiceProxyBase.d.ts.map +0 -1
- package/src/codes/HttpHeaders.ts +0 -17
- package/src/codes/Mimes.ts +0 -6
- package/src/codes/index.ts +0 -2
- package/src/decorators/LoadAroundBefore.ts +0 -28
- package/src/decorators/SaveAroundAfter.ts +0 -27
- package/src/decorators/index.ts +0 -2
- package/src/filters/IntentSchemeFilter.ts +0 -69
- package/src/proxy/IntentSchemeFrontProxy.ts +0 -67
- package/src/proxy/IntentSchemeServerProxy.ts +0 -35
- package/src/proxy/SymbolIntentApiServiceProxy.ts +0 -115
- package/src/proxy/SymbolIntentApiServiceProxyBase.ts +0 -19
package/README.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# @dooboostore/simple-boot-http-server-ssr
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@dooboostore/simple-boot-http-server-ssr)
|
|
4
|
+
[](https://github.com/dooboostore-develop/packages/actions/workflows/main.yaml)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
7
|
+
`@dooboostore/simple-boot-http-server-ssr` provides a powerful **Server-Side Rendering (SSR)** environment by seamlessly integrating `@dooboostore/simple-boot-front` and `@dooboostore/simple-boot-http-server`.
|
|
8
|
+
|
|
9
|
+
By utilizing JSDOM, it creates a virtual DOM environment on the server, executing the same frontend code to deliver fully rendered HTML to users instantly.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 🚀 Key Features
|
|
14
|
+
|
|
15
|
+
- **Seamless SSR**: Render your SPA on the server without code modifications to maximize SEO and First Contentful Paint (FCP).
|
|
16
|
+
- **JSDOM-based Rendering**: Emulate browser APIs in a Node.js environment to execute frontend components.
|
|
17
|
+
- **Component Pooling**: Optimize resource management by pooling SSR instances to handle concurrent requests efficiently.
|
|
18
|
+
- **Automatic Data Hydration**: Serialize server-fetched data into the HTML, preventing redundant API calls during client-side hydration.
|
|
19
|
+
- **Isomorphic Architecture**: Maintain a single codebase for routing, services, and components shared between server and client.
|
|
20
|
+
- **SWC Optimization**: Dedicated filters for `@dooboostore/simple-web-component` to automate component registration and rendering.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 📦 Installation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pnpm add @dooboostore/simple-boot-http-server-ssr @dooboostore/simple-web-component jsdom
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## 💻 Core Usage
|
|
33
|
+
|
|
34
|
+
### 1. Universal Bootfactory (bootfactory.ts)
|
|
35
|
+
Define a shared function to initialize the application on both server and client.
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
export default (window: Window, urlPath?: string) => {
|
|
39
|
+
// Register components
|
|
40
|
+
register(window, [MyComponent, MyPage]);
|
|
41
|
+
|
|
42
|
+
const appElement = window.document.querySelector('#app');
|
|
43
|
+
if (appElement?.connect) {
|
|
44
|
+
const isClient = typeof window !== 'undefined' && window === globalThis.window;
|
|
45
|
+
|
|
46
|
+
appElement.connect({
|
|
47
|
+
rootRouter: RootRouter,
|
|
48
|
+
path: urlPath ?? '/',
|
|
49
|
+
window,
|
|
50
|
+
// Server renders in 'direct' mode, Client hydrates in 'swap' mode
|
|
51
|
+
connectMode: isClient ? 'swap' : 'direct'
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
return appElement;
|
|
55
|
+
};
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 2. Backend Configuration (SSR Filter)
|
|
59
|
+
Add `SSRSimpleWebComponentFilter` to your server configuration to enable SSR.
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
const swcFilter = new SSRSimpleWebComponentFilter({
|
|
63
|
+
frontDistPath: './dist-client',
|
|
64
|
+
frontDistIndexFileName: 'index.html',
|
|
65
|
+
registerComponents: async (window: any) => {
|
|
66
|
+
// Initialize app in server-side virtual DOM
|
|
67
|
+
bootfactory(window, window.location.pathname);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const server = new SimpleBootHttpSSRServer(
|
|
72
|
+
new HttpSSRServerOption({
|
|
73
|
+
filters: [new ResourceFilter('./dist-client'), swcFilter]
|
|
74
|
+
})
|
|
75
|
+
);
|
|
76
|
+
server.run();
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 🌊 Data Hydration
|
|
82
|
+
Automate the process of safely transferring async data from server to client.
|
|
83
|
+
|
|
84
|
+
1. **Server Side**: Fetches data and embeds it as JSON within the HTML.
|
|
85
|
+
2. **Client Side**: Detects embedded data on load and restores the initial state.
|
|
86
|
+
3. **Result**: Provides a fast UI for users while reducing network load.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## 📖 Learn More
|
|
91
|
+
Check out the detailed guides and tutorials in the `document` folder.
|
|
92
|
+
- [SSR Basics & JSDOM Usage](https://github.com/dooboostore-develop/packages/tree/main/simple-boot-http-server-ssr/document/Create%20a%20SSR%20Server%20Application%20Framework/02_chapter1_ssr_basics_jsdom.md)
|
|
93
|
+
- [Data Hydration Guide](https://github.com/dooboostore-develop/packages/tree/main/simple-boot-http-server-ssr/document/Create%20a%20SSR%20Server%20Application%20Framework/04_chapter3_data_hydration.md)
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## License
|
|
98
|
+
[MIT License](LICENSE.md)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/SimpleBootHttpSSRFactory.ts"],
|
|
4
|
-
"sourcesContent": ["import { SimpleBootFront } from '@dooboostore/simple-boot-front/SimpleBootFront';\nimport { ConstructorType } from '@dooboostore/core
|
|
4
|
+
"sourcesContent": ["import { SimpleBootFront } from '@dooboostore/simple-boot-front/SimpleBootFront';\nimport { ConstructorType } from '@dooboostore/core';\nimport { SimFrontOption } from '@dooboostore/simple-boot-front/option/SimFrontOption';\nexport abstract class SimpleBootHttpSSRFactory {\n public abstract factory(simFrontOption: SimFrontOption, using: (ConstructorType<any> | Function)[], domExcludes: ConstructorType<any>[]): Promise<SimpleBootFront> ;\n\n public async create(simFrontOption: SimFrontOption, using: (ConstructorType<any> | Function)[] = [], domExcludes: ConstructorType<any>[] = []): Promise<SimpleBootFront> {\n const front = await this.factory(simFrontOption, using, domExcludes);\n return front;\n }\n}\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGO,MAAe,yBAAyB;AAAA,EAG3C,MAAa,OAAO,gBAAgC,QAA6C,CAAC,GAAG,cAAsC,CAAC,GAA6B;AACrK,UAAM,QAAQ,MAAM,KAAK,QAAQ,gBAAgB,OAAO,WAAW;AACnE,WAAO;AAAA,EACX;AACJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -27,6 +27,7 @@ class SimpleBootHttpSSRServer extends import_SimpleBootHttpServer.SimpleBootHttp
|
|
|
27
27
|
}
|
|
28
28
|
run(otherInstanceSim) {
|
|
29
29
|
const oi = /* @__PURE__ */ new Map();
|
|
30
|
+
oi.set(SimpleBootHttpSSRServer, this);
|
|
30
31
|
otherInstanceSim?.forEach((value, key) => oi.set(key, value));
|
|
31
32
|
return super.run(oi);
|
|
32
33
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/SimpleBootHttpSSRServer.ts"],
|
|
4
|
-
"sourcesContent": ["import { SimpleBootHttpServer } from '@dooboostore/simple-boot-http-server/SimpleBootHttpServer';\
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kCAAqC;AAK9B,MAAM,gCAAgC,iDAAqB;AAAA,EAChE,YAAY,QAA8B;AACxC,UAAM,MAAM;AAAA,EACd;AAAA,EAEA,IAAI,
|
|
4
|
+
"sourcesContent": ["import { SimpleBootHttpServer } from '@dooboostore/simple-boot-http-server/SimpleBootHttpServer';\nimport { HttpSSRServerOption } from './option/HttpSSRServerOption';\nimport { ConstructorType } from '@dooboostore/core';\nimport {SimConfig} from \"@dooboostore/simple-boot/decorators/SimDecorator\";\n\nexport class SimpleBootHttpSSRServer extends SimpleBootHttpServer {\n constructor(option?: HttpSSRServerOption) {\n super(option)\n }\n\n run(otherInstanceSim?: Map<ConstructorType<any> | Function | SimConfig | symbol, any>) {\n const oi = new Map<ConstructorType<any> | Function | SimConfig | symbol, any>();\n oi.set(SimpleBootHttpSSRServer, this);\n otherInstanceSim?.forEach((value, key) => oi.set(key, value));\n return super.run(oi);\n }\n\n // TODO: \uB098\uC911\uC5D0 \uBB50\uB77C\uB3C4..\n stop(){\n\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kCAAqC;AAK9B,MAAM,gCAAgC,iDAAqB;AAAA,EAChE,YAAY,QAA8B;AACxC,UAAM,MAAM;AAAA,EACd;AAAA,EAEA,IAAI,kBAAmF;AACrF,UAAM,KAAK,oBAAI,IAA+D;AAC9E,OAAG,IAAI,yBAAyB,IAAI;AACpC,sBAAkB,QAAQ,CAAC,OAAO,QAAQ,GAAG,IAAI,KAAK,KAAK,CAAC;AAC5D,WAAO,MAAM,IAAI,EAAE;AAAA,EACrB;AAAA;AAAA,EAGA,OAAM;AAAA,EAEN;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/cjs/bundle-entry.js
CHANGED
|
@@ -14,8 +14,6 @@ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "defau
|
|
|
14
14
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
15
|
var bundle_entry_exports = {};
|
|
16
16
|
module.exports = __toCommonJS(bundle_entry_exports);
|
|
17
|
-
__reExport(bundle_entry_exports, require("./codes"), module.exports);
|
|
18
|
-
__reExport(bundle_entry_exports, require("./decorators"), module.exports);
|
|
19
17
|
__reExport(bundle_entry_exports, require("./filters"), module.exports);
|
|
20
18
|
__reExport(bundle_entry_exports, require("./initializers"), module.exports);
|
|
21
19
|
__reExport(bundle_entry_exports, require("./option"), module.exports);
|
|
@@ -24,8 +22,6 @@ __reExport(bundle_entry_exports, require("./SimpleBootHttpSSRFactory"), module.e
|
|
|
24
22
|
__reExport(bundle_entry_exports, require("./SimpleBootHttpSSRServer"), module.exports);
|
|
25
23
|
// Annotate the CommonJS export names for ESM import in node:
|
|
26
24
|
0 && (module.exports = {
|
|
27
|
-
...require("./codes"),
|
|
28
|
-
...require("./decorators"),
|
|
29
25
|
...require("./filters"),
|
|
30
26
|
...require("./initializers"),
|
|
31
27
|
...require("./option"),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/bundle-entry.ts"],
|
|
4
|
-
"sourcesContent": ["export * from './
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;AAAA;AAAA;AAAA,iCAAc,
|
|
4
|
+
"sourcesContent": ["export * from './filters';\nexport * from './initializers';\nexport * from './option';\nexport * from './proxy';\nexport * from './SimpleBootHttpSSRFactory';\nexport * from './SimpleBootHttpSSRServer';"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;AAAA;AAAA;AAAA,iCAAc,sBAAd;AACA,iCAAc,2BADd;AAEA,iCAAc,qBAFd;AAGA,iCAAc,oBAHd;AAIA,iCAAc,uCAJd;AAKA,iCAAc,sCALd;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -20,121 +20,99 @@ __export(SSRDomParserFilter_exports, {
|
|
|
20
20
|
SSRDomParserFilter: () => SSRDomParserFilter
|
|
21
21
|
});
|
|
22
22
|
module.exports = __toCommonJS(SSRDomParserFilter_exports);
|
|
23
|
+
var import_RequestResponse = require("@dooboostore/simple-boot-http-server/models/RequestResponse");
|
|
23
24
|
var import_HttpHeaders = require("@dooboostore/simple-boot-http-server/codes/HttpHeaders");
|
|
25
|
+
var import_core = require("@dooboostore/core");
|
|
24
26
|
var import_Mimes = require("@dooboostore/simple-boot-http-server/codes/Mimes");
|
|
25
27
|
var import_HttpStatus = require("@dooboostore/simple-boot-http-server/codes/HttpStatus");
|
|
26
|
-
var import_AsyncBlockingQueue = require("@dooboostore/core/queues/AsyncBlockingQueue");
|
|
27
|
-
var import_RandomUtils = require("@dooboostore/core/random/RandomUtils");
|
|
28
28
|
var import_NotFoundError = require("@dooboostore/simple-boot-http-server/errors/NotFoundError");
|
|
29
|
-
var
|
|
30
|
-
var import_filter = require("@dooboostore/core/message/operators/filter");
|
|
31
|
-
var import_first = require("@dooboostore/core/message/operators/first");
|
|
32
|
-
var import_firstValueFrom = require("@dooboostore/core/message/internal/firstValueFrom");
|
|
33
|
-
var import_Promises = require("@dooboostore/core/promise/Promises");
|
|
29
|
+
var import_dom_render = require("@dooboostore/dom-render");
|
|
34
30
|
var import_DomParserInitializer = require("../initializers/DomParserInitializer");
|
|
35
31
|
class SSRDomParserFilter {
|
|
32
|
+
// private poolGeneration = 0;
|
|
33
|
+
// private intervalId?: NodeJS.Timeout;
|
|
36
34
|
constructor(config, otherInstanceSim) {
|
|
37
35
|
this.config = config;
|
|
38
36
|
this.otherInstanceSim = otherInstanceSim;
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
// private simpleBootFrontPool: SimpleBootFront[] = [];
|
|
38
|
+
// private simpleBootFrontQueue = new AsyncBlockingQueue<SimpleBootFront>();
|
|
41
39
|
// private indexHTML: string;
|
|
42
40
|
this.welcomUrl = "http://localhost";
|
|
43
|
-
this.poolGeneration = 0;
|
|
44
41
|
config.frontDistIndexFileName = config.frontDistIndexFileName || "index.html";
|
|
45
42
|
}
|
|
46
43
|
async onInit(app) {
|
|
47
|
-
for (let i = 0; i < this.config.poolOption.min; i++) {
|
|
48
|
-
await this.pushQueue();
|
|
49
|
-
}
|
|
50
|
-
if (this.config.poolOption.clearIntervalTime && this.config.poolOption.clearIntervalTime > 0) {
|
|
51
|
-
this.intervalId = setInterval(() => {
|
|
52
|
-
this.poolGeneration++;
|
|
53
|
-
}, this.config.poolOption.clearIntervalTime);
|
|
54
|
-
}
|
|
55
44
|
}
|
|
56
45
|
async onDestroy() {
|
|
57
|
-
if (this.intervalId) {
|
|
58
|
-
clearInterval(this.intervalId);
|
|
59
|
-
}
|
|
60
|
-
this.simpleBootFrontPool.forEach((front) => {
|
|
61
|
-
front.jsdom?.window.close();
|
|
62
|
-
});
|
|
63
|
-
this.simpleBootFrontPool = [];
|
|
64
46
|
}
|
|
65
|
-
async makePage() {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
{ url: this.welcomUrl }
|
|
70
|
-
).run();
|
|
71
|
-
return windowPromise;
|
|
47
|
+
async makePage(url = this.welcomUrl) {
|
|
48
|
+
const domParserInitializer = new import_DomParserInitializer.DomParserInitializer(this.config.frontDistPath, this.config.frontDistIndexFileName || "index.html", { url });
|
|
49
|
+
const window = await domParserInitializer.run();
|
|
50
|
+
return { window, domParserInitializer };
|
|
72
51
|
}
|
|
73
|
-
async makeFront(window) {
|
|
74
|
-
const name =
|
|
52
|
+
async makeFront(window, otherInstanceSim) {
|
|
53
|
+
const name = import_core.RandomUtils.uuid();
|
|
75
54
|
window.ssrUse = false;
|
|
76
|
-
const option = this.config.factorySimFrontOption(
|
|
77
|
-
const
|
|
78
|
-
simpleBootFront.
|
|
79
|
-
|
|
55
|
+
const option = this.config.factorySimFrontOption(import_dom_render.DomRenderProxy.final(window));
|
|
56
|
+
const domExcludes = [import_RequestResponse.RequestResponse, ...this.config.domExcludes || []];
|
|
57
|
+
const simpleBootFront = await this.config.factory.create(option, this.config.using, domExcludes);
|
|
58
|
+
otherInstanceSim ??= /* @__PURE__ */ new Map();
|
|
59
|
+
this.otherInstanceSim?.forEach((v, k) => otherInstanceSim.set(k, v));
|
|
60
|
+
simpleBootFront.run(otherInstanceSim);
|
|
80
61
|
return simpleBootFront;
|
|
81
62
|
}
|
|
82
|
-
enqueueFrontApp(simpleBootFront) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
63
|
+
// enqueueFrontApp(simpleBootFront: SimpleBootFront) {
|
|
64
|
+
// // this.simpleBootFrontPool.set(simpleBootFront.option.name!, simpleBootFront);
|
|
65
|
+
// this.simpleBootFrontPool.push(simpleBootFront);
|
|
66
|
+
// this.simpleBootFrontQueue.enqueue(simpleBootFront);
|
|
67
|
+
// }
|
|
68
|
+
//
|
|
69
|
+
// async pushQueue() {
|
|
70
|
+
// if (this.simpleBootFrontPool.length < this.config.poolOption.max) {
|
|
71
|
+
// this.enqueueFrontApp(await this.makeFront(await this.makePage()));
|
|
72
|
+
// }
|
|
73
|
+
// }
|
|
91
74
|
async proceedBefore({ rr, app }) {
|
|
92
75
|
if (this.config.ssrExcludeFilter?.(rr)) {
|
|
93
76
|
return false;
|
|
94
77
|
}
|
|
95
78
|
if (rr.reqHasAcceptHeader(import_Mimes.Mimes.TextHtml) || rr.reqHasAcceptHeader(import_Mimes.Mimes.All)) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
const
|
|
79
|
+
const url = rr.reqUrlObj({ host: "localhost" });
|
|
80
|
+
const targetUrl = url.toString() ?? this.welcomUrl;
|
|
81
|
+
const { window, domParserInitializer } = await this.makePage(targetUrl);
|
|
82
|
+
const otherSim = /* @__PURE__ */ new Map();
|
|
83
|
+
otherSim.set(import_RequestResponse.RequestResponse, rr);
|
|
84
|
+
const simpleBootFront = await this.makeFront(window, otherSim);
|
|
100
85
|
try {
|
|
101
86
|
simpleBootFront.option.window.ssrUse = true;
|
|
102
|
-
delete simpleBootFront.option.window.server_side_data;
|
|
103
|
-
const url = rr.reqUrlObj({ host: "localhost" });
|
|
104
87
|
if (this.config.simpleBootFront?.notFoundError) {
|
|
105
|
-
const intent = await simpleBootFront.
|
|
88
|
+
const intent = await simpleBootFront.routingRouterModule(url.pathname);
|
|
106
89
|
if (intent.module === void 0 && !intent.getRouterPathData(rr.reqUrlPathName)) {
|
|
107
90
|
throw new import_NotFoundError.NotFoundError({ message: `Not Found: ${rr.reqUrlPathName}` });
|
|
108
91
|
}
|
|
109
92
|
}
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
(it) => it.triggerPoint === "end" && typeof it.routerModule.intent.uri === "string" && targetUrl.endsWith(it.routerModule.intent.uri)
|
|
117
|
-
),
|
|
93
|
+
const data = await import_core.MessageInternal.firstValueFrom(
|
|
94
|
+
simpleBootFront.routingObservable.pipe(
|
|
95
|
+
import_core.MessageOperator.filter((it) => {
|
|
96
|
+
const sw = it.triggerPoint === "end" && typeof it.routerModule.intent.uri === "string" && targetUrl.endsWith(it.routerModule.intent.uri);
|
|
97
|
+
return sw;
|
|
98
|
+
}),
|
|
118
99
|
// delay(1000),
|
|
119
|
-
|
|
100
|
+
import_core.MessageOperator.first()
|
|
120
101
|
)
|
|
121
102
|
);
|
|
122
|
-
|
|
103
|
+
simpleBootFront.writeDataHydration();
|
|
104
|
+
simpleBootFront.clearDataHydration();
|
|
123
105
|
const html = this.makeHTML(simpleBootFront);
|
|
124
106
|
await this.writeOkHtmlAndEnd({ rr }, html);
|
|
125
107
|
} finally {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}
|
|
135
|
-
this.pushQueue();
|
|
136
|
-
} else {
|
|
137
|
-
this.simpleBootFrontQueue.enqueue(simpleBootFront);
|
|
108
|
+
try {
|
|
109
|
+
simpleBootFront.option.window.ssrUse = false;
|
|
110
|
+
window.close();
|
|
111
|
+
simpleBootFront.onDestroy();
|
|
112
|
+
simpleBootFront.option.window?.close?.();
|
|
113
|
+
domParserInitializer.destroy();
|
|
114
|
+
} catch (e) {
|
|
115
|
+
console.log("eeeeee", e);
|
|
138
116
|
}
|
|
139
117
|
}
|
|
140
118
|
return false;
|
|
@@ -155,19 +133,6 @@ class SSRDomParserFilter {
|
|
|
155
133
|
html = "<!DOCTYPE html>" + html;
|
|
156
134
|
}
|
|
157
135
|
html = html.replace(/\$\{[\s\S]*?\}\$/g, "");
|
|
158
|
-
const serverSideData = simpleBootFront.option.window.server_side_data;
|
|
159
|
-
if (serverSideData) {
|
|
160
|
-
const data = Object.entries(serverSideData).map(([k, v]) => {
|
|
161
|
-
if (typeof v === "string") {
|
|
162
|
-
return `window.server_side_data.${k} = ${v}`;
|
|
163
|
-
} else {
|
|
164
|
-
return `window.server_side_data.${k} = ${JSON.stringify(v)}`;
|
|
165
|
-
}
|
|
166
|
-
}).join(";");
|
|
167
|
-
if (data) {
|
|
168
|
-
html = html.replace("</head>", `<script> window.server_side_data={}; ${data}; </script></head>`);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
136
|
return html;
|
|
172
137
|
}
|
|
173
138
|
async writeOkHtmlAndEnd({ rr, status = import_HttpStatus.HttpStatus.Ok }, html) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/filters/SSRDomParserFilter.ts"],
|
|
4
|
-
"sourcesContent": ["import { RequestResponse } from '@dooboostore/simple-boot-http-server/models/RequestResponse';\nimport { HttpHeaders } from '@dooboostore/simple-boot-http-server/codes/HttpHeaders';\nimport { SimpleBootHttpSSRFactory } from '../SimpleBootHttpSSRFactory';\nimport { ConstructorType } from '@dooboostore/core/types';\nimport { Filter } from '@dooboostore/simple-boot-http-server/filters/Filter';\nimport { Mimes } from '@dooboostore/simple-boot-http-server/codes/Mimes';\nimport { HttpStatus } from '@dooboostore/simple-boot-http-server/codes/HttpStatus';\nimport { SimpleBootHttpServer } from '@dooboostore/simple-boot-http-server/SimpleBootHttpServer';\nimport { SimFrontOption } from '@dooboostore/simple-boot-front/option/SimFrontOption';\nimport { SimpleBootFront } from '@dooboostore/simple-boot-front/SimpleBootFront';\nimport { AsyncBlockingQueue } from '@dooboostore/core/queues/AsyncBlockingQueue';\nimport { RandomUtils } from '@dooboostore/core/random/RandomUtils';\nimport * as JSDOM from 'jsdom';\nimport { NotFoundError } from '@dooboostore/simple-boot-http-server/errors/NotFoundError';\nimport { DomRenderProxy } from '@dooboostore/dom-render/DomRenderProxy';\nimport { filter } from '@dooboostore/core/message/operators/filter';\nimport { first } from '@dooboostore/core/message/operators/first';\nimport { delay } from '@dooboostore/core/message/operators/delay';\nimport { firstValueFrom } from '@dooboostore/core/message/internal/firstValueFrom';\nimport { parseHTML } from 'linkedom';\nimport {Promises} from '@dooboostore/core/promise/Promises';\nimport { DomParserInitializer } from '../initializers/DomParserInitializer';\n\nexport type FactoryAndParams = {\n frontDistPath: string;\n frontDistIndexFileName?: string;\n factorySimFrontOption: (window: any) => SimFrontOption;\n factory: SimpleBootHttpSSRFactory;\n poolOption: {\n max: number;\n min: number;\n clearIntervalTime?: number;\n };\n using: ConstructorType<any>[];\n domExcludes?: ConstructorType<any>[];\n ssrExcludeFilter?: (rr: RequestResponse) => boolean;\n simpleBootFront?: {\n notFoundError?: boolean;\n };\n};\n\nexport class SSRDomParserFilter implements Filter {\n private simpleBootFrontPool: SimpleBootFront[] = [];\n private simpleBootFrontQueue = new AsyncBlockingQueue<SimpleBootFront>();\n // private indexHTML: string;\n private welcomUrl = 'http://localhost';\n private poolGeneration = 0;\n private intervalId?: NodeJS.Timeout;\n\n constructor(\n public config: FactoryAndParams,\n public otherInstanceSim?: Map<ConstructorType<any>, any>\n ) {\n config.frontDistIndexFileName = config.frontDistIndexFileName || 'index.html';\n // this.indexHTML = JsdomInitializer.loadFile(this.config.frontDistPath, config.frontDistIndexFileName);\n }\n\n async onInit(app: SimpleBootHttpServer) {\n for (let i = 0; i < this.config.poolOption.min; i++) {\n await this.pushQueue();\n }\n\n if (this.config.poolOption.clearIntervalTime && this.config.poolOption.clearIntervalTime > 0) {\n this.intervalId = setInterval(() => {\n this.poolGeneration++;\n }, this.config.poolOption.clearIntervalTime);\n }\n }\n\n async onDestroy() {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n }\n // this.simpleBootFrontQueue.clear();\n this.simpleBootFrontPool.forEach(front => {\n (front as any).jsdom?.window.close();\n });\n this.simpleBootFrontPool = [];\n }\n\n async makePage() {\n let windowPromise = await new DomParserInitializer(\n this.config.frontDistPath,\n this.config.frontDistIndexFileName || 'index.html',\n { url: this.welcomUrl }\n ).run();\n return windowPromise;\n // const jsdom = await new JsdomInitializer(\n // this.config.frontDistPath,\n // this.config.frontDistIndexFileName || 'index.html',\n // { url: this.welcomUrl }\n // ).run();\n // return jsdom;\n }\n\n async makeFront(window: Window) {\n const name = RandomUtils.uuid();\n (window as any).ssrUse = false;\n const option = this.config.factorySimFrontOption(DomRenderProxy.final(window));\n const simpleBootFront = await this.config.factory.create(option, this.config.using, this.config.domExcludes);\n simpleBootFront.run(this.otherInstanceSim);\n (simpleBootFront as any).generation = this.poolGeneration;\n return simpleBootFront;\n }\n\n enqueueFrontApp(simpleBootFront: SimpleBootFront) {\n // this.simpleBootFrontPool.set(simpleBootFront.option.name!, simpleBootFront);\n this.simpleBootFrontPool.push(simpleBootFront);\n this.simpleBootFrontQueue.enqueue(simpleBootFront);\n }\n async pushQueue() {\n if (this.simpleBootFrontPool.length < this.config.poolOption.max) {\n this.enqueueFrontApp(await this.makeFront(await this.makePage()));\n }\n }\n\n async proceedBefore({ rr, app }: { rr: RequestResponse; app: SimpleBootHttpServer; carrier: Map<string, any> }) {\n if (this.config.ssrExcludeFilter?.(rr)) {\n return false;\n }\n if (rr.reqHasAcceptHeader(Mimes.TextHtml) || rr.reqHasAcceptHeader(Mimes.All)) {\n if (this.simpleBootFrontQueue.isEmpty()) {\n await this.pushQueue();\n }\n const simpleBootFront = await this.simpleBootFrontQueue.dequeue();\n try {\n (simpleBootFront.option.window as any).ssrUse = true;\n delete (simpleBootFront.option.window as any).server_side_data;\n const url = rr.reqUrlObj({ host: 'localhost' });\n if (this.config.simpleBootFront?.notFoundError) {\n // intent router check first\n const intent = await simpleBootFront.getIntent(url.pathname);\n // route\uB97C \uBABB\uCC3E\uC740\uC0C1\uD0DC\uC5D0\uC11C router path\uAE4C\uC9C0 \uC548\uB9DE\uC73C\uBA74 404 \uCC98\uB9AC\uD55C\uB2E4. route\uB791 router\uB791 \uB2E4\uB974\uB2C8\uAE50 \uD5DB\uAC08\uB9AC\uC9C0\uB9D0\uB3C4\uB85D\n if (intent.module === undefined && !intent.getRouterPathData(rr.reqUrlPathName)) {\n throw new NotFoundError({ message: `Not Found: ${rr.reqUrlPathName}` });\n }\n }\n\n // runRouting!!\n const targetUrl = url.toString();\n // console.log('runRoutingrunRouting', targetUrl);\n await simpleBootFront.goRouting(targetUrl);\n await Promises.sleep(0); // <--\uC911\uC694: \uC774\uAC70 \uB123\uC5B4\uC57C\uC9C0 \uB450\uBC88\uBD88\uB7EC\uC9C0\uB294\uAC8C \uC5C6\uC5B4\uC9C0\uB294\uB4EF? \uBB50\uC9C0 event loop \uBCC0\uACBD\uB41C\uAC74\uAC00?\n\n // console.log('runRout22222ingrunRouting', targetUrl);\n\n // simpleBootFront.routingSubjectObservable.subscribe(it=>{\n // console.log('zzzzzzzzzzzzzzzzzzz', it);\n // if (it.triggerPoint==='end') {\n // console.log('zzz@@', it.routerModule.intent);\n // }\n // })\n\n const data = await firstValueFrom(\n simpleBootFront.routingSubjectObservable.pipe(\n filter(\n (it) =>\n it.triggerPoint === 'end' &&\n typeof it.routerModule.intent.uri === 'string' &&\n targetUrl.endsWith(it.routerModule.intent.uri)\n ),\n // delay(1000),\n first()\n )\n );\n // console.log('???????done');\n await Promises.sleep(0)\n const html = this.makeHTML(simpleBootFront);\n // console.log('---------',html);\n await this.writeOkHtmlAndEnd({ rr }, html);\n } finally {\n (simpleBootFront.option.window as any).ssrUse = false;\n delete (simpleBootFront.option.window as any).server_side_data;\n if ((simpleBootFront as any).generation < this.poolGeneration) {\n // Stale instance, destroy it\n const jsdom = (simpleBootFront as any).jsdom as JSDOM.JSDOM | undefined;\n jsdom?.window.close();\n const index = this.simpleBootFrontPool.indexOf(simpleBootFront);\n if (index > -1) {\n this.simpleBootFrontPool.splice(index, 1);\n }\n this.pushQueue();\n } else {\n // Current instance, return to queue\n this.simpleBootFrontQueue.enqueue(simpleBootFront);\n }\n }\n return false;\n } else {\n return true;\n }\n }\n\n makeHTML(simpleBootFront: SimpleBootFront) {\n (simpleBootFront.option.window as any).document.querySelectorAll('*').forEach((el:HTMLElement )=> {\n Array.from(el.attributes).forEach(attr => {\n if (/^dr-/.test(attr.name) || /^domstyle/.test(attr.name) || /this-path/.test(attr.name)) {\n el.removeAttribute(attr.name);\n }\n });\n });\n let html = simpleBootFront.option.window.document.documentElement.outerHTML;\n if (!/^<!DOCTYPE html>/i.test(html)) {\n html = '<!DOCTYPE html>' + html;\n }\n html = html.replace(/\\$\\{[\\s\\S]*?\\}\\$/g, '');\n const serverSideData = (simpleBootFront.option.window as any).server_side_data;\n if (serverSideData) {\n const data = Object.entries(serverSideData)\n .map(([k, v]) => {\n if (typeof v === 'string') {\n return `window.server_side_data.${k} = ${v}`;\n } else {\n return `window.server_side_data.${k} = ${JSON.stringify(v)}`;\n }\n })\n .join(';');\n if (data) {\n html = html.replace('</head>', `<script> window.server_side_data={}; ${data}; </script></head>`);\n }\n }\n return html;\n }\n async writeOkHtmlAndEnd({ rr, status = HttpStatus.Ok }: { rr: RequestResponse; status?: HttpStatus }, html: string) {\n rr.resStatusCode(status);\n rr.resSetHeader(HttpHeaders.ContentType, Mimes.TextHtml);\n await rr.resEnd(html);\n }\n\n async proceedAfter({ rr, app }: { rr: RequestResponse; app: SimpleBootHttpServer; carrier: Map<string, any> }) {\n return true;\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["import { RequestResponse } from '@dooboostore/simple-boot-http-server/models/RequestResponse';\nimport { HttpHeaders } from '@dooboostore/simple-boot-http-server/codes/HttpHeaders';\nimport { SimpleBootHttpSSRFactory } from '../SimpleBootHttpSSRFactory';\nimport { ConstructorType, AsyncBlockingQueue, RandomUtils, MessageOperator, MessageInternal, Promises } from '@dooboostore/core';\nimport { Filter } from '@dooboostore/simple-boot-http-server/filters/Filter';\nimport { Mimes } from '@dooboostore/simple-boot-http-server/codes/Mimes';\nimport { HttpStatus } from '@dooboostore/simple-boot-http-server/codes/HttpStatus';\nimport { SimpleBootHttpServer } from '@dooboostore/simple-boot-http-server/SimpleBootHttpServer';\nimport { SimFrontOption } from '@dooboostore/simple-boot-front/option/SimFrontOption';\nimport { SimpleBootFront } from '@dooboostore/simple-boot-front/SimpleBootFront';\nimport * as JSDOM from 'jsdom';\nimport { NotFoundError } from '@dooboostore/simple-boot-http-server/errors/NotFoundError';\nimport { DomRenderProxy } from '@dooboostore/dom-render';\nimport { parseHTML } from 'linkedom';\nimport { DomParserInitializer } from '../initializers/DomParserInitializer';\nimport { JsdomInitializer } from '../initializers';\nimport { SimConfig } from '@dooboostore/simple-boot/decorators/SimDecorator';\n\nexport type DomParserFactoryAndParams = {\n frontDistPath: string;\n frontDistIndexFileName?: string;\n factorySimFrontOption: (window: any) => SimFrontOption;\n factory: SimpleBootHttpSSRFactory;\n // poolOption: {\n // max: number;\n // min: number;\n // clearIntervalTime?: number;\n // };\n using: ConstructorType<any>[];\n domExcludes?: ConstructorType<any>[];\n ssrExcludeFilter?: (rr: RequestResponse) => boolean;\n simpleBootFront?: {\n notFoundError?: boolean;\n };\n};\n\nexport class SSRDomParserFilter implements Filter {\n // private simpleBootFrontPool: SimpleBootFront[] = [];\n // private simpleBootFrontQueue = new AsyncBlockingQueue<SimpleBootFront>();\n // private indexHTML: string;\n private welcomUrl = 'http://localhost';\n // private poolGeneration = 0;\n // private intervalId?: NodeJS.Timeout;\n\n constructor(\n public config: DomParserFactoryAndParams,\n public otherInstanceSim?: Map<ConstructorType<any> | Function | SimConfig | Symbol, any>\n ) {\n config.frontDistIndexFileName = config.frontDistIndexFileName || 'index.html';\n // this.indexHTML = JsdomInitializer.loadFile(this.config.frontDistPath, config.frontDistIndexFileName);\n }\n\n async onInit(app: SimpleBootHttpServer) {\n // for (let i = 0; i < this.config.poolOption.min; i++) {\n // await this.pushQueue();\n // }\n // if (this.config.poolOption.clearIntervalTime && this.config.poolOption.clearIntervalTime > 0) {\n // this.intervalId = setInterval(() => {\n // this.poolGeneration++;\n // }, this.config.poolOption.clearIntervalTime);\n // }\n }\n\n async onDestroy() {\n // if (this.intervalId) {\n // clearInterval(this.intervalId);\n // }\n // // this.simpleBootFrontQueue.clear();\n // this.simpleBootFrontPool.forEach(front => {\n // // JSDOM\uB3C4 \uC815\uB9AC (\uD558\uC704 \uD638\uD658\uC131)\n // (front as any).jsdom?.window.close();\n // // Window close - \uC774\uAC83\uB9CC\uC73C\uB85C WindowBase.close()\uAC00 \uD638\uCD9C\uB418\uC5B4 \uBA54\uBAA8\uB9AC \uC815\uB9AC\uB428\n // (front.option.window as any)?.close?.();\n // });\n // this.simpleBootFrontPool = [];\n }\n\n async makePage(url = this.welcomUrl) {\n const domParserInitializer = new DomParserInitializer(this.config.frontDistPath, this.config.frontDistIndexFileName || 'index.html', { url: url });\n const window = await domParserInitializer.run();\n // window.document.querySelector('#app').setAttribute(('vvv'),'zzz')\n // console.log('vvv', window.document.querySelector('#app'))\n // console.log('------', window.document.documentElement.outerHTML);\n return { window, domParserInitializer };\n // const jsdom = await new JsdomInitializer(\n // this.config.frontDistPath,\n // this.config.frontDistIndexFileName || 'index.html',\n // { url: this.welcomUrl }\n // ).run();\n // return { window: jsdom.window as any, domParserInitializer: {destroy: () => {jsdom.window.close()}} };\n // return jsdom;\n }\n\n async makeFront(window: Window, otherInstanceSim?: Map<Function | ConstructorType<any> | SimConfig | Symbol, any>) {\n const name = RandomUtils.uuid();\n (window as any).ssrUse = false;\n const option = this.config.factorySimFrontOption(DomRenderProxy.final(window));\n const domExcludes = [RequestResponse, ...(this.config.domExcludes || [])];\n const simpleBootFront = await this.config.factory.create(option, this.config.using, domExcludes);\n otherInstanceSim ??= new Map<Function | ConstructorType<any> | SimConfig | symbol, any>();\n this.otherInstanceSim?.forEach((v, k) => otherInstanceSim!.set(k, v));\n\n simpleBootFront.run(otherInstanceSim as any);\n // (simpleBootFront as any).generation = this.poolGeneration;\n return simpleBootFront;\n }\n\n // enqueueFrontApp(simpleBootFront: SimpleBootFront) {\n // // this.simpleBootFrontPool.set(simpleBootFront.option.name!, simpleBootFront);\n // this.simpleBootFrontPool.push(simpleBootFront);\n // this.simpleBootFrontQueue.enqueue(simpleBootFront);\n // }\n //\n // async pushQueue() {\n // if (this.simpleBootFrontPool.length < this.config.poolOption.max) {\n // this.enqueueFrontApp(await this.makeFront(await this.makePage()));\n // }\n // }\n\n async proceedBefore({ rr, app }: { rr: RequestResponse; app: SimpleBootHttpServer; carrier: Map<string, any> }) {\n if (this.config.ssrExcludeFilter?.(rr)) {\n return false;\n }\n if (rr.reqHasAcceptHeader(Mimes.TextHtml) || rr.reqHasAcceptHeader(Mimes.All)) {\n // if (this.simpleBootFrontQueue.isEmpty()) {\n // await this.pushQueue();\n // }\n // const simpleBootFront = await this.simpleBootFrontQueue.dequeue();\n const url = rr.reqUrlObj({ host: 'localhost' });\n const targetUrl = url.toString() ?? this.welcomUrl;\n const { window, domParserInitializer } = await this.makePage(targetUrl);\n const otherSim = new Map<Function | ConstructorType<any> | SimConfig | Symbol, any>();\n otherSim.set(RequestResponse, rr);\n const simpleBootFront = await this.makeFront(window, otherSim);\n try {\n (simpleBootFront.option.window as any).ssrUse = true;\n // console.log(simpleBootFront.routing)\n if (this.config.simpleBootFront?.notFoundError) {\n // intent router check first\n const intent = await simpleBootFront.routingRouterModule(url.pathname);\n // route\uB97C \uBABB\uCC3E\uC740\uC0C1\uD0DC\uC5D0\uC11C router path\uAE4C\uC9C0 \uC548\uB9DE\uC73C\uBA74 404 \uCC98\uB9AC\uD55C\uB2E4. route\uB791 router\uB791 \uB2E4\uB974\uB2C8\uAE50 \uD5DB\uAC08\uB9AC\uC9C0\uB9D0\uB3C4\uB85D\n if (intent.module === undefined && !intent.getRouterPathData(rr.reqUrlPathName)) {\n throw new NotFoundError({ message: `Not Found: ${rr.reqUrlPathName}` });\n }\n }\n\n const data = await MessageInternal.firstValueFrom(\n simpleBootFront.routingObservable.pipe(\n MessageOperator.filter(it => {\n\n const sw = it.triggerPoint === 'end' && typeof it.routerModule.intent.uri === 'string' && targetUrl.endsWith(it.routerModule.intent.uri);\n return sw;\n }),\n // delay(1000),\n MessageOperator.first()\n )\n );\n\n // [\uC544\uD0A4\uD14D\uD2B8\uB2D8\uC758 \uC815\uC11D] \uD558\uC774\uB4DC\uB808\uC774\uC158 \uB370\uC774\uD130\uB97C \uAC00\uC0C1 \uC708\uB3C4\uC6B0\uC758 body\uC5D0 script \uD0DC\uADF8\uB85C \uBC15\uC81C\n // @ts-ignore: writeDataHydration is part of the \uC815\uC11D\n simpleBootFront.writeDataHydration();\n simpleBootFront.clearDataHydration();\n\n const html = this.makeHTML(simpleBootFront);\n await this.writeOkHtmlAndEnd({ rr }, html);\n } finally {\n try {\n (simpleBootFront.option.window as any).ssrUse = false;\n window.close();\n simpleBootFront.onDestroy();\n\n // window.close()\uB9CC \uD638\uCD9C\uD558\uBA74 WindowBase.close()\uAC00 \uC2E4\uD589\uB418\uC5B4 \uBA54\uBAA8\uB9AC \uC815\uB9AC\uB428\n (simpleBootFront.option.window as any)?.close?.();\n domParserInitializer.destroy();\n } catch (e) {\n console.log('eeeeee', e);\n }\n\n // const index = this.simpleBootPool.indexOf(simpleBootFront);\n // if (index > -1) {\n // this.simpleBootPool.splice(index, 1);\n // }\n // this.pushQueue();\n }\n return false;\n } else {\n return true;\n }\n }\n\n makeHTML(simpleBootFront: SimpleBootFront) {\n (simpleBootFront.option.window as any).document.querySelectorAll('*').forEach((el: HTMLElement) => {\n Array.from(el.attributes).forEach(attr => {\n if (/^dr-/.test(attr.name) || /^domstyle/.test(attr.name) || /this-path/.test(attr.name)) {\n el.removeAttribute(attr.name);\n }\n });\n });\n let html = simpleBootFront.option.window.document.documentElement.outerHTML;\n if (!/^<!DOCTYPE html>/i.test(html)) {\n html = '<!DOCTYPE html>' + html;\n }\n html = html.replace(/\\$\\{[\\s\\S]*?\\}\\$/g, '');\n\n // [\uC544\uD0A4\uD14D\uD2B8\uB2D8\uC758 \uC815\uC11D]\n // body\uC5D0 \uC9C1\uC811 append\uB41C script tag\uAC00 outerHTML\uC5D0 \uC774\uBBF8 \uD3EC\uD568\uB418\uC5B4 \uC788\uC73C\uBBC0\uB85C \uCD94\uAC00 \uC870\uC791\uC740 \uBD88\uD544\uC694\uD569\uB2C8\uB2E4.\n\n return html;\n }\n\n async writeOkHtmlAndEnd({ rr, status = HttpStatus.Ok }: { rr: RequestResponse; status?: HttpStatus }, html: string) {\n rr.resStatusCode(status);\n rr.resSetHeader(HttpHeaders.ContentType, Mimes.TextHtml);\n await rr.resEnd(html);\n }\n\n async proceedAfter({ rr, app }: { rr: RequestResponse; app: SimpleBootHttpServer; carrier: Map<string, any> }) {\n return true;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -21,22 +21,18 @@ __export(SSRFilter_exports, {
|
|
|
21
21
|
});
|
|
22
22
|
module.exports = __toCommonJS(SSRFilter_exports);
|
|
23
23
|
var import_HttpHeaders = require("@dooboostore/simple-boot-http-server/codes/HttpHeaders");
|
|
24
|
+
var import_core = require("@dooboostore/core");
|
|
24
25
|
var import_JsdomInitializer = require("../initializers/JsdomInitializer");
|
|
25
26
|
var import_Mimes = require("@dooboostore/simple-boot-http-server/codes/Mimes");
|
|
26
27
|
var import_HttpStatus = require("@dooboostore/simple-boot-http-server/codes/HttpStatus");
|
|
27
|
-
var import_AsyncBlockingQueue = require("@dooboostore/core/queues/AsyncBlockingQueue");
|
|
28
|
-
var import_RandomUtils = require("@dooboostore/core/random/RandomUtils");
|
|
29
28
|
var import_NotFoundError = require("@dooboostore/simple-boot-http-server/errors/NotFoundError");
|
|
30
|
-
var
|
|
31
|
-
var import_filter = require("@dooboostore/core/message/operators/filter");
|
|
32
|
-
var import_first = require("@dooboostore/core/message/operators/first");
|
|
33
|
-
var import_firstValueFrom = require("@dooboostore/core/message/internal/firstValueFrom");
|
|
29
|
+
var import_dom_render = require("@dooboostore/dom-render");
|
|
34
30
|
class SSRFilter {
|
|
35
31
|
constructor(config, otherInstanceSim) {
|
|
36
32
|
this.config = config;
|
|
37
33
|
this.otherInstanceSim = otherInstanceSim;
|
|
38
34
|
this.simpleBootFrontPool = [];
|
|
39
|
-
this.simpleBootFrontQueue = new
|
|
35
|
+
this.simpleBootFrontQueue = new import_core.AsyncBlockingQueue();
|
|
40
36
|
this.welcomUrl = "http://localhost";
|
|
41
37
|
this.poolGeneration = 0;
|
|
42
38
|
config.frontDistIndexFileName = config.frontDistIndexFileName || "index.html";
|
|
@@ -78,10 +74,10 @@ class SSRFilter {
|
|
|
78
74
|
return jsdom;
|
|
79
75
|
}
|
|
80
76
|
async makeFront(jsdom) {
|
|
81
|
-
const name =
|
|
77
|
+
const name = import_core.RandomUtils.uuid();
|
|
82
78
|
const window = jsdom.window;
|
|
83
79
|
window.ssrUse = false;
|
|
84
|
-
const option = this.config.factorySimFrontOption(
|
|
80
|
+
const option = this.config.factorySimFrontOption(import_dom_render.DomRenderProxy.final(window));
|
|
85
81
|
const simpleBootFront = await this.config.factory.create(option, this.config.using, this.config.domExcludes);
|
|
86
82
|
simpleBootFront.run(this.otherInstanceSim);
|
|
87
83
|
simpleBootFront.jsdom = jsdom;
|
|
@@ -115,7 +111,7 @@ class SSRFilter {
|
|
|
115
111
|
delete simpleBootFront.option.window.server_side_data;
|
|
116
112
|
const url = rr.reqUrlObj({ host: "localhost" });
|
|
117
113
|
if (this.config.simpleBootFront?.notFoundError) {
|
|
118
|
-
const intent = await simpleBootFront.
|
|
114
|
+
const intent = await simpleBootFront.routingRouterModule(url.pathname);
|
|
119
115
|
if (intent.module === void 0 && !intent.getRouterPathData(rr.reqUrlPathName)) {
|
|
120
116
|
throw new import_NotFoundError.NotFoundError({ message: `Not Found: ${rr.reqUrlPathName}` });
|
|
121
117
|
}
|
|
@@ -123,15 +119,15 @@ class SSRFilter {
|
|
|
123
119
|
const targetUrl = url.toString();
|
|
124
120
|
await simpleBootFront.goRouting(targetUrl);
|
|
125
121
|
await new Promise((r) => setTimeout(r, 0));
|
|
126
|
-
const data = await
|
|
122
|
+
const data = await import_core.MessageInternal.firstValueFrom(
|
|
127
123
|
// @ts-ignore
|
|
128
|
-
simpleBootFront.
|
|
124
|
+
simpleBootFront.routingObservable.pipe(
|
|
129
125
|
// @ts-ignore
|
|
130
|
-
|
|
126
|
+
import_core.MessageOperator.filter(
|
|
131
127
|
(it) => it.triggerPoint === "end" && typeof it.routerModule.intent.uri === "string" && targetUrl.endsWith(it.routerModule.intent.uri)
|
|
132
128
|
),
|
|
133
129
|
// delay(1000),
|
|
134
|
-
|
|
130
|
+
import_core.MessageOperator.first()
|
|
135
131
|
)
|
|
136
132
|
);
|
|
137
133
|
const html = this.makeHTML(simpleBootFront);
|