gatsby
Version:
Blazing fast modern site generator for React
730 lines (715 loc) • 31.7 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
exports.__esModule = true;
exports.startServer = startServer;
var _webpackHotMiddleware = _interopRequireDefault(require("@gatsbyjs/webpack-hot-middleware"));
var _webpackDevMiddleware = _interopRequireDefault(require("webpack-dev-middleware"));
var _got = _interopRequireDefault(require("got"));
var _webpack = _interopRequireDefault(require("webpack"));
var _express = _interopRequireDefault(require("express"));
var _compression = _interopRequireDefault(require("compression"));
var _express2 = require("graphql-http/lib/use/express");
var _gatsbyGraphiqlExplorer = _interopRequireDefault(require("gatsby-graphiql-explorer"));
var _graphql = require("graphql");
var _gatsbyCoreUtils = require("gatsby-core-utils");
var _http = _interopRequireDefault(require("http"));
var _https = _interopRequireDefault(require("https"));
var _cors = _interopRequireDefault(require("cors"));
var _gatsbyTelemetry = _interopRequireDefault(require("gatsby-telemetry"));
var _launchEditor = _interopRequireDefault(require("react-dev-utils/launchEditor"));
var _codeFrame = require("@babel/code-frame");
var fs = _interopRequireWildcard(require("fs-extra"));
var _path = require("../utils/path");
var _webpack2 = _interopRequireDefault(require("../utils/webpack.config"));
var _redux = require("../redux");
var _reporter = _interopRequireDefault(require("gatsby-cli/lib/reporter"));
var WorkerPool = _interopRequireWildcard(require("../utils/worker/pool"));
var _developStatic = require("../commands/develop-static");
var _context = _interopRequireDefault(require("../schema/context"));
var _websocketManager = require("../utils/websocket-manager");
var _pageData = require("./page-data");
var _getPageData = require("./get-page-data");
var _findPageByPath = require("./find-page-by-path");
var _apiRunnerNode = _interopRequireDefault(require("../utils/api-runner-node"));
var path = _interopRequireWildcard(require("path"));
var _types = require("../commands/types");
var _stackTraceUtils = require("./stack-trace-utils");
var _developPreloadHeaders = require("./develop-preload-headers");
var _loadingIndicator = require("./loading-indicator");
var _renderDevHtml = require("./dev-ssr/render-dev-html");
var _getServerData = require("./get-server-data");
var _constants = require("../constants");
var _pageMode = require("./page-mode");
var _expressMiddlewares = require("./express-middlewares");
var _polyfillRemoteFile = require("gatsby-plugin-utils/polyfill-remote-file");
var _isFileInsideCompilations = require("./webpack/utils/is-file-inside-compilations");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
async function startServer(program, app, workerPool = WorkerPool.create()) {
const directory = program.directory;
const PAGE_RENDERER_PATH = path.join(program.directory, _constants.ROUTES_DIRECTORY, `render-page.js`);
const webpackActivity = _reporter.default.activityTimer(`Building development bundle`, {
id: `webpack-develop`
});
webpackActivity.start();
// loading indicator
// write virtual module always to not fail webpack compilation, but only add express route handlers when
// query on demand is enabled and loading indicator is not disabled
(0, _loadingIndicator.writeVirtualLoadingIndicatorModule)();
// Remove the following when merging GATSBY_EXPERIMENTAL_DEV_SSR
const directoryPath = (0, _path.withBasePath)(directory);
const {
buildRenderer,
doBuildPages
} = require(`../commands/build-html`);
const createIndexHtml = async activity => {
try {
const {
rendererPath,
close
} = await buildRenderer(program, _types.Stage.DevelopHTML, activity.span);
await doBuildPages(rendererPath, [`/`], activity, workerPool, _types.Stage.DevelopHTML);
// close the compiler
await close();
} catch (err) {
if (err.name !== `WebpackError`) {
_reporter.default.panic(err);
return;
}
_reporter.default.panic(_reporter.default.stripIndent`
There was an error compiling the html.js component for the development server.
See our docs page on debugging HTML builds for help https://gatsby.dev/debug-html
`, err);
}
};
const indexHTMLActivity = _reporter.default.phantomActivity(`building index.html`, {});
let pageRenderer;
if (process.env.GATSBY_EXPERIMENTAL_DEV_SSR) {
const {
buildRenderer
} = require(`../commands/build-html`);
pageRenderer = (await buildRenderer(program, _types.Stage.DevelopHTML)).rendererPath;
const {
initDevWorkerPool
} = require(`./dev-ssr/render-dev-html`);
initDevWorkerPool();
} else {
indexHTMLActivity.start();
await createIndexHtml(indexHTMLActivity);
indexHTMLActivity.end();
}
const devConfig = await (0, _webpack2.default)(program, directory, _types.Stage.Develop, program.port, {
parentSpan: webpackActivity.span
});
const compiler = (0, _webpack.default)(devConfig);
/**
* Set up the express app.
**/
app.use((0, _compression.default)());
app.use(_gatsbyTelemetry.default.expressMiddleware(`DEVELOP`));
app.use((0, _webpackHotMiddleware.default)(compiler, {
log: false,
path: `/__webpack_hmr`,
heartbeat: 10 * 1000
}));
app.use((0, _cors.default)());
/**
* Pattern matching all endpoints with graphql or graphiql with 1 or more leading underscores
*/
const graphqlEndpoint = `/_+graphi?ql`;
(0, _gatsbyGraphiqlExplorer.default)(app, {
graphqlEndpoint,
getFragments: function getFragments() {
const fragments = [];
for (const def of _redux.store.getState().definitions.values()) {
if (def.def.kind === _graphql.Kind.FRAGMENT_DEFINITION) {
fragments.push(def.def);
}
}
return fragments;
}
});
app.use(graphqlEndpoint, (0, _express2.createHandler)({
schema() {
return _redux.store.getState().schema;
},
context() {
return (0, _context.default)({
schema: _redux.store.getState().schema,
schemaComposer: _redux.store.getState().schemaCustomization.composer,
context: {},
customContext: _redux.store.getState().schemaCustomization.context
});
},
onOperation(_req, _args, result) {
if (result.errors) {
result.errors = result.errors.map(err => ({
...err.toJSON(),
extensions: {
stack: err.stack ? err.stack.split(`\n`) : []
}
}));
}
result.extensions = {
enableRefresh: process.env.ENABLE_GATSBY_REFRESH_ENDPOINT,
refreshToken: process.env.GATSBY_REFRESH_TOKEN
};
return result;
}
}));
/**
* Refresh external data sources.
* This behavior is disabled by default, but the ENABLE_GATSBY_REFRESH_ENDPOINT env var enables it
* If no GATSBY_REFRESH_TOKEN env var is available, then no Authorization header is required
**/
const REFRESH_ENDPOINT = `/__refresh`;
const refresh = async (req, pluginName) => {
global.__GATSBY.buildId = _gatsbyCoreUtils.uuid.v4();
_redux.emitter.emit(`WEBHOOK_RECEIVED`, {
webhookBody: req.body,
pluginName
});
};
app.post(`${REFRESH_ENDPOINT}/:plugin_name?`, _express.default.json(), (req, res) => {
const pluginName = req.params[`plugin_name`];
const enableRefresh = process.env.ENABLE_GATSBY_REFRESH_ENDPOINT;
const refreshToken = process.env.GATSBY_REFRESH_TOKEN;
const authorizedRefresh = !refreshToken || req.headers.authorization === refreshToken;
if (enableRefresh && authorizedRefresh) {
refresh(req, pluginName);
res.status(200);
res.setHeader(`content-type`, `application/json`);
} else {
res.status(authorizedRefresh ? 404 : 403);
res.json({
error: enableRefresh ? `Authorization failed. Make sure you add authorization header to your refresh requests` : `Refresh endpoint is not enabled. Run gatsby with "ENABLE_GATSBY_REFRESH_ENDPOINT=true" environment variable set.`,
isEnabled: !!process.env.ENABLE_GATSBY_REFRESH_ENDPOINT
});
}
res.end();
});
app.get(`/__open-stack-frame-in-editor`, (req, res) => {
if (req.query.fileName) {
const fileName = path.resolve(process.cwd(), req.query.fileName);
const lineNumber = parseInt(req.query.lineNumber, 10);
(0, _launchEditor.default)(fileName, isNaN(lineNumber) ? 1 : lineNumber);
}
res.end();
});
(0, _polyfillRemoteFile.addImageRoutes)(app, _redux.store);
const webpackDevMiddlewareInstance = (0, _webpackDevMiddleware.default)(compiler, {
publicPath: devConfig.output.publicPath,
stats: `errors-only`,
serverSideRender: true
});
app.use(webpackDevMiddlewareInstance);
app.get(`/page-data/:pagePath(*)/page-data.json`, async (req, res, next) => {
const requestedPagePath = req.params.pagePath;
if (!requestedPagePath) {
next();
return;
}
const potentialPagePath = (0, _pageData.reverseFixedPagePath)(requestedPagePath);
const page = (0, _findPageByPath.findPageByPath)(_redux.store.getState(), potentialPagePath, false);
if (page) {
try {
let serverDataPromise = Promise.resolve({});
const pageMode = (0, _pageMode.getPageMode)(page);
if (pageMode === `SSR`) {
const renderer = require(PAGE_RENDERER_PATH);
const componentInstance = await renderer.getPageChunk(page);
serverDataPromise = (0, _getServerData.getServerData)(req, page, potentialPagePath, componentInstance).catch(error => error);
}
let pageData;
// TODO move to query-engine
if (process.env.GATSBY_QUERY_ON_DEMAND) {
const start = Date.now();
pageData = await (0, _getPageData.getPageData)(page.path);
_gatsbyTelemetry.default.trackCli(`RUN_QUERY_ON_DEMAND`, {
name: `getPageData`,
duration: Date.now() - start
});
} else {
pageData = await (0, _pageData.readPageData)(path.join(_redux.store.getState().program.directory, `public`), page.path);
}
let statusCode = 200;
if (pageMode === `SSR`) {
try {
const result = await serverDataPromise;
if (result instanceof Error) {
throw result;
}
if (result.headers) {
for (const [name, value] of Object.entries(result.headers)) {
res.setHeader(name, value);
}
}
if (result.status) {
statusCode = result.status;
}
pageData.result.serverData = result.props;
pageData.getServerDataError = null;
} catch (error) {
const structuredError = _reporter.default.panicOnBuild({
id: `95315`,
context: {
sourceMessage: error.message,
pagePath: requestedPagePath,
potentialPagePath
},
error
});
// Use page-data.json file instead of emitting via websockets as this makes it easier
// to only display the relevant error + clearing of the error
// The query-result-store reacts to this
pageData.getServerDataError = structuredError;
}
pageData.path = page.matchPath ? `/${potentialPagePath}` : page.path;
} else {
// When user removes getServerData function, Gatsby browser runtime still has cached version of page-data.
// Send `null` to always reset cached serverData:
pageData.result.serverData = null;
}
res.status(statusCode).send(pageData);
return;
} catch (e) {
_reporter.default.error(`Error loading a result for the page query in "${requestedPagePath}" / "${potentialPagePath}". Query was not run and no cached result was found.`, e);
}
}
res.status(404).send({
path: potentialPagePath
});
});
app.get(`/__original-stack-frame`, (req, res) => {
var _req$query, _sourceLine, _sourceColumn;
const emptyResponse = {
codeFrame: `No codeFrame could be generated`,
sourcePosition: null,
sourceContent: null
};
let sourceContent;
let sourceLine;
let sourceColumn;
let sourceEndLine;
let sourceEndColumn;
let sourcePosition;
if ((_req$query = req.query) !== null && _req$query !== void 0 && _req$query.skipSourceMap) {
var _req$query2, _res$locals, _res$locals$webpack, _res$locals$webpack$d, _res$locals$webpack$d2, _req$query3;
if (!((_req$query2 = req.query) !== null && _req$query2 !== void 0 && _req$query2.moduleId)) {
res.json(emptyResponse);
return;
}
const absolutePath = path.resolve(_redux.store.getState().program.directory, req.query.moduleId);
const compilation = (_res$locals = res.locals) === null || _res$locals === void 0 ? void 0 : (_res$locals$webpack = _res$locals.webpack) === null || _res$locals$webpack === void 0 ? void 0 : (_res$locals$webpack$d = _res$locals$webpack.devMiddleware) === null || _res$locals$webpack$d === void 0 ? void 0 : (_res$locals$webpack$d2 = _res$locals$webpack$d.stats) === null || _res$locals$webpack$d2 === void 0 ? void 0 : _res$locals$webpack$d2.compilation;
if (!compilation) {
res.json(emptyResponse);
return;
}
if (!(0, _isFileInsideCompilations.isFileInsideCompilations)(absolutePath, compilation)) {
res.json(emptyResponse);
return;
}
try {
sourceContent = fs.readFileSync(absolutePath, `utf-8`);
} catch (e) {
res.json(emptyResponse);
return;
}
if ((_req$query3 = req.query) !== null && _req$query3 !== void 0 && _req$query3.lineNumber) {
try {
var _req$query4, _req$query5, _req$query6;
sourceLine = parseInt(req.query.lineNumber, 10);
if ((_req$query4 = req.query) !== null && _req$query4 !== void 0 && _req$query4.endLineNumber) {
sourceEndLine = parseInt(req.query.endLineNumber, 10);
}
if ((_req$query5 = req.query) !== null && _req$query5 !== void 0 && _req$query5.columnNumber) {
sourceColumn = parseInt(req.query.columnNumber, 10);
}
if ((_req$query6 = req.query) !== null && _req$query6 !== void 0 && _req$query6.endColumnNumber) {
sourceEndColumn = parseInt(req.query.endColumnNumber, 10);
}
} catch {
// failed to get line/column, we should still try to show the code frame
}
}
sourcePosition = {
line: sourceLine,
column: sourceColumn
};
} else {
var _res$locals2, _res$locals2$webpack, _res$locals2$webpack$, _res$locals2$webpack$2, _req$query7, _ref, _req$query8, _ref2, _req$query9, _compilation$codeGene, _compilation$codeGene2, _sourcePosition, _sourcePosition2;
const compilation = (_res$locals2 = res.locals) === null || _res$locals2 === void 0 ? void 0 : (_res$locals2$webpack = _res$locals2.webpack) === null || _res$locals2$webpack === void 0 ? void 0 : (_res$locals2$webpack$ = _res$locals2$webpack.devMiddleware) === null || _res$locals2$webpack$ === void 0 ? void 0 : (_res$locals2$webpack$2 = _res$locals2$webpack$.stats) === null || _res$locals2$webpack$2 === void 0 ? void 0 : _res$locals2$webpack$2.compilation;
if (!compilation) {
res.json(emptyResponse);
return;
}
const moduleId = (_req$query7 = req.query) === null || _req$query7 === void 0 ? void 0 : _req$query7.moduleId;
const lineNumber = parseInt((_ref = (_req$query8 = req.query) === null || _req$query8 === void 0 ? void 0 : _req$query8.lineNumber) !== null && _ref !== void 0 ? _ref : 1, 10);
const columnNumber = parseInt((_ref2 = (_req$query9 = req.query) === null || _req$query9 === void 0 ? void 0 : _req$query9.columnNumber) !== null && _ref2 !== void 0 ? _ref2 : 1, 10);
let fileModule;
for (const module of compilation.modules) {
const moduleIdentifier = compilation.chunkGraph.getModuleId(module);
if (moduleIdentifier === moduleId) {
fileModule = module;
break;
}
}
if (!fileModule) {
res.json(emptyResponse);
return;
}
// We need the internal webpack file that is used in the bundle, not the module source.
// It doesn't have the correct sourceMap.
const webpackSource = compilation === null || compilation === void 0 ? void 0 : (_compilation$codeGene = compilation.codeGenerationResults) === null || _compilation$codeGene === void 0 ? void 0 : (_compilation$codeGene2 = _compilation$codeGene.get(fileModule)) === null || _compilation$codeGene2 === void 0 ? void 0 : _compilation$codeGene2.sources.get(`javascript`);
const sourceMap = webpackSource === null || webpackSource === void 0 ? void 0 : webpackSource.map();
if (!sourceMap) {
res.json(emptyResponse);
return;
}
const position = {
line: lineNumber,
column: columnNumber
};
const result = (0, _stackTraceUtils.findOriginalSourcePositionAndContent)(sourceMap, position);
sourcePosition = result === null || result === void 0 ? void 0 : result.sourcePosition;
sourceLine = (_sourcePosition = sourcePosition) === null || _sourcePosition === void 0 ? void 0 : _sourcePosition.line;
sourceColumn = (_sourcePosition2 = sourcePosition) === null || _sourcePosition2 === void 0 ? void 0 : _sourcePosition2.column;
sourceContent = result === null || result === void 0 ? void 0 : result.sourceContent;
if (!sourceContent || !sourceLine) {
res.json(emptyResponse);
return;
}
}
const codeFrame = (0, _codeFrame.codeFrameColumns)(sourceContent, {
start: {
line: (_sourceLine = sourceLine) !== null && _sourceLine !== void 0 ? _sourceLine : 0,
column: (_sourceColumn = sourceColumn) !== null && _sourceColumn !== void 0 ? _sourceColumn : 0
},
end: sourceEndLine ? {
line: sourceEndLine,
column: sourceEndColumn
} : undefined
}, {
highlightCode: true
});
res.json({
codeFrame,
sourcePosition,
sourceContent
});
});
app.get(`/__file-code-frame`, async (req, res) => {
var _req$query10, _req$query11, _req$query12, _res$locals3, _res$locals3$webpack, _res$locals3$webpack$, _res$locals3$webpack$2;
const emptyResponse = {
codeFrame: `No codeFrame could be generated`,
sourcePosition: null,
sourceContent: null
};
const filePath = (_req$query10 = req.query) === null || _req$query10 === void 0 ? void 0 : _req$query10.filePath;
const lineNumber = parseInt((_req$query11 = req.query) === null || _req$query11 === void 0 ? void 0 : _req$query11.lineNumber, 10);
const columnNumber = parseInt((_req$query12 = req.query) === null || _req$query12 === void 0 ? void 0 : _req$query12.columnNumber, 10);
if (!filePath) {
res.json(emptyResponse);
return;
}
const absolutePath = path.resolve(_redux.store.getState().program.directory, filePath);
const compilation = (_res$locals3 = res.locals) === null || _res$locals3 === void 0 ? void 0 : (_res$locals3$webpack = _res$locals3.webpack) === null || _res$locals3$webpack === void 0 ? void 0 : (_res$locals3$webpack$ = _res$locals3$webpack.devMiddleware) === null || _res$locals3$webpack$ === void 0 ? void 0 : (_res$locals3$webpack$2 = _res$locals3$webpack$.stats) === null || _res$locals3$webpack$2 === void 0 ? void 0 : _res$locals3$webpack$2.compilation;
if (!compilation) {
res.json(emptyResponse);
return;
}
if (!(0, _isFileInsideCompilations.isFileInsideCompilations)(absolutePath, compilation)) {
res.json(emptyResponse);
return;
}
const sourceContent = await fs.readFile(absolutePath, `utf-8`);
const codeFrame = (0, _codeFrame.codeFrameColumns)(sourceContent, {
start: {
line: lineNumber,
column: columnNumber !== null && columnNumber !== void 0 ? columnNumber : 0
}
}, {
highlightCode: true
});
res.json({
codeFrame
});
});
// Expose access to app for advanced use cases
const {
developMiddleware
} = _redux.store.getState().config;
if (developMiddleware) {
developMiddleware(app);
}
const {
proxy,
trailingSlash
} = _redux.store.getState().config;
app.use((0, _expressMiddlewares.configureTrailingSlash)(() => _redux.store.getState(), trailingSlash));
// Disable directory indexing i.e. serving index.html from a directory.
// This can lead to serving stale html files during development.
//
// We serve by default an empty index.html that sets up the dev environment.
app.use((0, _developStatic.developStatic)(`public`, {
index: false
}));
// Set up API proxy.
if (proxy) {
proxy.forEach(({
prefix,
url
}) => {
app.use(`${prefix}/*`, (req, res) => {
const proxiedUrl = url + req.originalUrl;
const {
// remove `host` from copied headers
// eslint-disable-next-line @typescript-eslint/no-unused-vars
headers: {
host,
...headers
},
method
} = req;
req.pipe(_got.default.stream(proxiedUrl, {
headers,
method: method,
decompress: false
}).on(`response`, response => res.writeHead(response.statusCode || 200, response.headers)).on(`error`, (err, _, response) => {
if (response) {
res.writeHead(response.statusCode || 400, response.headers);
} else {
const message = `Error when trying to proxy request "${req.originalUrl}" to "${proxiedUrl}"`;
_reporter.default.error(message, err);
res.sendStatus(500);
}
})).pipe(res);
});
}, (0, _cors.default)());
}
await (0, _apiRunnerNode.default)(`onCreateDevServer`, {
app,
deferNodeMutation: true
});
// In case nothing before handled hot-update - send 404.
// This fixes "Unexpected token < in JSON at position 0" runtime
// errors after restarting development server and
// cause automatic hard refresh in the browser.
app.use(/.*\.hot-update\.json$/i, (_, res) => {
res.status(404).end();
});
// Render an HTML page and serve it.
if (process.env.GATSBY_EXPERIMENTAL_DEV_SSR) {
app.get(`*`, async (req, res, next) => {
_gatsbyTelemetry.default.trackFeatureIsUsed(`GATSBY_EXPERIMENTAL_DEV_SSR`);
const pathObj = (0, _findPageByPath.findPageByPath)(_redux.store.getState(), decodeURI(req.path));
if (!pathObj) {
return next();
}
const allowTimedFallback = !req.headers[`x-gatsby-wait-for-dev-ssr`];
await (0, _developPreloadHeaders.appendPreloadHeaders)(pathObj.path, res);
const htmlActivity = _reporter.default.phantomActivity(`building HTML for path`, {});
htmlActivity.start();
try {
const {
html: renderResponse,
serverData
} = await (0, _renderDevHtml.renderDevHTML)({
path: pathObj.path,
page: pathObj,
skipSsr: Object.prototype.hasOwnProperty.call(req.query, `skip-ssr`),
store: _redux.store,
allowTimedFallback,
htmlComponentRendererPath: PAGE_RENDERER_PATH,
directory: program.directory,
req
});
if (serverData !== null && serverData !== void 0 && serverData.headers) {
for (const [name, value] of Object.entries(serverData.headers)) {
res.setHeader(name, value);
}
}
let statusCode = 200;
if (serverData !== null && serverData !== void 0 && serverData.status) {
statusCode = serverData.status;
}
res.status(statusCode).send(renderResponse);
} catch (error) {
// The page errored but couldn't read the page component.
// This is a race condition when a page is deleted but its requested
// immediately after before anything can recompile.
if (error === `404 page`) {
return next();
}
// renderDevHTML throws an error with these information
const lineNumber = error === null || error === void 0 ? void 0 : error.line;
const columnNumber = error === null || error === void 0 ? void 0 : error.column;
const filePath = error === null || error === void 0 ? void 0 : error.filename;
const sourceContent = error === null || error === void 0 ? void 0 : error.sourceContent;
_reporter.default.error({
id: `11614`,
context: {
path: pathObj.path,
filePath: filePath,
line: lineNumber,
column: columnNumber
}
});
const emptyResponse = {
codeFrame: `No codeFrame could be generated`,
sourcePosition: null,
sourceContent: null
};
if (!sourceContent || !lineNumber) {
res.json(emptyResponse);
return null;
}
const codeFrame = (0, _codeFrame.codeFrameColumns)(sourceContent, {
start: {
line: lineNumber,
column: columnNumber !== null && columnNumber !== void 0 ? columnNumber : 0
}
}, {
highlightCode: true
});
const message = {
codeFrame,
source: filePath,
line: lineNumber,
column: columnNumber !== null && columnNumber !== void 0 ? columnNumber : 0,
sourceMessage: error === null || error === void 0 ? void 0 : error.message,
stack: error === null || error === void 0 ? void 0 : error.stack
};
try {
// Generate a shell for client-only content -- for the error overlay
const {
html: clientOnlyShell
} = await (0, _renderDevHtml.renderDevHTML)({
path: pathObj.path,
page: pathObj,
skipSsr: true,
store: _redux.store,
error: message,
htmlComponentRendererPath: PAGE_RENDERER_PATH,
directory: program.directory,
req,
allowTimedFallback
});
res.send(clientOnlyShell);
} catch (e) {
_reporter.default.error({
id: `11616`,
context: {
sourceMessage: e.message
},
filePath: e.filename,
location: {
start: {
line: e.line,
column: e.column
}
}
});
const minimalHTML = `<head><title>Failed to Server Render (SSR)</title></head><body><h1>Failed to Server Render (SSR)</h1><h2>Error message:</h2><p>${e.message}</p><h2>File:</h2><p>${e.filename}:${e.line}:${e.column}</p><h2>Stack:</h2><pre><code>${e.stack}</code></pre></body>`;
res.send(minimalHTML).status(500);
}
}
htmlActivity.end();
return null;
});
}
if (process.env.GATSBY_QUERY_ON_DEMAND && process.env.GATSBY_QUERY_ON_DEMAND_LOADING_INDICATOR === `true`) {
(0, _loadingIndicator.routeLoadingIndicatorRequests)(app);
}
app.use(async (req, res) => {
// in this catch-all block we don't support POST so we should 404
if (req.method === `POST`) {
res.status(404).end();
return;
}
const fullUrl = req.protocol + `://` + req.get(`host`) + req.originalUrl;
// This isn't used in development.
if (fullUrl.endsWith(`app-data.json`)) {
res.json({
webpackCompilationHash: `123`
});
// If this gets here, it's a non-existent file so just send back 404.
} else if (fullUrl.endsWith(`.json`)) {
res.json({}).status(404);
} else {
await (0, _developPreloadHeaders.appendPreloadHeaders)(req.path, res);
if (process.env.GATSBY_EXPERIMENTAL_DEV_SSR) {
try {
const allowTimedFallback = !req.headers[`x-gatsby-wait-for-dev-ssr`];
const {
html: renderResponse
} = await (0, _renderDevHtml.renderDevHTML)({
path: `/dev-404-page/`,
// Let renderDevHTML figure it out.
page: undefined,
store: _redux.store,
htmlComponentRendererPath: pageRenderer,
directory: program.directory,
req,
allowTimedFallback
});
res.status(404).send(renderResponse);
} catch (e) {
_reporter.default.error({
id: `11615`,
context: {
sourceMessage: e.message
},
filePath: e.filename,
location: {
start: {
line: e.line,
column: e.column
}
}
});
res.send(e).status(500);
}
} else {
const potentialPagePath = (0, _pageData.reverseFixedPagePath)(decodeURI(req.path));
const page = (0, _findPageByPath.findPageByPath)(_redux.store.getState(), potentialPagePath, false);
// When we can't find a page we send 404
if (!page) {
res.status(404);
}
res.sendFile(directoryPath(`.cache/develop-html/index.html`), err => {
if (err) {
res.status(500).end();
}
});
}
}
});
/**
* Set up the HTTP server and socket.io.
**/
const server = program.ssl ? new _https.default.Server(program.ssl, app) : new _http.default.Server(app);
const socket = _websocketManager.websocketManager.init({
server
});
const listener = server.listen(program.port, program.host);
if (!process.env.GATSBY_EXPERIMENTAL_DEV_SSR) {
const chokidar = require(`chokidar`);
// Register watcher that rebuilds index.html every time html.js changes.
const watchGlobs = [`src/html.js`, `plugins/**/gatsby-ssr.js`].map(path => (0, _gatsbyCoreUtils.slash)(directoryPath(path)));
chokidar.watch(watchGlobs).on(`change`, async () => {
await createIndexHtml(indexHTMLActivity);
// eslint-disable-next-line no-unused-expressions
socket === null || socket === void 0 ? void 0 : socket.to(`clients`).emit(`reload`);
});
}
return {
compiler,
listener,
webpackActivity,
websocketManager: _websocketManager.websocketManager,
workerPool,
webpackWatching: webpackDevMiddlewareInstance.context.watching
};
}
//# sourceMappingURL=start-server.js.map
;