UNPKG

@dooboostore/simple-boot-http-server-ssr

Version:
232 lines 13.4 kB
import { __awaiter } from "tslib"; import { HttpHeaders } from '@dooboostore/simple-boot-http-server/codes/HttpHeaders'; import { JsdomInitializer } from '../initializers/JsdomInitializer'; import { Mimes } from '@dooboostore/simple-boot-http-server/codes/Mimes'; import { HttpStatus } from '@dooboostore/simple-boot-http-server/codes/HttpStatus'; import { AsyncBlockingQueue } from '@dooboostore/core/queues/AsyncBlockingQueue'; import { RandomUtils } from '@dooboostore/core/random/RandomUtils'; import { NotFoundError } from '@dooboostore/simple-boot-http-server/errors/NotFoundError'; export class SSRFilter { constructor(config, otherInstanceSim) { this.config = config; this.otherInstanceSim = otherInstanceSim; this.simpleBootFrontPool = []; this.simpleBootFrontQueue = new AsyncBlockingQueue(); this.welcomUrl = 'http://localhost'; config.frontDistIndexFileName = config.frontDistIndexFileName || 'index.html'; this.indexHTML = JsdomInitializer.loadFile(this.config.frontDistPath, config.frontDistIndexFileName); } onInit(app) { return __awaiter(this, void 0, void 0, function* () { for (let i = 0; i < this.config.poolOption.min; i++) { yield this.pushQueue(); } // console.log('SimpleBootHttpSSRFactory init success ', + this.simpleBootFrontPool.length) }); } // workerTs(workerOptions: WorkerOptions) { // workerOptions.eval = true; // if (!workerOptions.workerData) { // workerOptions.workerData = {}; // } // workerOptions.workerData.__filename = '/Users/hyunhakim/source/visualkhh/pet-space/libs/simple-boot-http-ssr/dist/filters/SSRCreatorWorker.js'; // return new Worker(` const wk = require('worker_threads'); require('ts-node').register(); let file = wk.workerData.__filename; require(file); `, workerOptions,); // } makeJsdom() { return __awaiter(this, void 0, void 0, function* () { const jsdom = yield new JsdomInitializer(this.config.frontDistPath, this.config.frontDistIndexFileName || 'index.html', { url: this.welcomUrl }).run(); return jsdom; }); } makeFront(jsdom) { return __awaiter(this, void 0, void 0, function* () { const name = RandomUtils.uuid(); // const jsdom = await this.makeJsdom(); const window = jsdom.window; window.ssrUse = false; const option = this.config.factorySimFrontOption(window); const simpleBootFront = yield this.config.factory.create(option, this.config.using, this.config.domExcludes); simpleBootFront.run(this.otherInstanceSim); simpleBootFront.jsdom = jsdom; return simpleBootFront; }); } enqueueFrontApp(simpleBootFront) { // this.simpleBootFrontPool.set(simpleBootFront.option.name!, simpleBootFront); this.simpleBootFrontPool.push(simpleBootFront); this.simpleBootFrontQueue.enqueue(simpleBootFront); } // async pushQueue(destorFront?: SimpleBootFront) { // if (destorFront) { // this.simpleBootFrontPool.delete(destorFront.option.name!); // } pushQueue() { return __awaiter(this, void 0, void 0, function* () { if (this.simpleBootFrontPool.length < this.config.poolOption.max) { this.enqueueFrontApp(yield this.makeFront(yield this.makeJsdom())); } }); } proceedBefore(_a) { return __awaiter(this, arguments, void 0, function* ({ rr, app }) { var _b, _c, _d; if ((_c = (_b = this.config).ssrExcludeFilter) === null || _c === void 0 ? void 0 : _c.call(_b, rr)) { return false; } if ((rr.reqHasAcceptHeader(Mimes.TextHtml) || rr.reqHasAcceptHeader(Mimes.All))) { if (this.simpleBootFrontQueue.isEmpty()) { yield this.pushQueue(); } const simpleBootFront = yield this.simpleBootFrontQueue.dequeue(); try { // console.log('SSRFilter before-->' , simpleBootFront.option.name, 'poolLength:',this.simpleBootFrontPool.size); simpleBootFront.option.window.ssrUse = true; delete simpleBootFront.option.window.server_side_data; const url = rr.reqUrlObj({ host: 'localhost' }); if ((_d = this.config.simpleBootFront) === null || _d === void 0 ? void 0 : _d.notFoundError) { // intent router check first const intent = yield simpleBootFront.getIntent(url.pathname); // route를 못찾은상태에서 router path까지 안맞으면 404 처리한다. route랑 router랑 다르니깐 헛갈리지말도록 if (intent.module === undefined && (!intent.getRouterPathData(rr.reqUrlPathName))) { throw new NotFoundError({ message: `Not Found: ${rr.reqUrlPathName}` }); } } // runRouting!! simpleBootFront.goRouting(url.toString()); // console.log('------intent', intent) yield new Promise((r) => setTimeout(r, 0)); // <--중요: 이거 넣어야지 두번불러지는게 없어지는듯? 뭐지 event loop 변경된건가? // const e = Expression.Path.pathNameData(rr.reqUrlPathName, intent.getRouterPath()) // console.log('------intent', rr.reqUrl, rr.reqUrlPathName, intent.module, intent.getRouterPath(), e) // simpleBootFront.option.window.document.documentElemenh // "dr-"로 시작하는 모든 attribute를 가진 element에서 해당 attribute를 제거 simpleBootFront.option.window.document.querySelectorAll('*').forEach(el => { Array.from(el.attributes).forEach(attr => { if (/^dr-/.test(attr.name) || /^domstyle/.test(attr.name) || /this-path/.test(attr.name)) { el.removeAttribute(attr.name); } }); }); let html = simpleBootFront.option.window.document.documentElement.outerHTML; // html = '<!DOCTYPE html>'+html; html = html.replace(/\$\{[\s\S]*?\}\$/g, ''); const serverSideData = simpleBootFront.option.window.server_side_data; if (serverSideData) { const data = Object.entries(serverSideData).map(([k, v]) => { if (typeof v === 'string') { return `window.server_side_data.${k} = ${v}`; } else { return `window.server_side_data.${k} = ${JSON.stringify(v)}`; } }).join(';'); if (data) { html = html.replace('</head>', `<script> window.server_side_data={}; ${data}; </script></head>`); } } yield this.writeOkHtmlAndEnd({ rr }, html); } finally { simpleBootFront.option.window.ssrUse = false; delete simpleBootFront.option.window.server_side_data; // console.log('--------->', simpleBootFront.option.window) // simpleBootFront.ninitWriteRootRouter(); // ((simpleBootFront as any).jsdom as JSDOM.JSDOM)?.reconfigure({url: '/' }); // simpleBootFront.option.window.location.href = 'about:blank'; this.simpleBootFrontQueue.enqueue(simpleBootFront); // simpleBootFront.option.window.document.body.innerHTML = this.rootJSDOM.window.document.body.innerHTML; // simpleBootFront.writeRootRouter() // await simpleBootFront.goRouting('/'); // ((simpleBootFront as any).jsdom as JSDOM.JSDOM)?.reconfigure({url: this.welcomUrl }); // simpleBootFront.option.window.location.href = this.welcomUrl; // simpleBootFront.option.window.document.documentElement.outerHTML = this.indexHTML; // this.simpleBootFrontQueue.enqueue(simpleBootFront); // await new Promise((re, r) => setTimeout(() => re(true), 10000)); // new Promise((re, r) => setTimeout(() => re(true), 10000)).then(it => { // console.log('ddddddddddd') // }); // this.simpleBootFrontPool.delete(simpleBootFront.option.name!); // if (isMainThread) { // 메인 스레드 // console.log('file-->', __filename) // const worker = new Worker(__filename); // worker.on('message', (value: any) => { // console.log('워커로부터', value) // }) // worker.on('exit', (value: any) => { // parentPort.close()가 일어나면 이벤트 발생 // console.log('워커 끝~'); // }) // worker.postMessage('ping'); // 워커스레드에게 메세지를 보낸다. // } else { // 워커스레드 // parentPort.on('message', (value: any) => { // console.log("부모로부터", value); // parentPort.postMessage('pong'); // parentPort.close(); // 워커스레드 종료라고 메인스레드에 알려줘야 exit이벤트 발생 // }) // } //worker thrad // const workerPath = path.join(__dirname, 'SSRWorker.js'); // const worker = new Worker(workerPath); // worker.once('message', (value: any) => { // console.log('워커로부터', value) // }); // const receiveWorker = new Worker('/Users/hyunhakim/source/visualkhh/pet-space/libs/simple-boot-http-ssr/dist/filters/SSRCreatorWorker.js'); // receiveWorker.on('message', (msg: JSDOM.JSDOM)=>{ // console.log('워커로부터', msg, msg.window.document.body.innerHTML) // console.log('a message is sent! : ', msg) // // }); // // receiveWorker.on('error', err=>{ // console.error(err); // }) // // receiveWorker.on('exit', ()=>console.log('exited!')); // receiveWorker.postMessage( // { // frontDistPath: this.factory.frontDistPath, // frontDistIndexFileName: this.factory.frontDistIndexFileName, // } // ); // const myWorkers = this.workerTs({}); // myWorkers.postMessage(this); // myWorkers.on('message', (value: SimpleBootFront) => { // this.pushQueue(value); // }) // this // this.pushQueue(simpleBootFront).then(it => { // console.log('deee') // }); // console.log('-1->', simpleBootFront.option.window.location.href); // simpleBootFront.option.window.location.href = this.welcomUrl; // simpleBootFront.option.window.location.reload(); // console.log('-2->', simpleBootFront.option.window.location.href); // simpleBootFront.option.window.location.reload(); // console.log('-3->', simpleBootFront.option.window.location.href); // this.simpleBootFrontQueue.enqueue(simpleBootFront); // await this.makeJsdom(); // simpleBootFront.option.window.location.href = this.welcomUrl; } // console.log('----doen') return false; } else { // console.log('----doen2') return true; } }); } writeOkHtmlAndEnd(_a, html_1) { return __awaiter(this, arguments, void 0, function* ({ rr, status = HttpStatus.Ok }, html) { // rr.res.writeHead(status, {[HttpHeaders.ContentType]: Mimes.TextHtml}); rr.resStatusCode(status); rr.resSetHeader(HttpHeaders.ContentType, Mimes.TextHtml); yield rr.resEnd(html); }); } proceedAfter(_a) { return __awaiter(this, arguments, void 0, function* ({ rr, app }) { // console.log('done--------', sw) return true; }); } } //# sourceMappingURL=SSRFilter.js.map