-
Notifications
You must be signed in to change notification settings - Fork 27.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: include promises from late waitUntil calls in FetchEventResult.waitUntil #66747
base: fix-pass-waituntil-to-webserver
Are you sure you want to change the base?
fix: include promises from late waitUntil calls in FetchEventResult.waitUntil #66747
Conversation
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. Join @lubieowoce and the rest of your teammates on Graphite |
Failing test suitesCommit: b713ed0
Expand output● unstable_after() in edge runtime › runs in dynamic pages
● unstable_after() in edge runtime › runs in server actions
● unstable_after() in edge runtime › runs callbacks from nested unstable_after calls
● unstable_after() in edge runtime › interrupted RSC renders › runs callbacks if redirect() was called
● unstable_after() in edge runtime › interrupted RSC renders › runs callbacks if notFound() was called
● unstable_after() in edge runtime › interrupted RSC renders › runs callbacks if a user error was thrown in the RSC render
● unstable_after() in edge runtime › only runs callbacks after the response is fully sent
● unstable_after() in edge runtime › runs in generateMetadata()
● unstable_after() in edge runtime › does not allow modifying cookies in a callback
Read more about building and testing Next.js in contributing.md.
Expand output● deterministic build › should have same md5 file across build
Read more about building and testing Next.js in contributing.md.
Expand output● app-dir-hmr › filesystem changes › should not break when renaming a folder
Read more about building and testing Next.js in contributing.md. |
Stats from current PRDefault Build (Increase detected
|
vercel/next.js canary | vercel/next.js fix-adapter-waituntil-streaming | Change | |
---|---|---|---|
buildDuration | 16.7s | 16.5s | N/A |
buildDurationCached | 8.7s | 7.3s | N/A |
nodeModulesSize | 352 MB | 352 MB | N/A |
nextStartRea..uration (ms) | 421ms | 436ms | N/A |
Client Bundles (main, webpack)
vercel/next.js canary | vercel/next.js fix-adapter-waituntil-streaming | Change | |
---|---|---|---|
124-HASH.js gzip | 37.3 kB | 37.3 kB | N/A |
5121a57b-HASH.js gzip | 51.9 kB | 51.9 kB | N/A |
7480.HASH.js gzip | 169 B | 169 B | ✓ |
935-HASH.js gzip | 5.19 kB | 5.19 kB | N/A |
framework-HASH.js gzip | 56.7 kB | 56.7 kB | ✓ |
main-app-HASH.js gzip | 223 B | 225 B | N/A |
main-HASH.js gzip | 32.5 kB | 32.2 kB | N/A |
webpack-HASH.js gzip | 1.71 kB | 1.71 kB | ✓ |
Overall change | 58.6 kB | 58.6 kB | ✓ |
Legacy Client Bundles (polyfills)
vercel/next.js canary | vercel/next.js fix-adapter-waituntil-streaming | Change | |
---|---|---|---|
polyfills-HASH.js gzip | 31 kB | 31 kB | ✓ |
Overall change | 31 kB | 31 kB | ✓ |
Client Pages
vercel/next.js canary | vercel/next.js fix-adapter-waituntil-streaming | Change | |
---|---|---|---|
_app-HASH.js gzip | 193 B | 194 B | N/A |
_error-HASH.js gzip | 193 B | 192 B | N/A |
amp-HASH.js gzip | 509 B | 511 B | N/A |
css-HASH.js gzip | 342 B | 343 B | N/A |
dynamic-HASH.js gzip | 1.84 kB | 1.84 kB | ✓ |
edge-ssr-HASH.js gzip | 265 B | 266 B | N/A |
head-HASH.js gzip | 362 B | 364 B | N/A |
hooks-HASH.js gzip | 393 B | 393 B | ✓ |
image-HASH.js gzip | 4.4 kB | 4.4 kB | ✓ |
index-HASH.js gzip | 268 B | 267 B | N/A |
link-HASH.js gzip | 2.81 kB | 2.81 kB | N/A |
routerDirect..HASH.js gzip | 329 B | 327 B | N/A |
script-HASH.js gzip | 395 B | 396 B | N/A |
withRouter-HASH.js gzip | 325 B | 323 B | N/A |
1afbb74e6ecf..834.css gzip | 106 B | 106 B | ✓ |
Overall change | 6.74 kB | 6.74 kB | ✓ |
Client Build Manifests
vercel/next.js canary | vercel/next.js fix-adapter-waituntil-streaming | Change | |
---|---|---|---|
_buildManifest.js gzip | 748 B | 748 B | ✓ |
Overall change | 748 B | 748 B | ✓ |
Rendered Page Sizes
vercel/next.js canary | vercel/next.js fix-adapter-waituntil-streaming | Change | |
---|---|---|---|
index.html gzip | 521 B | 521 B | ✓ |
link.html gzip | 536 B | 538 B | N/A |
withRouter.html gzip | 517 B | 518 B | N/A |
Overall change | 521 B | 521 B | ✓ |
Edge SSR bundle Size Overall increase ⚠️
vercel/next.js canary | vercel/next.js fix-adapter-waituntil-streaming | Change | |
---|---|---|---|
edge-ssr.js gzip | 127 kB | 128 kB | |
page.js gzip | 168 kB | 168 kB | |
Overall change | 295 kB | 296 kB |
Middleware size Overall increase ⚠️
vercel/next.js canary | vercel/next.js fix-adapter-waituntil-streaming | Change | |
---|---|---|---|
middleware-b..fest.js gzip | 669 B | 670 B | N/A |
middleware-r..fest.js gzip | 155 B | 156 B | N/A |
middleware.js gzip | 29.6 kB | 29.9 kB | |
edge-runtime..pack.js gzip | 1.03 kB | 1.03 kB | ✓ |
Overall change | 30.6 kB | 30.9 kB |
Next Runtimes
vercel/next.js canary | vercel/next.js fix-adapter-waituntil-streaming | Change | |
---|---|---|---|
928-experime...dev.js gzip | 310 B | 310 B | ✓ |
928.runtime.dev.js gzip | 301 B | 301 B | ✓ |
app-page-exp...dev.js gzip | 246 kB | 246 kB | N/A |
app-page-exp..prod.js gzip | 121 kB | 120 kB | N/A |
app-page-tur..prod.js gzip | 133 kB | 132 kB | N/A |
app-page-tur..prod.js gzip | 128 kB | 128 kB | N/A |
app-page.run...dev.js gzip | 232 kB | 232 kB | N/A |
app-page.run..prod.js gzip | 117 kB | 117 kB | N/A |
app-route-ex...dev.js gzip | 23.1 kB | 23.1 kB | N/A |
app-route-ex..prod.js gzip | 18.8 kB | 18.8 kB | N/A |
app-route-tu..prod.js gzip | 18.8 kB | 18.8 kB | N/A |
app-route-tu..prod.js gzip | 18.6 kB | 18.6 kB | N/A |
app-route.ru...dev.js gzip | 24.4 kB | 24.4 kB | N/A |
app-route.ru..prod.js gzip | 18.6 kB | 18.6 kB | N/A |
pages-api-tu..prod.js gzip | 9.6 kB | 9.6 kB | ✓ |
pages-api.ru...dev.js gzip | 9.87 kB | 9.87 kB | ✓ |
pages-api.ru..prod.js gzip | 9.59 kB | 9.59 kB | ✓ |
pages-turbo...prod.js gzip | 21.6 kB | 21.6 kB | ✓ |
pages.runtim...dev.js gzip | 22.2 kB | 22.2 kB | ✓ |
pages.runtim..prod.js gzip | 21.6 kB | 21.6 kB | ✓ |
server.runti..prod.js gzip | 56.8 kB | 56.8 kB | N/A |
Overall change | 95 kB | 95 kB | ✓ |
build cache
vercel/next.js canary | vercel/next.js fix-adapter-waituntil-streaming | Change | |
---|---|---|---|
0.pack gzip | 1.41 MB | 1.41 MB | N/A |
index.pack gzip | 121 kB | 121 kB | N/A |
Overall change | 0 B | 0 B | ✓ |
Diff details
Diff for page.js
Diff too large to display
Diff for middleware.js
Diff too large to display
Diff for edge-ssr.js
Diff too large to display
Diff for image-HASH.js
@@ -1,7 +1,7 @@
(self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
[8358],
{
- /***/ 8316: /***/ (
+ /***/ 8834: /***/ (
__unused_webpack_module,
__unused_webpack_exports,
__webpack_require__
@@ -9,7 +9,7 @@
(window.__NEXT_P = window.__NEXT_P || []).push([
"/image",
function () {
- return __webpack_require__(4765);
+ return __webpack_require__(5780);
},
]);
if (false) {
@@ -18,7 +18,7 @@
/***/
},
- /***/ 1112: /***/ (module, exports, __webpack_require__) => {
+ /***/ 7481: /***/ (module, exports, __webpack_require__) => {
"use strict";
/* __next_internal_client_entry_do_not_use__ cjs */
Object.defineProperty(exports, "__esModule", {
@@ -40,17 +40,17 @@
__webpack_require__(5596)
);
const _head = /*#__PURE__*/ _interop_require_default._(
- __webpack_require__(9382)
+ __webpack_require__(9639)
);
- const _getimgprops = __webpack_require__(2097);
- const _imageconfig = __webpack_require__(8714);
- const _imageconfigcontextsharedruntime = __webpack_require__(1327);
- const _warnonce = __webpack_require__(6055);
- const _routercontextsharedruntime = __webpack_require__(8275);
+ const _getimgprops = __webpack_require__(1607);
+ const _imageconfig = __webpack_require__(2867);
+ const _imageconfigcontextsharedruntime = __webpack_require__(1015);
+ const _warnonce = __webpack_require__(6694);
+ const _routercontextsharedruntime = __webpack_require__(9562);
const _imageloader = /*#__PURE__*/ _interop_require_default._(
- __webpack_require__(6067)
+ __webpack_require__(3463)
);
- const _usemergedref = __webpack_require__(1261);
+ const _usemergedref = __webpack_require__(1057);
// This is replaced by webpack define plugin
const configEnv = {
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
@@ -371,7 +371,7 @@
/***/
},
- /***/ 1261: /***/ (module, exports, __webpack_require__) => {
+ /***/ 1057: /***/ (module, exports, __webpack_require__) => {
"use strict";
Object.defineProperty(exports, "__esModule", {
@@ -440,7 +440,7 @@
/***/
},
- /***/ 2097: /***/ (
+ /***/ 1607: /***/ (
__unused_webpack_module,
exports,
__webpack_require__
@@ -456,9 +456,9 @@
return getImgProps;
},
});
- const _warnonce = __webpack_require__(6055);
- const _imageblursvg = __webpack_require__(9254);
- const _imageconfig = __webpack_require__(8714);
+ const _warnonce = __webpack_require__(6694);
+ const _imageblursvg = __webpack_require__(9866);
+ const _imageconfig = __webpack_require__(2867);
const VALID_LOADING_VALUES =
/* unused pure expression or super */ null && [
"lazy",
@@ -830,7 +830,7 @@
/***/
},
- /***/ 9254: /***/ (__unused_webpack_module, exports) => {
+ /***/ 9866: /***/ (__unused_webpack_module, exports) => {
"use strict";
/**
* A shared function, used on both client and server, to generate a SVG blur placeholder.
@@ -885,7 +885,7 @@
/***/
},
- /***/ 9331: /***/ (
+ /***/ 3484: /***/ (
__unused_webpack_module,
exports,
__webpack_require__
@@ -912,10 +912,10 @@
},
});
const _interop_require_default = __webpack_require__(4345);
- const _getimgprops = __webpack_require__(2097);
- const _imagecomponent = __webpack_require__(1112);
+ const _getimgprops = __webpack_require__(1607);
+ const _imagecomponent = __webpack_require__(7481);
const _imageloader = /*#__PURE__*/ _interop_require_default._(
- __webpack_require__(6067)
+ __webpack_require__(3463)
);
function getImageProps(imgProps) {
const { props } = (0, _getimgprops.getImgProps)(imgProps, {
@@ -947,7 +947,7 @@
/***/
},
- /***/ 6067: /***/ (__unused_webpack_module, exports) => {
+ /***/ 3463: /***/ (__unused_webpack_module, exports) => {
"use strict";
Object.defineProperty(exports, "__esModule", {
@@ -982,7 +982,7 @@
/***/
},
- /***/ 4765: /***/ (
+ /***/ 5780: /***/ (
__unused_webpack_module,
__webpack_exports__,
__webpack_require__
@@ -999,8 +999,8 @@
// EXTERNAL MODULE: ./node_modules/.pnpm/[email protected]/node_modules/react/jsx-runtime.js
var jsx_runtime = __webpack_require__(3262);
- // EXTERNAL MODULE: ./node_modules/.pnpm/next@file+..+main-repo+packages+next+next-packed.tgz_react-dom@19.0.0-rc-06d0b89e-20240801_re_432dyi3er6pnalgpduyz2i6axm/node_modules/next/image.js
- var next_image = __webpack_require__(2692);
+ // EXTERNAL MODULE: ./node_modules/.pnpm/next@file+..+diff-repo+packages+next+next-packed.tgz_react-dom@19.0.0-rc-06d0b89e-20240801_re_wusbvjw3sleq6d7g7gklhdw6bm/node_modules/next/image.js
+ var next_image = __webpack_require__(8565);
var image_default = /*#__PURE__*/ __webpack_require__.n(next_image); // CONCATENATED MODULE: ./pages/nextjs.png
/* harmony default export */ const nextjs = {
src: "/_next/static/media/nextjs.cae0b805.png",
@@ -1030,12 +1030,12 @@
/***/
},
- /***/ 2692: /***/ (
+ /***/ 8565: /***/ (
module,
__unused_webpack_exports,
__webpack_require__
) => {
- module.exports = __webpack_require__(9331);
+ module.exports = __webpack_require__(3484);
/***/
},
@@ -1045,7 +1045,7 @@
/******/ var __webpack_exec__ = (moduleId) =>
__webpack_require__((__webpack_require__.s = moduleId));
/******/ __webpack_require__.O(0, [2888, 9774, 179], () =>
- __webpack_exec__(8316)
+ __webpack_exec__(8834)
);
/******/ var __webpack_exports__ = __webpack_require__.O();
/******/ _N_E = __webpack_exports__;
Diff for link-HASH.js
@@ -1,7 +1,7 @@
(self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([
[4644],
{
- /***/ 3809: /***/ (
+ /***/ 9251: /***/ (
__unused_webpack_module,
__unused_webpack_exports,
__webpack_require__
@@ -9,7 +9,7 @@
(window.__NEXT_P = window.__NEXT_P || []).push([
"/link",
function () {
- return __webpack_require__(484);
+ return __webpack_require__(7234);
},
]);
if (false) {
@@ -18,7 +18,7 @@
/***/
},
- /***/ 9298: /***/ (module, exports) => {
+ /***/ 9580: /***/ (module, exports) => {
"use strict";
Object.defineProperty(exports, "__esModule", {
@@ -110,7 +110,7 @@
/***/
},
- /***/ 8909: /***/ (module, exports, __webpack_require__) => {
+ /***/ 2876: /***/ (module, exports, __webpack_require__) => {
"use strict";
Object.defineProperty(exports, "__esModule", {
@@ -122,7 +122,7 @@
return getDomainLocale;
},
});
- const _normalizetrailingslash = __webpack_require__(6010);
+ const _normalizetrailingslash = __webpack_require__(43);
const basePath =
/* unused pure expression or super */ null && (false || "");
function getDomainLocale(path, locale, locales, domainLocales) {
@@ -146,7 +146,7 @@
/***/
},
- /***/ 4300: /***/ (module, exports, __webpack_require__) => {
+ /***/ 8612: /***/ (module, exports, __webpack_require__) => {
"use strict";
/* __next_internal_client_entry_do_not_use__ cjs */
Object.defineProperty(exports, "__esModule", {
@@ -163,18 +163,18 @@
const _react = /*#__PURE__*/ _interop_require_default._(
__webpack_require__(6408)
);
- const _resolvehref = __webpack_require__(2381);
- const _islocalurl = __webpack_require__(952);
- const _formaturl = __webpack_require__(8919);
- const _utils = __webpack_require__(3149);
- const _addlocale = __webpack_require__(513);
- const _routercontextsharedruntime = __webpack_require__(8275);
- const _approutercontextsharedruntime = __webpack_require__(91);
- const _useintersection = __webpack_require__(3065);
- const _getdomainlocale = __webpack_require__(8909);
- const _addbasepath = __webpack_require__(9887);
- const _routerreducertypes = __webpack_require__(9298);
- const _usemergedref = __webpack_require__(1261);
+ const _resolvehref = __webpack_require__(2772);
+ const _islocalurl = __webpack_require__(6335);
+ const _formaturl = __webpack_require__(4997);
+ const _utils = __webpack_require__(8346);
+ const _addlocale = __webpack_require__(1365);
+ const _routercontextsharedruntime = __webpack_require__(9562);
+ const _approutercontextsharedruntime = __webpack_require__(6269);
+ const _useintersection = __webpack_require__(2610);
+ const _getdomainlocale = __webpack_require__(2876);
+ const _addbasepath = __webpack_require__(9513);
+ const _routerreducertypes = __webpack_require__(9580);
+ const _usemergedref = __webpack_require__(1057);
const prefetched = new Set();
function prefetch(router, href, as, options, appOptions, isAppRouter) {
if (false) {
@@ -184,11 +184,8 @@
return;
}
// We should only dedupe requests when experimental.optimisticClientCache is
- // disabled & when we're not using the app router. App router handles
- // reusing an existing prefetch entry (if it exists) for the same URL.
- // If we dedupe in here, we will cause a race where different prefetch kinds
- // to the same URL (ie auto vs true) will cause one to be ignored.
- if (!options.bypassPrefetchedCheck && !isAppRouter) {
+ // disabled.
+ if (!options.bypassPrefetchedCheck) {
const locale =
typeof options.locale !== "undefined"
? options.locale
@@ -602,7 +599,7 @@
/***/
},
- /***/ 3065: /***/ (module, exports, __webpack_require__) => {
+ /***/ 2610: /***/ (module, exports, __webpack_require__) => {
"use strict";
Object.defineProperty(exports, "__esModule", {
@@ -615,7 +612,7 @@
},
});
const _react = __webpack_require__(6408);
- const _requestidlecallback = __webpack_require__(5586);
+ const _requestidlecallback = __webpack_require__(7509);
const hasIntersectionObserver =
typeof IntersectionObserver === "function";
const observers = new Map();
@@ -728,7 +725,7 @@
/***/
},
- /***/ 1261: /***/ (module, exports, __webpack_require__) => {
+ /***/ 1057: /***/ (module, exports, __webpack_require__) => {
"use strict";
Object.defineProperty(exports, "__esModule", {
@@ -797,7 +794,7 @@
/***/
},
- /***/ 484: /***/ (
+ /***/ 7234: /***/ (
__unused_webpack_module,
__webpack_exports__,
__webpack_require__
@@ -812,7 +809,7 @@
/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_0__ =
__webpack_require__(3262);
/* harmony import */ var next_link__WEBPACK_IMPORTED_MODULE_1__ =
- __webpack_require__(9758);
+ __webpack_require__(6065);
/* harmony import */ var next_link__WEBPACK_IMPORTED_MODULE_1___default =
/*#__PURE__*/ __webpack_require__.n(
next_link__WEBPACK_IMPORTED_MODULE_1__
@@ -843,12 +840,12 @@
/***/
},
- /***/ 9758: /***/ (
+ /***/ 6065: /***/ (
module,
__unused_webpack_exports,
__webpack_require__
) => {
- module.exports = __webpack_require__(4300);
+ module.exports = __webpack_require__(8612);
/***/
},
@@ -858,7 +855,7 @@
/******/ var __webpack_exec__ = (moduleId) =>
__webpack_require__((__webpack_require__.s = moduleId));
/******/ __webpack_require__.O(0, [2888, 9774, 179], () =>
- __webpack_exec__(3809)
+ __webpack_exec__(9251)
);
/******/ var __webpack_exports__ = __webpack_require__.O();
/******/ _N_E = __webpack_exports__;
Diff for 124-HASH.js
Diff too large to display
Diff for main-HASH.js
Diff too large to display
Diff for app-page-exp..ntime.dev.js
Diff too large to display
Diff for app-page-exp..time.prod.js
Diff too large to display
Diff for app-page-tur..time.prod.js
Diff too large to display
Diff for app-page-tur..time.prod.js
Diff too large to display
Diff for app-page.runtime.dev.js
Diff too large to display
Diff for app-page.runtime.prod.js
Diff too large to display
Diff for app-route-ex..ntime.dev.js
Diff too large to display
Diff for app-route-ex..time.prod.js
Diff too large to display
Diff for app-route-tu..time.prod.js
Diff too large to display
Diff for app-route-tu..time.prod.js
Diff too large to display
Diff for app-route.runtime.dev.js
Diff too large to display
Diff for app-route.ru..time.prod.js
Diff too large to display
Diff for server.runtime.prod.js
Diff too large to display
2066bd4
to
ed009c9
Compare
6829cdb
to
4c35e33
Compare
ed009c9
to
4a8763c
Compare
4c35e33
to
6d0038c
Compare
4a8763c
to
721339d
Compare
6d0038c
to
0f642ea
Compare
721339d
to
c21386d
Compare
0f642ea
to
a074bba
Compare
c21386d
to
2a4edcc
Compare
a074bba
to
c5335d0
Compare
2a4edcc
to
d86f16a
Compare
c5335d0
to
b6b69ad
Compare
d86f16a
to
6ae2031
Compare
b6b69ad
to
d7b7c7d
Compare
6ae2031
to
079c5a6
Compare
d7b7c7d
to
4d5f231
Compare
079c5a6
to
41e443f
Compare
4d5f231
to
5614a2e
Compare
41e443f
to
56105d6
Compare
5614a2e
to
751297e
Compare
56105d6
to
17b7395
Compare
751297e
to
4f1b5b8
Compare
17b7395
to
2f95c61
Compare
4f1b5b8
to
a9dc67c
Compare
2f95c61
to
0bb50f8
Compare
a9dc67c
to
79c95fa
Compare
0bb50f8
to
dcab3e5
Compare
79c95fa
to
8efe900
Compare
dcab3e5
to
d34eb53
Compare
8efe900
to
b713ed0
Compare
What?
Restructure
server/web/adapter
'swaitUntil
implementation to handlewaitUntil
calls that happen late in a streaming response, afteradapter
exits.Why?
In the previous PR, we dealt with making sure that
server/web/adapter
always properly collects promises passed to its "fake"waitUntil
into theFetchEventResult
it returns. However, that implementation still has one issue.The way
adapter
handledwaitUntil
(i.e. a simple Promise.all of promises passed to it) means that if awaitUntil
call occurs afteradapter
returns, it won't get included in the result! This can happen if the response is streaming andwaitUntil
is called after a delay -- see the test introduced in the first PR of this stack.How?
We solve this problem via a combination of two things:
NextFetchEvent.waitUntil
to use anAwaiterOnce
(which was originally introduced in the first PR).awaiter.waitUntil
allows promises passed to it to recursively callwaitUntil
. which we use by...event.waitUntil(new Promise((resolve) => res.onClose(resolve)))
, which means that the Awaiter will stay "open" at least until the response is finished, so anywaitUntil
calls that happen during render will also be picked up.This is... definitely not ideal. But I don't see any other way to fix this without restructuring
adapter
(and the corresponding code in the vercel builder ) to remove theFetchEventResult.waitUntil
promise completely, and just let the handler callwaitUntil
directly. But that kind of change is a bit difficult to coordinate, so I think we should do this workaround for now, and do the larger refactor as a follow-up.