Skip to content

Commit 473eb19

Browse files
authored
Merge pull request #967 from evershopcommerce/optimize_build
fix(ssr): return 500 on render error instead of hanging; partial data…
2 parents 99a8f6e + a14fdff commit 473eb19

3 files changed

Lines changed: 25 additions & 12 deletions

File tree

packages/evershop/src/lib/response/render.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ function renderDevelopment(
117117
`);
118118
}
119119

120-
function renderProduction(request, response) {
120+
function renderProduction(request, response, next?) {
121121
const route = request.currentRoute;
122122
const serverIndexPath = path.resolve(
123123
getRouteBuildPath(route),
@@ -165,12 +165,19 @@ function renderProduction(request, response) {
165165
})
166166
.catch((e) => {
167167
error(e);
168+
// This render runs inside a floated promise, so a throw here never reaches
169+
// the calling middleware's try/catch. Without forwarding it, the request
170+
// hangs until the socket/requestTimeout fires (no status, no body). Hand it
171+
// to the error handler so the client gets a proper 500 instead.
172+
if (typeof next === 'function' && !response.headersSent) {
173+
next(e);
174+
}
168175
});
169176
}
170177

171-
export function render(request, response) {
178+
export function render(request, response, next?) {
172179
if (isProductionMode()) {
173-
renderProduction(request, response);
180+
renderProduction(request, response, next);
174181
} else {
175182
renderDevelopment(request, response);
176183
}

packages/evershop/src/modules/base/pages/global/response[errorHandler].ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ export default async (request: EvershopRequest, response, next) => {
119119
} as AppStateContextValue
120120
});
121121
} else {
122-
render(request, response);
122+
render(request, response, next);
123123
}
124124
}
125125
}

packages/evershop/src/modules/graphql/pages/global/[buildQuery]graphql[response].js

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,17 +73,23 @@ export default async function graphql(request, response, next) {
7373
document,
7474
variableValues: graphqlVariables
7575
});
76+
// Render with whatever data resolved instead of aborting the whole
77+
// page on the first field error. A single failing or non-critical
78+
// resolver (e.g. "related products") should degrade that area, not
79+
// turn the entire SSR response into a 500. Field errors are logged;
80+
// partial `data.data` (or {} on total failure) is passed through.
7681
if (data.errors) {
77-
next(data.errors[0]);
78-
} else {
79-
response.locals = response.locals || {};
80-
response.locals.graphqlResponse = JSON.parse(
81-
JSON.stringify(data.data)
82+
data.errors.forEach((e) =>
83+
debug(`GraphQL field error: ${e.message}`)
8284
);
83-
// Get id and props from the queryRaw object and assign to response.locals.propsMap
84-
response.locals.propsMap = propsMap;
85-
next();
8685
}
86+
response.locals = response.locals || {};
87+
response.locals.graphqlResponse = data.data
88+
? JSON.parse(JSON.stringify(data.data))
89+
: {};
90+
// Get id and props from the queryRaw object and assign to response.locals.propsMap
91+
response.locals.propsMap = propsMap;
92+
next();
8793
}
8894
}
8995
}

0 commit comments

Comments
 (0)