UNPKG

@shopify/react-server

Version:
93 lines (92 loc) 5.61 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var react_1 = tslib_1.__importDefault(require("react")); var server_1 = require("@shopify/react-html/server"); var server_2 = require("@shopify/react-network/server"); var react_hydrate_1 = require("@shopify/react-hydrate"); var server_3 = require("@shopify/react-effect/server"); var react_async_1 = require("@shopify/react-async"); var react_network_1 = require("@shopify/react-network"); var sewing_kit_koa_1 = require("@shopify/sewing-kit-koa"); var logger_1 = require("../logger"); /** * Creates a Koa middleware for rendering an `@shopify/react-html` based React application defined by `options.render`. * @param render */ function createRender(render, options) { if (options === void 0) { options = {}; } return function renderFunction(ctx) { return tslib_1.__awaiter(this, void 0, void 0, function () { function Providers(_a) { var children = _a.children; return (react_1.default.createElement(react_async_1.AsyncAssetContext.Provider, { value: asyncAssetManager }, react_1.default.createElement(react_hydrate_1.HydrationContext.Provider, { value: hydrationManager }, react_1.default.createElement(server_2.NetworkContext.Provider, { value: networkManager }, children)))); } var logger, assets, networkManager, htmlManager, asyncAssetManager, hydrationManager, app, immediateAsyncAssets, _a, styles, scripts, response, error_1, errorMessage; return tslib_1.__generator(this, function (_b) { switch (_b.label) { case 0: logger = logger_1.getLogger(ctx) || console; assets = sewing_kit_koa_1.getAssets(ctx); networkManager = new server_2.NetworkManager({ headers: ctx.headers, cookies: ctx.request.headers.cookie || '', }); htmlManager = new server_1.HtmlManager(); asyncAssetManager = new react_async_1.AsyncAssetManager(); hydrationManager = new react_hydrate_1.HydrationManager(); _b.label = 1; case 1: _b.trys.push([1, 4, , 5]); app = render(ctx); return [4 /*yield*/, server_3.extract(app, tslib_1.__assign({ decorate: function (element) { return (react_1.default.createElement(server_1.HtmlContext.Provider, { value: htmlManager }, react_1.default.createElement(Providers, null, element))); }, afterEachPass: function (_a) { var renderDuration = _a.renderDuration, resolveDuration = _a.resolveDuration, index = _a.index, finished = _a.finished; var pass = "Pass number " + index + " " + (finished ? ' (this was the final pass)' : ''); var rendering = "Rendering took " + renderDuration + "ms"; var resolving = "Resolving promises took " + resolveDuration + "ms"; logger.log(pass); logger.log(rendering); logger.log(resolving); } }, options))]; case 2: _b.sent(); server_2.applyToContext(ctx, networkManager); immediateAsyncAssets = asyncAssetManager.used(react_async_1.AssetTiming.Immediate); return [4 /*yield*/, Promise.all([ assets.styles({ name: 'main', asyncAssets: immediateAsyncAssets }), assets.scripts({ name: 'main', asyncAssets: immediateAsyncAssets }), ])]; case 3: _a = tslib_1.__read.apply(void 0, [_b.sent(), 2]), styles = _a[0], scripts = _a[1]; response = server_1.stream(react_1.default.createElement(server_1.Html, { manager: htmlManager, styles: styles, scripts: scripts }, react_1.default.createElement(Providers, null, app))); ctx.set(react_network_1.Header.ContentType, 'text/html'); ctx.body = response; return [3 /*break*/, 5]; case 4: error_1 = _b.sent(); errorMessage = "React server-side rendering error:\n" + (error_1.stack || error_1.message); logger.log(errorMessage); ctx.status = react_network_1.StatusCode.InternalServerError; // eslint-disable-next-line no-process-env if (process.env.NODE_ENV === 'development') { ctx.body = errorMessage; } else { ctx.throw(react_network_1.StatusCode.InternalServerError, error_1); } return [3 /*break*/, 5]; case 5: return [2 /*return*/]; } }); }); }; } exports.createRender = createRender;