UNPKG

@scullyio/scully-plugin-playwright

Version:

The playwright renderer is utilizing the [playwright](https://playwright.dev/) engine to render your pages.

171 lines 7.99 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.playwrightRenderer = exports.playwrightRender = exports.title404 = void 0; const tslib_1 = require("tslib"); const scully_1 = require("@scullyio/scully"); const cli_options_1 = require("@scullyio/scully/src/lib/utils/cli-options"); const fs_extra_1 = require("fs-extra"); const jsonc_1 = require("jsonc"); const path_1 = require("path"); const plugins_scully_plugin_playwright_utils_1 = require("./plugins-scully-plugin-playwright-utils"); let version = '0.0.0'; try { const pkg = path_1.join(__dirname, '../../../package.json'); version = jsonc_1.jsonc.parse(fs_extra_1.readFileSync(pkg).toString()).version || '0.0.0'; } catch (e) { // this is only for internals builds } exports.title404 = '404 - URL not provided in the app Scully is serving'; const errorredPages = new Map(); exports.playwrightRender = 'playwrightRender'; const playwrightRenderer = (route) => tslib_1.__awaiter(void 0, void 0, void 0, function* () { const path = route.rawRoute ? route.rawRoute : scully_1.scullyConfig.hostUrl ? `${scully_1.scullyConfig.hostUrl}${route.route}` : `http${cli_options_1.ssl ? 's' : ''}://${scully_1.scullyConfig.hostName}:${scully_1.scullyConfig.appPort}${route.route}`; let pageHtml; let browser; let page; try { browser = yield plugins_scully_plugin_playwright_utils_1.launchedBrowser().catch((e) => { scully_1.logError('Playwright died?', e); return Promise.reject(e); }); // open a new page page = yield browser.newPage(); let resolve; const pageReady = new Promise((r) => (resolve = r)); if (scully_1.scullyConfig.ignoreResourceTypes && scully_1.scullyConfig.ignoreResourceTypes.length > 0) { yield page.route('**/*', (route) => checkIfRequestShouldBeIgnored.bind(route.request)); // eslint-disable-next-line no-inner-declarations function checkIfRequestShouldBeIgnored(request) { if (scully_1.scullyConfig.ignoreResourceTypes.includes(request.resourceType())) { request.abort(); } else { request.continue(); } } } /** this will be called from the browser, but runs in node */ yield page.exposeFunction('pageRenderReady', () => { resolve(); }); windowSet(page, 'scullyVersion', version); if (route.config && route.config.manualIdleCheck) { route.exposeToPage = route.exposeToPage || {}; route.exposeToPage.manualIdle = true; } if (scully_1.scullyConfig.inlineStateOnly) { route.injectToPage = route.injectToPage || {}; route.injectToPage.inlineStateOnly = true; } if (route.exposeToPage !== undefined) { windowSet(page, 'ScullyIO-exposed', route.exposeToPage); } if (route.injectToPage !== undefined) { windowSet(page, 'ScullyIO-injected', route.injectToPage); } /** Inject this into the running page, runs in browser */ yield page.addInitScript(() => { /** set "running" mode */ window['ScullyIO'] = 'running'; window.addEventListener('AngularReady', () => { window['pageRenderReady'](); }); }); // enter url in page yield page.goto(path); yield Promise.race([pageReady, plugins_scully_plugin_playwright_utils_1.waitForIt(25 * 1000)]); /** when done, add in some scully content. */ yield page.evaluate(() => { const head = document.head; /** add a small script tag to set "generated" mode */ const d = document.createElement('script'); d.innerHTML = `window['ScullyIO']='generated';`; if (window['ScullyIO-injected']) { /** and add the injected data there too. */ d.innerHTML += `window['ScullyIO-injected']=${JSON.stringify(window['ScullyIO-injected'])};`; } const m = document.createElement('meta'); m.name = 'generator'; m.content = `Scully ${window['scullyVersion']}`; head.appendChild(d); head.insertBefore(m, head.firstChild); /** inject the scully version into the body attribute */ document.body.setAttribute('scully-version', window['scullyVersion']); }); pageHtml = yield page.content(); /** Check for undefined content and re-try */ if ([undefined, null, '', 'undefined', 'null'].includes(pageHtml)) { throw new Error(`Route "${route.route}" render to ${path}`); } const firstTitle = yield page.evaluate(() => { const d = document.querySelector('h1'); return (d && d.innerText) || ''; }); if (firstTitle === exports.title404) { scully_1.logWarn(`Route "${scully_1.yellow(route.route)}" not provided by angular app`); } /** save thumbnail to disk code */ if (scully_1.scullyConfig.thumbnails) { const file = path_1.join(scully_1.scullyConfig.outDir, route.route, '/thumbnail.jpg'); scully_1.createFolderFor(file); yield page.screenshot({ path: file }); } /** * when the browser is shown, use a 2 minute timeout, otherwise * wait for page-read || timeout @ 25 seconds. */ if (cli_options_1.showBrowser) { page.evaluate("console.log('\\n\\n------------------------------\\nScully is done, page left open for 120 seconds for inspection\\n------------------------------\\n\\n')"); //* don't close the browser, but leave it open for inspection for 120 secs plugins_scully_plugin_playwright_utils_1.waitForIt(1200 * 1000).then(() => page.close()); } else { // await page.close(); page.close(); } } catch (err) { const { message } = err; // tslint:disable-next-line: no-unused-expression page && typeof page.close === 'function' && (yield page.close()); scully_1.logWarn(`Playwright error while rendering "${scully_1.yellow(route.route)}"`, err, ' we will retry rendering this page up to 3 times.'); if (message && message.includes('closed')) { /** signal the launched to relaunch playwright, as it has likely died here. */ //TODO:c plugins_scully_plugin_playwright_utils_1.reLaunch('closed'); // return playwrightRender(route); } if (errorredPages.has(route.route) && errorredPages.get(route.route) > 2) { scully_1.logError(`Playwright error while rendering "${scully_1.yellow(route.route)}"`, err, ' we retried rendering this page 3 times.'); /** we tried this page before, something is really off. Exit stage left. */ //TODO: // captureException(err); process.exit(15); } else { const count = errorredPages.get(route.route) || 0; errorredPages.set(route.route, count + 1); /** give it a couple of secs */ yield plugins_scully_plugin_playwright_utils_1.waitForIt(3 * 1000); /** retry! */ return exports.playwrightRenderer(route); } } // logWarn(`done with page ${path}`); return pageHtml; }); exports.playwrightRenderer = playwrightRenderer; const windowSet = (page, name, value) => page.addInitScript(` Object.defineProperty(window, '${name}', { get() { return JSON.parse('${JSON.stringify(value)}') } }) `); scully_1.registerPlugin('scullySystem', exports.playwrightRender, exports.playwrightRenderer); //# sourceMappingURL=plugins-scully-plugin-playwright.js.map