UNPKG

gatsby

Version:
366 lines (360 loc) • 13.9 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports.default = staticPage; exports.getPageChunk = getPageChunk; var _concat2 = _interopRequireDefault(require("lodash/concat")); var _uniqBy2 = _interopRequireDefault(require("lodash/uniqBy")); var _flatten2 = _interopRequireDefault(require("lodash/flatten")); var _isObject2 = _interopRequireDefault(require("lodash/isObject")); var _merge2 = _interopRequireDefault(require("lodash/merge")); var _get2 = _interopRequireDefault(require("lodash/get")); var _react = _interopRequireDefault(require("react")); var _fsExtra = _interopRequireDefault(require("fs-extra")); var _server = require("react-dom/server"); var _path = _interopRequireDefault(require("path")); var _apiRunnerSsr = require("./api-runner-ssr"); var _findPath = require("./find-path"); var _ssrSyncRequires = _interopRequireDefault(require("$virtual/ssr-sync-requires")); var _routeAnnouncerProps = require("./route-announcer-props"); var _reachRouter = require("@gatsbyjs/reach-router"); var _headExportHandlerForSsr = require("./head/head-export-handler-for-ssr"); var _loader = require("./loader"); var _writableAsPromise = require("./server-utils/writable-as-promise"); var _context = require("./slice/context"); /* global BROWSER_ESM_ONLY */ // prefer default export if available const preferDefault = m => m && m.default || m; const testRequireError = (moduleName, err) => { const regex = new RegExp(`Error: Cannot find module\\s.${moduleName}`); const firstLine = err.toString().split(`\n`)[0]; return regex.test(firstLine); }; let cachedStats; const getStats = publicDir => { if (cachedStats) { return cachedStats; } else { cachedStats = JSON.parse(_fsExtra.default.readFileSync(_path.default.join(publicDir, `webpack.stats.json`), `utf-8`)); return cachedStats; } }; let Html; try { Html = require(`../src/html`); } catch (err) { if (testRequireError(`../src/html`, err)) { Html = require(`./default-html`); } else { console.log(`There was an error requiring "src/html.js"\n\n`, err, `\n\n`); process.exit(); } } Html = Html && Html.__esModule ? Html.default : Html; async function staticPage({ pagePath, isClientOnlyPage, publicDir, error, serverData }) { let bodyHtml = ``; let headComponents = [/*#__PURE__*/_react.default.createElement("meta", { key: "environment", name: "note", content: "environment=development" })]; let htmlAttributes = {}; let bodyAttributes = {}; let preBodyComponents = []; let postBodyComponents = []; let bodyProps = {}; if (error) { postBodyComponents.push([/*#__PURE__*/_react.default.createElement("script", { key: "dev-ssr-error", dangerouslySetInnerHTML: { __html: `window._gatsbyEvents = window._gatsbyEvents || []; window._gatsbyEvents.push(["FAST_REFRESH", { action: "SHOW_DEV_SSR_ERROR", payload: ${JSON.stringify(error)} }])` } }), /*#__PURE__*/_react.default.createElement("noscript", { key: "dev-ssr-error-noscript" }, /*#__PURE__*/_react.default.createElement("h1", null, "Failed to Server Render (SSR)"), /*#__PURE__*/_react.default.createElement("h2", null, "Error message:"), /*#__PURE__*/_react.default.createElement("p", null, error.sourceMessage), /*#__PURE__*/_react.default.createElement("h2", null, "File:"), /*#__PURE__*/_react.default.createElement("p", null, error.source, ":", error.line, ":", error.column), /*#__PURE__*/_react.default.createElement("h2", null, "Stack:"), /*#__PURE__*/_react.default.createElement("pre", null, /*#__PURE__*/_react.default.createElement("code", null, error.stack)))]); } const generateBodyHTML = async () => { const setHeadComponents = components => { headComponents = headComponents.concat(components); }; const setHtmlAttributes = attributes => { htmlAttributes = (0, _merge2.default)(htmlAttributes, attributes); }; const setBodyAttributes = attributes => { bodyAttributes = (0, _merge2.default)(bodyAttributes, attributes); }; const setPreBodyComponents = components => { preBodyComponents = preBodyComponents.concat(components); }; const setPostBodyComponents = components => { postBodyComponents = postBodyComponents.concat(components); }; const setBodyProps = props => { bodyProps = (0, _merge2.default)({}, bodyProps, props); }; const getHeadComponents = () => headComponents; const replaceHeadComponents = components => { headComponents = components; }; const replaceBodyHTMLString = body => { bodyHtml = body; }; const getPreBodyComponents = () => preBodyComponents; const replacePreBodyComponents = components => { preBodyComponents = components; }; const getPostBodyComponents = () => postBodyComponents; const replacePostBodyComponents = components => { postBodyComponents = components; }; const getPageDataPath = path => { const fixedPagePath = path === `/` ? `index` : path; return _path.default.join(`page-data`, fixedPagePath, `page-data.json`); }; const getPageData = pagePath => { const pageDataPath = getPageDataPath(pagePath); const absolutePageDataPath = _path.default.join(publicDir, pageDataPath); const pageDataJson = _fsExtra.default.readFileSync(absolutePageDataPath, `utf8`); try { return JSON.parse(pageDataJson); } catch (err) { return null; } }; const pageData = getPageData(pagePath); const { componentChunkName, slicesMap } = pageData; const pageComponent = await _ssrSyncRequires.default.ssrComponents[componentChunkName]; let scriptsAndStyles = (0, _flatten2.default)([`commons`].map(chunkKey => { const fetchKey = `assetsByChunkName[${chunkKey}]`; const stats = getStats(publicDir); let chunks = (0, _get2.default)(stats, fetchKey); const namedChunkGroups = (0, _get2.default)(stats, `namedChunkGroups`); if (!chunks) { return null; } chunks = chunks.map(chunk => { if (chunk === `/`) { return null; } return { rel: `preload`, name: chunk }; }); namedChunkGroups[chunkKey].assets.forEach(asset => chunks.push({ rel: `preload`, name: asset.name })); const childAssets = namedChunkGroups[chunkKey].childAssets; for (const rel in childAssets) { if (childAssets.hasownProperty(rel)) { chunks = (0, _concat2.default)(chunks, childAssets[rel].map(chunk => { return { rel, name: chunk }; })); } } return chunks; })).filter(s => (0, _isObject2.default)(s)).sort((s1, _s2) => s1.rel == `preload` ? -1 : 1); // given priority to preload scriptsAndStyles = (0, _uniqBy2.default)(scriptsAndStyles, item => item.name); const styles = scriptsAndStyles.filter(style => style.name && style.name.endsWith(`.css`)); styles.slice(0).reverse().forEach(style => { headComponents.unshift( /*#__PURE__*/_react.default.createElement("link", { "data-identity": `gatsby-dev-css`, key: style.name, rel: "stylesheet", type: "text/css", href: `${__PATH_PREFIX__}/${style.name}` })); }); class RouteHandler extends _react.default.Component { render() { var _pageData$result, _pageData$result$page; const props = { ...this.props, ...pageData.result, serverData, params: { ...(0, _findPath.grabMatchParams)(this.props.location.pathname), ...(((_pageData$result = pageData.result) === null || _pageData$result === void 0 ? void 0 : (_pageData$result$page = _pageData$result.pageContext) === null || _pageData$result$page === void 0 ? void 0 : _pageData$result$page.__params) || {}) } }; const pageElement = /*#__PURE__*/_react.default.createElement(preferDefault(_ssrSyncRequires.default.ssrComponents[componentChunkName]), props); const wrappedPage = (0, _apiRunnerSsr.apiRunner)(`wrapPageElement`, { element: pageElement, props }, pageElement, ({ result }) => { return { element: result, props }; }).pop(); return wrappedPage; } } const routerElement = _ssrSyncRequires.default.ssrComponents[componentChunkName] && !isClientOnlyPage ? /*#__PURE__*/_react.default.createElement(_reachRouter.ServerLocation, { url: `${__BASE_PATH__}${pagePath}` }, /*#__PURE__*/_react.default.createElement(_reachRouter.Router, { id: "gatsby-focus-wrapper", baseuri: __BASE_PATH__ }, /*#__PURE__*/_react.default.createElement(RouteHandler, { path: "/*" })), /*#__PURE__*/_react.default.createElement("div", _routeAnnouncerProps.RouteAnnouncerProps)) : null; let bodyComponent = (0, _apiRunnerSsr.apiRunner)(`wrapRootElement`, { element: routerElement, pathname: pagePath }, routerElement, ({ result }) => { return { element: result, pathname: pagePath }; }).pop(); if (process.env.GATSBY_SLICES) { const readSliceData = sliceName => { const filePath = _path.default.join(publicDir, `slice-data`, `${sliceName}.json`); const rawSliceData = _fsExtra.default.readFileSync(filePath, `utf-8`); return JSON.parse(rawSliceData); }; const slicesContext = { renderEnvironment: `dev-ssr` }; const sliceProps = {}; const slicesDb = new Map(); const sliceData = {}; for (const sliceName of Object.values(slicesMap)) { sliceData[sliceName] = await readSliceData(sliceName); } for (const sliceName of Object.values(slicesMap)) { const slice = sliceData[sliceName]; const { default: SliceComponent } = await getPageChunk(slice); const sliceObject = { component: SliceComponent, sliceContext: slice.result.sliceContext, data: slice.result.data }; slicesDb.set(sliceName, sliceObject); } bodyComponent = /*#__PURE__*/_react.default.createElement(_context.SlicesContext.Provider, { value: slicesContext }, /*#__PURE__*/_react.default.createElement(_context.SlicesPropsContext.Provider, { value: sliceProps }, /*#__PURE__*/_react.default.createElement(_context.SlicesMapContext.Provider, { value: slicesMap }, /*#__PURE__*/_react.default.createElement(_context.SlicesResultsContext.Provider, { value: slicesDb }, bodyComponent)))); } // Let the site or plugin render the page component. await (0, _apiRunnerSsr.apiRunnerAsync)(`replaceRenderer`, { bodyComponent, replaceBodyHTMLString, setHeadComponents, setHtmlAttributes, setBodyAttributes, setPreBodyComponents, setPostBodyComponents, setBodyProps, pathname: pagePath, pathPrefix: __PATH_PREFIX__ }); // If no one stepped up, we'll handle it. if (!bodyHtml) { try { const writableStream = new _writableAsPromise.WritableAsPromise(); const { pipe } = (0, _server.renderToPipeableStream)(bodyComponent, { onAllReady() { pipe(writableStream); }, onError(error) { writableStream.destroy(error); } }); bodyHtml = await writableStream; } catch (e) { // ignore @reach/router redirect errors if (!(0, _reachRouter.isRedirect)(e)) throw e; } } (0, _apiRunnerSsr.apiRunner)(`onRenderBody`, { setHeadComponents, setHtmlAttributes, setBodyAttributes, setPreBodyComponents, setPostBodyComponents, setBodyProps, pathname: pagePath }); // we want to run Head after onRenderBody, so Html and Body attributes // from Head wins over global ones from onRenderBody (0, _headExportHandlerForSsr.headHandlerForSSR)({ pageComponent, setHeadComponents, setHtmlAttributes, setBodyAttributes, staticQueryContext: (0, _loader.getStaticQueryResults)(), pageData, pagePath }); (0, _apiRunnerSsr.apiRunner)(`onPreRenderHTML`, { getHeadComponents, replaceHeadComponents, getPreBodyComponents, replacePreBodyComponents, getPostBodyComponents, replacePostBodyComponents, pathname: pagePath }); return bodyHtml; }; const bodyStr = await generateBodyHTML(); const htmlElement = /*#__PURE__*/_react.default.createElement(Html, { ...bodyProps, body: bodyStr, headComponents: headComponents.concat([/*#__PURE__*/_react.default.createElement("script", { key: `io`, src: "/socket.io/socket.io.js" })]), htmlAttributes, bodyAttributes, preBodyComponents, postBodyComponents: postBodyComponents.concat([!BROWSER_ESM_ONLY && /*#__PURE__*/_react.default.createElement("script", { key: `polyfill`, src: "/polyfill.js", noModule: true }), /*#__PURE__*/_react.default.createElement("script", { key: `framework`, src: "/framework.js" }), /*#__PURE__*/_react.default.createElement("script", { key: `commons`, src: "/commons.js" })].filter(Boolean)) }); let htmlStr = (0, _server.renderToStaticMarkup)(htmlElement); htmlStr = `<!DOCTYPE html>${htmlStr}`; return htmlStr; } function getPageChunk({ componentChunkName }) { return _ssrSyncRequires.default.ssrComponents[componentChunkName]; } //# sourceMappingURL=ssr-develop-static-entry.js.map